Fixed the healing code
This commit is contained in:
parent
0d65d57219
commit
b19fd441f8
9 changed files with 486 additions and 96 deletions
14
build.gradle
14
build.gradle
|
@ -104,16 +104,6 @@ repositories {
|
||||||
// }
|
// }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
maven {
|
|
||||||
// location of the maven that hosts JEI files
|
|
||||||
name = "Progwml6 maven"
|
|
||||||
url = "https://dvs1.progwml6.com/files/maven/"
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
// location of a maven mirror for JEI files, as a fallback
|
|
||||||
name = "ModMaven"
|
|
||||||
url = "https://modmaven.dev"
|
|
||||||
}
|
|
||||||
maven {
|
maven {
|
||||||
name = "CurseMaven"
|
name = "CurseMaven"
|
||||||
url = "https://cursemaven.com"
|
url = "https://cursemaven.com"
|
||||||
|
@ -131,10 +121,6 @@ dependencies {
|
||||||
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
|
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
|
||||||
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
||||||
|
|
||||||
compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")
|
|
||||||
compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}")
|
|
||||||
runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}")
|
|
||||||
|
|
||||||
implementation fg.deobf("dev.zontreck:libzontreck:${libz_version}:dev")
|
implementation fg.deobf("dev.zontreck:libzontreck:${libz_version}:dev")
|
||||||
compileOnly fg.deobf("dev.zontreck:libzontreck:${libz_version}:dev")
|
compileOnly fg.deobf("dev.zontreck:libzontreck:${libz_version}:dev")
|
||||||
runtimeOnly fg.deobf("dev.zontreck:libzontreck:${libz_version}")
|
runtimeOnly fg.deobf("dev.zontreck:libzontreck:${libz_version}")
|
||||||
|
|
|
@ -7,5 +7,4 @@ my_version=1.3.4.4
|
||||||
|
|
||||||
mc_version=1.19.2
|
mc_version=1.19.2
|
||||||
forge_version=43.1.40
|
forge_version=43.1.40
|
||||||
jei_version=11.3.0.271
|
|
||||||
libz_version=1.0.1.2
|
libz_version=1.0.1.2
|
|
@ -69,7 +69,7 @@ public class OTEMod
|
||||||
public static Map<String,Profile> PROFILES = new HashMap<String,Profile>();
|
public static Map<String,Profile> PROFILES = new HashMap<String,Profile>();
|
||||||
public static List<TeleportContainer> TeleportRegistry = new ArrayList<>();
|
public static List<TeleportContainer> TeleportRegistry = new ArrayList<>();
|
||||||
public static MinecraftServer THE_SERVER;
|
public static MinecraftServer THE_SERVER;
|
||||||
public static boolean ALIVE;
|
public static boolean ALIVE=false;
|
||||||
public static boolean HEALER_WAIT=true; // Only on loading finish should this unlock
|
public static boolean HEALER_WAIT=true; // Only on loading finish should this unlock
|
||||||
public static Thread HEALER_THREAD;
|
public static Thread HEALER_THREAD;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package dev.zontreck.otemod.antigrief;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import dev.zontreck.libzontreck.vectors.Vector3;
|
import dev.zontreck.libzontreck.vectors.Vector3;
|
||||||
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
||||||
|
@ -60,7 +61,7 @@ public class Handler
|
||||||
if(exploder==null)return ; // TODO: Make this check config
|
if(exploder==null)return ; // TODO: Make this check config
|
||||||
|
|
||||||
final Collection<StoredBlock> affectedBlocks = buildBlocks(level, event.getAffectedBlocks());
|
final Collection<StoredBlock> affectedBlocks = buildBlocks(level, event.getAffectedBlocks());
|
||||||
final Collection<StoredBlock> toHeal = new ArrayList<StoredBlock>(affectedBlocks.size());
|
Collection<StoredBlock> toHeal = new ArrayList<StoredBlock>(affectedBlocks.size());
|
||||||
|
|
||||||
Block tnt = Blocks.TNT;
|
Block tnt = Blocks.TNT;
|
||||||
|
|
||||||
|
@ -96,7 +97,22 @@ public class Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to the healing queue
|
// Add to the healing queue
|
||||||
HealerQueue.ToHeal.addAll(toHeal);
|
List<StoredBlock> mainList = new ArrayList<>();
|
||||||
|
mainList.addAll(toHeal);
|
||||||
|
mainList = HealerQueue.removeSame(mainList);
|
||||||
|
|
||||||
|
HealerWorker work = new HealerWorker(mainList);
|
||||||
|
HealerQueue.ManagerInstance.registerWorker(work);
|
||||||
|
Thread tx = new Thread(work);
|
||||||
|
tx.start();
|
||||||
|
|
||||||
|
HealerQueue.ToHeal.addAll(mainList);
|
||||||
|
|
||||||
|
|
||||||
|
HealerQueue.Pass=0;
|
||||||
|
HealerQueue.ToHeal.addAll(HealerQueue.ToValidate);
|
||||||
|
HealerQueue.ToValidate = new ArrayList<>();
|
||||||
|
|
||||||
HealerQueue.Shuffle();
|
HealerQueue.Shuffle();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
72
src/main/java/dev/zontreck/otemod/antigrief/HealRunner.java
Normal file
72
src/main/java/dev/zontreck/otemod/antigrief/HealRunner.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
package dev.zontreck.otemod.antigrief;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import dev.zontreck.libzontreck.vectors.Vector3;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.sounds.SoundEvent;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public class HealRunner implements Runnable
|
||||||
|
{
|
||||||
|
public final StoredBlock BlockToSet;
|
||||||
|
// Play a popping sound at the block position
|
||||||
|
public final SoundEvent pop = SoundEvents.ITEM_PICKUP;
|
||||||
|
|
||||||
|
|
||||||
|
public HealRunner(StoredBlock sb)
|
||||||
|
{
|
||||||
|
BlockToSet = sb;
|
||||||
|
}
|
||||||
|
public static void scheduleHeal(StoredBlock sb){
|
||||||
|
sb.getWorldPosition().getActualDimension().getServer().execute(new HealRunner(sb));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
|
||||||
|
//BlockSnapshot bs = BlockSnapshot.create(level.dimension(), level, sb.getPos());
|
||||||
|
|
||||||
|
//BlockState current = level.getBlockState(sb.getPos());
|
||||||
|
final ServerLevel level = BlockToSet.getWorldPosition().getActualDimension();
|
||||||
|
|
||||||
|
BlockState nState = Block.updateFromNeighbourShapes(BlockToSet.getState(), level, BlockToSet.getPos());
|
||||||
|
level.setBlock(BlockToSet.getPos(), nState, Block.UPDATE_CLIENTS); // no update?
|
||||||
|
|
||||||
|
|
||||||
|
//level.setBlocksDirty(sb.getPos(), sb.getState(), level.getBlockState(sb.getPos()));
|
||||||
|
//level.markAndNotifyBlock(sb.getPos(), level.getChunkAt(sb.getPos()), sb.getState(), level.getBlockState(sb.getPos()), 2, 0);
|
||||||
|
|
||||||
|
//level.getChunkAt(sb.getPos()).setBlockState(sb.getPos(), sb.getState(), false);
|
||||||
|
|
||||||
|
BlockEntity be = level.getBlockEntity(BlockToSet.getPos());
|
||||||
|
|
||||||
|
if(be!=null){
|
||||||
|
//be.deserializeNBT(sb.getBlockEntity());
|
||||||
|
be.load(BlockToSet.getBlockEntity());
|
||||||
|
be.setChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything is restored, play sound
|
||||||
|
SoundSource ss = SoundSource.NEUTRAL;
|
||||||
|
Vector3 v3 = BlockToSet.getWorldPosition().Position;
|
||||||
|
Random rng = new Random();
|
||||||
|
|
||||||
|
level.playSound(null, v3.asBlockPos(), pop, ss, rng.nextFloat(0.75f,1.0f), rng.nextFloat(1));
|
||||||
|
|
||||||
|
/*for(ServerPlayer player : level.players())
|
||||||
|
{
|
||||||
|
Vector3 playerPos = new Vector3(player.position());
|
||||||
|
if(sb.getWorldPosition().Position.distance(playerPos) < 15)
|
||||||
|
{
|
||||||
|
// have player's client play sound (Packet?)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,12 @@ package dev.zontreck.otemod.antigrief;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import dev.zontreck.libzontreck.vectors.Vector3;
|
import dev.zontreck.libzontreck.vectors.Vector3;
|
||||||
|
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
||||||
import dev.zontreck.otemod.OTEMod;
|
import dev.zontreck.otemod.OTEMod;
|
||||||
import dev.zontreck.otemod.configs.OTEServerConfig;
|
import dev.zontreck.otemod.configs.OTEServerConfig;
|
||||||
import net.minecraft.server.commands.SetBlockCommand;
|
import net.minecraft.server.commands.SetBlockCommand;
|
||||||
|
@ -15,6 +18,7 @@ import net.minecraft.sounds.SoundEvents;
|
||||||
import net.minecraft.sounds.SoundSource;
|
import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.world.entity.item.FallingBlockEntity;
|
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.FallingBlock;
|
import net.minecraft.world.level.block.FallingBlock;
|
||||||
import net.minecraft.world.level.block.SandBlock;
|
import net.minecraft.world.level.block.SandBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
@ -23,8 +27,18 @@ import net.minecraftforge.common.util.BlockSnapshot;
|
||||||
|
|
||||||
public class HealerManager implements Runnable
|
public class HealerManager implements Runnable
|
||||||
{
|
{
|
||||||
|
private List<HealerWorker> Workers = new ArrayList<>();
|
||||||
public HealerManager(){
|
public HealerManager(){
|
||||||
|
|
||||||
|
}
|
||||||
|
public void registerWorker(HealerWorker worker)
|
||||||
|
{
|
||||||
|
Workers.add(worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deregisterWorker(HealerWorker worker)
|
||||||
|
{
|
||||||
|
Workers.remove(worker);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void run(){
|
public void run(){
|
||||||
|
@ -33,34 +47,159 @@ public class HealerManager implements Runnable
|
||||||
long lastSave = 0;
|
long lastSave = 0;
|
||||||
final long saveInterval = (2*60); // Every 2 minutes
|
final long saveInterval = (2*60); // Every 2 minutes
|
||||||
boolean lastWait = false;
|
boolean lastWait = false;
|
||||||
|
// Heal pass 1 is set all positions to bedrock
|
||||||
|
// Pass 2 is assert all solid blocks (Not air)
|
||||||
|
// Pass 3 is to set the air blocks and remove bedrock
|
||||||
|
|
||||||
|
|
||||||
while(OTEMod.ALIVE)
|
while(OTEMod.ALIVE)
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
// Run the queue
|
try{
|
||||||
// We want to restore one block per run, then halt for number of seconds in config
|
if(!skipWait) Thread.sleep(OTEServerConfig.HEALER_TIMER.get());
|
||||||
try {
|
}catch(Exception E){}
|
||||||
if(!skipWait)
|
|
||||||
Thread.sleep(OTEServerConfig.HEALER_TIMER.get());
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if(lastWait != OTEMod.HEALER_WAIT){
|
|
||||||
OTEMod.LOGGER.info("Healer wait flag was toggled");
|
|
||||||
}
|
|
||||||
lastWait = OTEMod.HEALER_WAIT;
|
|
||||||
if(OTEMod.HEALER_WAIT)
|
|
||||||
continue; // Wait until the saved queue has been fully imported
|
|
||||||
|
|
||||||
if(!OTEMod.ALIVE)
|
if(lastWait != OTEMod.HEALER_WAIT) OTEMod.LOGGER.info("Healer Wait Flag was Toggled");
|
||||||
{
|
lastWait = OTEMod.HEALER_WAIT;
|
||||||
// Server has begun to shut down while we were sleeping
|
if(OTEMod.HEALER_WAIT) continue; // Wait to process until import completes
|
||||||
// Begin tear down
|
|
||||||
break;
|
if(!OTEMod.ALIVE) break; // Begin tear down, server has shut down
|
||||||
|
|
||||||
|
for (HealerWorker healerWorker : Workers) {
|
||||||
|
healerWorker.doTick=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(HealerQueue.ToHeal.size()==0 && HealerQueue.ToValidate.size()==0)
|
||||||
|
{
|
||||||
|
HealerQueue.Pass=0;
|
||||||
|
if(HealerQueue.dirty())
|
||||||
|
HealerQueue.dump();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the first block in the list
|
||||||
|
final StoredBlock sb = HealerQueue.locateLowestBlock(HealerQueue.ToHeal);
|
||||||
|
ServerLevel level = null;
|
||||||
|
StoredBlock below = null;
|
||||||
|
|
||||||
|
if(sb != null)
|
||||||
|
{
|
||||||
|
level = sb.getWorldPosition().getActualDimension();
|
||||||
|
below = HealerQueue.getExact(new WorldPosition(sb.getWorldPosition().Position.moveDown(), level));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch(HealerQueue.Pass)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// Pass 1. Set all positions to bedrock
|
||||||
|
// The code will check is the block is solid. If the block below it is not solid, it will set it to air, regardless of if it is a falling block of not
|
||||||
|
|
||||||
|
if(HealerQueue.ToHeal.size()==0)
|
||||||
|
{
|
||||||
|
// Move the validate list back into healer queue, and increment pass
|
||||||
|
OTEMod.LOGGER.info("Pass 1 completed, moving to pass 2");
|
||||||
|
HealerQueue.Pass=1;
|
||||||
|
HealerQueue.ToHeal = HealerQueue.ToValidate;
|
||||||
|
HealerQueue.ToValidate = new ArrayList<>();
|
||||||
|
HealerQueue.dump();
|
||||||
|
break; // Exit this loop
|
||||||
|
}
|
||||||
|
|
||||||
|
if(below == null){
|
||||||
|
// This line will prevent the block below from getting set to Sculk
|
||||||
|
below = StoredBlock.getSculk(new WorldPosition(sb.getWorldPosition().Position.moveDown(), level)); // below is null so it is a unknown, accept a loss if its a falling block
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!sb.getState().isAir() && below.getState().isAir())
|
||||||
|
{
|
||||||
|
HealRunner.scheduleHeal(StoredBlock.getSculk(below.getWorldPosition()));
|
||||||
|
skipWait=false;
|
||||||
|
}else {
|
||||||
|
if(!sb.getState().isAir())
|
||||||
|
{
|
||||||
|
HealRunner.scheduleHeal(StoredBlock.getSculk(sb.getWorldPosition()));
|
||||||
|
skipWait=false;
|
||||||
|
} else {
|
||||||
|
skipWait=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HealerQueue.ToValidate.add(sb);
|
||||||
|
HealerQueue.ToHeal.remove(sb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// Pass 2 only sets the solid blocks
|
||||||
|
if(HealerQueue.ToHeal.size()==0)
|
||||||
|
{
|
||||||
|
OTEMod.LOGGER.info("Pass 2 completed, moving to pass 3");
|
||||||
|
HealerQueue.Pass++;
|
||||||
|
HealerQueue.ToHeal = HealerQueue.ToValidate;
|
||||||
|
HealerQueue.ToValidate = new ArrayList<>();
|
||||||
|
HealerQueue.dump();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!sb.getState().isAir())
|
||||||
|
{
|
||||||
|
skipWait=false;
|
||||||
|
HealRunner.scheduleHeal(sb);
|
||||||
|
}else{
|
||||||
|
skipWait=true;
|
||||||
|
|
||||||
|
HealerQueue.ToValidate.add(sb);
|
||||||
|
}
|
||||||
|
HealerQueue.ToHeal.remove(sb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// Pass 3 removes bedrock by setting blocks that are air
|
||||||
|
if(HealerQueue.ToHeal.size()==0)
|
||||||
|
{
|
||||||
|
OTEMod.LOGGER.info("Pass 3 has been completed. Ending restore");
|
||||||
|
HealerQueue.Pass=0;
|
||||||
|
HealerQueue.ToHeal.clear();
|
||||||
|
HealerQueue.ToValidate.clear();
|
||||||
|
HealerQueue.dump();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HealerQueue.ToHeal.remove(sb);
|
||||||
|
|
||||||
|
if(sb.getState().isAir())
|
||||||
|
{
|
||||||
|
BlockState bs = sb.getWorldPosition().getActualDimension().getBlockState(sb.getPos());
|
||||||
|
if(!bs.isAir() && !bs.is(Blocks.SCULK))
|
||||||
|
{
|
||||||
|
skipWait=true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!bs.isAir()){
|
||||||
|
skipWait=false;
|
||||||
|
HealRunner.scheduleHeal(sb);
|
||||||
|
}else skipWait=true;
|
||||||
|
}else skipWait=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
HealerQueue.Pass=0;
|
||||||
|
OTEMod.LOGGER.info("/!\\ ALERT /!\\\n\nWARNING: Unknown pass operation was added to the HealQueue");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(Exception e){}
|
||||||
|
}
|
||||||
|
OTEMod.ALIVE=false;
|
||||||
|
/*while(OTEMod.ALIVE) // do nothing, code is disabled here.
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
|
||||||
// Loop back to start if no items in queue
|
// Loop back to start if no items in queue
|
||||||
if(HealerQueue.ToHeal.size()==0){
|
if(HealerQueue.ToHeal.size()==0){
|
||||||
|
|
||||||
|
@ -94,13 +233,10 @@ public class HealerManager implements Runnable
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play a popping sound at the block position
|
|
||||||
final SoundEvent pop = SoundEvents.ITEM_PICKUP;
|
|
||||||
// Get the first block in the list
|
// Get the first block in the list
|
||||||
final StoredBlock sb = HealerQueue.locateHighestBlock(HealerQueue.ToHeal);
|
final StoredBlock sb = HealerQueue.locateHighestBlock(HealerQueue.ToHeal);
|
||||||
final ServerLevel level = sb.getWorldPosition().getActualDimension();
|
final ServerLevel level = sb.getWorldPosition().getActualDimension();
|
||||||
|
|
||||||
|
|
||||||
// Remove the block from the queue now to prevent further issues
|
// Remove the block from the queue now to prevent further issues
|
||||||
if( !HealerQueue.ToValidate.add(sb) )
|
if( !HealerQueue.ToValidate.add(sb) )
|
||||||
{
|
{
|
||||||
|
@ -128,53 +264,6 @@ public class HealerManager implements Runnable
|
||||||
skipCount++;
|
skipCount++;
|
||||||
}
|
}
|
||||||
}else skipCount=0;
|
}else skipCount=0;
|
||||||
|
|
||||||
|
|
||||||
level.getServer().execute(new Runnable(){
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
|
|
||||||
//BlockSnapshot bs = BlockSnapshot.create(level.dimension(), level, sb.getPos());
|
|
||||||
|
|
||||||
//BlockState current = level.getBlockState(sb.getPos());
|
|
||||||
BlockState nState = Block.updateFromNeighbourShapes(sb.getState(), level, sb.getPos());
|
|
||||||
level.setBlock(sb.getPos(), nState, Block.UPDATE_CLIENTS | Block.UPDATE_KNOWN_SHAPE); // no update?
|
|
||||||
|
|
||||||
|
|
||||||
//level.setBlocksDirty(sb.getPos(), sb.getState(), level.getBlockState(sb.getPos()));
|
|
||||||
//level.markAndNotifyBlock(sb.getPos(), level.getChunkAt(sb.getPos()), sb.getState(), level.getBlockState(sb.getPos()), 2, 0);
|
|
||||||
|
|
||||||
//level.getChunkAt(sb.getPos()).setBlockState(sb.getPos(), sb.getState(), false);
|
|
||||||
|
|
||||||
BlockEntity be = level.getBlockEntity(sb.getPos());
|
|
||||||
|
|
||||||
if(be!=null){
|
|
||||||
//be.deserializeNBT(sb.getBlockEntity());
|
|
||||||
be.load(sb.getBlockEntity());
|
|
||||||
be.setChanged();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everything is restored, play sound
|
|
||||||
SoundSource ss = SoundSource.NEUTRAL;
|
|
||||||
Vector3 v3 = sb.getWorldPosition().Position;
|
|
||||||
Random rng = new Random();
|
|
||||||
|
|
||||||
level.playSound(null, v3.asBlockPos(), pop, ss, rng.nextFloat(0.75f,1.0f), rng.nextFloat(1));
|
|
||||||
|
|
||||||
/*for(ServerPlayer player : level.players())
|
|
||||||
{
|
|
||||||
Vector3 playerPos = new Vector3(player.position());
|
|
||||||
if(sb.getWorldPosition().Position.distance(playerPos) < 15)
|
|
||||||
{
|
|
||||||
// have player's client play sound (Packet?)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,7 +286,7 @@ public class HealerManager implements Runnable
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}*/
|
||||||
|
|
||||||
OTEMod.LOGGER.info("Tearing down healer jobs. Saving remaining queue, stand by...");
|
OTEMod.LOGGER.info("Tearing down healer jobs. Saving remaining queue, stand by...");
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -31,10 +31,18 @@ public class HealerQueue {
|
||||||
public static final String HealerQueueFile = "OTEHealerLastQueue.nbt";
|
public static final String HealerQueueFile = "OTEHealerLastQueue.nbt";
|
||||||
public static final String HealerQueueDebugFile = "OTEHealerLastQueue.snbt";
|
public static final String HealerQueueDebugFile = "OTEHealerLastQueue.snbt";
|
||||||
|
|
||||||
public static List<StoredBlock> ToHeal = new ArrayList<StoredBlock>();
|
public static List<StoredBlock> ToHeal = new ArrayList<StoredBlock>(); // Air and Solid Blocks get set to bedrock initially
|
||||||
public static List<StoredBlock> ToValidate = new ArrayList<StoredBlock>();
|
public static List<StoredBlock> ToValidate = new ArrayList<StoredBlock>(); // This contains all the blocks except air
|
||||||
public static List<StoredBlock> FinishedBlocks = new ArrayList<StoredBlock>();
|
|
||||||
|
|
||||||
|
public static int Pass = 0;
|
||||||
|
|
||||||
|
|
||||||
|
private static List<StoredBlock> LastToHeal = new ArrayList<StoredBlock>();
|
||||||
|
private static List<StoredBlock> LastToValidate = new ArrayList<StoredBlock>();
|
||||||
|
private static int LastPass = 0;
|
||||||
|
|
||||||
|
public static HealerManager ManagerInstance=null;
|
||||||
|
|
||||||
|
|
||||||
public static Path getPath()
|
public static Path getPath()
|
||||||
{
|
{
|
||||||
|
@ -68,6 +76,40 @@ public class HealerQueue {
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StoredBlock locateLowestBlock(List<StoredBlock> list)
|
||||||
|
{
|
||||||
|
StoredBlock sb = null;
|
||||||
|
double currentY = 300;
|
||||||
|
for (StoredBlock storedBlock : ToHeal) {
|
||||||
|
if(storedBlock.getWorldPosition().Position.y < currentY)
|
||||||
|
{
|
||||||
|
currentY = storedBlock.getWorldPosition().Position.y;
|
||||||
|
sb=storedBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StoredBlock getExact(WorldPosition wp)
|
||||||
|
{
|
||||||
|
for (StoredBlock storedBlock : ToHeal) {
|
||||||
|
if(storedBlock.getWorldPosition().same(wp))
|
||||||
|
{
|
||||||
|
return storedBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (StoredBlock storedBlock : ToValidate) {
|
||||||
|
if(storedBlock.getWorldPosition().same(wp))
|
||||||
|
{
|
||||||
|
return storedBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean HasValidatePosition(BlockPos pos, ServerLevel lvl)
|
public static boolean HasValidatePosition(BlockPos pos, ServerLevel lvl)
|
||||||
{
|
{
|
||||||
Vector3 realPos = new Vector3(pos);
|
Vector3 realPos = new Vector3(pos);
|
||||||
|
@ -134,7 +176,8 @@ public class HealerQueue {
|
||||||
tx.start();
|
tx.start();
|
||||||
|
|
||||||
// Set up the HealerManager / Runner
|
// Set up the HealerManager / Runner
|
||||||
Thread txx = new Thread(new HealerManager());
|
ManagerInstance = new HealerManager();
|
||||||
|
Thread txx = new Thread(ManagerInstance);
|
||||||
txx.start();
|
txx.start();
|
||||||
|
|
||||||
OTEMod.HEALER_THREAD = txx;
|
OTEMod.HEALER_THREAD = txx;
|
||||||
|
@ -157,6 +200,7 @@ public class HealerQueue {
|
||||||
|
|
||||||
tag.put("queue", lst);
|
tag.put("queue", lst);
|
||||||
tag.put("validate", lst2);
|
tag.put("validate", lst2);
|
||||||
|
tag.putInt("pass", HealerQueue.Pass);
|
||||||
|
|
||||||
//OTEMod.LOGGER.info("HEAL ["+HealerQueue.ToHeal.size()+"] / VALIDATE ["+HealerQueue.ToValidate.size()+"]");
|
//OTEMod.LOGGER.info("HEAL ["+HealerQueue.ToHeal.size()+"] / VALIDATE ["+HealerQueue.ToValidate.size()+"]");
|
||||||
|
|
||||||
|
@ -165,6 +209,48 @@ public class HealerQueue {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<StoredBlock> removeSame(List<StoredBlock> other)
|
||||||
|
{
|
||||||
|
other=removeSameFrom(ToHeal, other);
|
||||||
|
other=removeSameFrom(ToValidate,other);
|
||||||
|
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<StoredBlock> removeSameFrom(List<StoredBlock> stored, List<StoredBlock> other)
|
||||||
|
{
|
||||||
|
|
||||||
|
for(int i = 0;i<stored.size();i++)
|
||||||
|
{
|
||||||
|
for(int x = 0;x<other.size();x++)
|
||||||
|
{
|
||||||
|
if(other.get(x).getWorldPosition().same(stored.get(i).getWorldPosition()))
|
||||||
|
{
|
||||||
|
// Both are same
|
||||||
|
other.remove(x);
|
||||||
|
x=-1; // Reset indexing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeExact(WorldPosition pos)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ToHeal.size(); i++) {
|
||||||
|
if(ToHeal.get(i).getWorldPosition().same(pos)){
|
||||||
|
ToHeal.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ToValidate.size(); i++) {
|
||||||
|
if(ToValidate.get(i).getWorldPosition().same(pos)){
|
||||||
|
ToValidate.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void deserialize(CompoundTag tag)
|
public static void deserialize(CompoundTag tag)
|
||||||
{
|
{
|
||||||
OTEMod.HEALER_WAIT=true;
|
OTEMod.HEALER_WAIT=true;
|
||||||
|
@ -199,11 +285,25 @@ public class HealerQueue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HealerQueue.Pass = tag.getInt("pass");
|
||||||
|
|
||||||
OTEMod.LOGGER.info("Finished loading validation queue for healer ["+HealerQueue.ToValidate.size()+"] items");
|
OTEMod.LOGGER.info("Finished loading validation queue for healer ["+HealerQueue.ToValidate.size()+"] items");
|
||||||
OTEMod.HEALER_WAIT=false;
|
OTEMod.HEALER_WAIT=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean dirty()
|
||||||
|
{
|
||||||
|
if(ToHeal!=LastToHeal)return true;
|
||||||
|
if(ToValidate!=LastToValidate)return true;
|
||||||
|
if(Pass != LastPass)return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static void dump() throws IOException
|
public static void dump() throws IOException
|
||||||
{
|
{
|
||||||
|
LastToHeal = ToHeal;
|
||||||
|
LastToValidate = ToValidate;
|
||||||
|
LastPass = Pass;
|
||||||
CompoundTag serialized = HealerQueue.serialize();
|
CompoundTag serialized = HealerQueue.serialize();
|
||||||
if(OTEServerConfig.DEBUG_HEALER.get())
|
if(OTEServerConfig.DEBUG_HEALER.get())
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package dev.zontreck.otemod.antigrief;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
|
import dev.zontreck.otemod.OTEMod;
|
||||||
|
|
||||||
|
public class HealerWorker implements Runnable
|
||||||
|
{
|
||||||
|
private final List<StoredBlock> proc;
|
||||||
|
public boolean alive=false; // These are the
|
||||||
|
public boolean doTick = false;
|
||||||
|
public Thread MyThread;
|
||||||
|
public HealerWorker(List<StoredBlock> toProcess)
|
||||||
|
{
|
||||||
|
// TODO: Make this a individualized heal worker that does the task of the current HealerManager, but with a central list of positions for de-duplication. But that a second worker would not process the same positions
|
||||||
|
// The goal is to have a worker so a second explosion elsewhere does not reset the entire thing
|
||||||
|
for (StoredBlock sBlock : toProcess) {
|
||||||
|
if(!sBlock.claimed()) // Checks if a thread has been set on this storage block yet or not. This data does not get serialized.
|
||||||
|
sBlock.setClaimed(); // We are not yet in a new thread but we know we will be soon.
|
||||||
|
}
|
||||||
|
proc = toProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
MyThread=Thread.currentThread();
|
||||||
|
HealerQueue.ManagerInstance.registerWorker(this);
|
||||||
|
for (StoredBlock storedBlock : proc) {
|
||||||
|
storedBlock.setClaimedBy(Thread.currentThread());
|
||||||
|
}
|
||||||
|
|
||||||
|
while(alive){
|
||||||
|
// Stay alive
|
||||||
|
// The tick event will be fired when appropriate
|
||||||
|
if(doTick)tick();
|
||||||
|
|
||||||
|
|
||||||
|
doTick=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OTEMod.LOGGER.info(Thread.currentThread().getName()+" has completed healing an area. Worker is now dismantling");
|
||||||
|
|
||||||
|
HealerQueue.ManagerInstance.deregisterWorker(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
// A tick in the healer worker tells it to repair a block
|
||||||
|
// The healer manager is responsible for dispatching ticks
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.zontreck.otemod.antigrief;
|
package dev.zontreck.otemod.antigrief;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
|
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
|
||||||
import dev.zontreck.libzontreck.vectors.Vector3;
|
import dev.zontreck.libzontreck.vectors.Vector3;
|
||||||
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
||||||
|
@ -8,17 +10,73 @@ import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
public class StoredBlock {
|
public class StoredBlock implements Comparable
|
||||||
|
{
|
||||||
|
|
||||||
|
public static final StoredBlock getBedrock(WorldPosition pos){
|
||||||
|
StoredBlock sb = new StoredBlock(pos.Position.asBlockPos(), Blocks.BEDROCK.defaultBlockState(), pos.getActualDimension());
|
||||||
|
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
public static final StoredBlock getAir(WorldPosition pos){
|
||||||
|
StoredBlock sb = new StoredBlock(pos.Position.asBlockPos(), Blocks.AIR.defaultBlockState(), pos.getActualDimension());
|
||||||
|
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final StoredBlock getSculk(WorldPosition pos){
|
||||||
|
StoredBlock sb = new StoredBlock(pos.Position.asBlockPos(), Blocks.SCULK.defaultBlockState() ,pos.getActualDimension());
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static final int UNSET = 0;
|
||||||
|
public static final int PHASE1 = 1;
|
||||||
|
public static final int PHASE2 = 2;
|
||||||
|
public static final int PHSAE3 = 4;
|
||||||
|
|
||||||
public CompoundTag blockData;
|
public CompoundTag blockData;
|
||||||
|
|
||||||
private WorldPosition position;
|
private WorldPosition position;
|
||||||
private BlockState state;
|
private BlockState state;
|
||||||
|
|
||||||
private CompoundTag blockEntity;
|
private CompoundTag blockEntity;
|
||||||
|
|
||||||
|
private boolean claim = false;
|
||||||
|
private long claimed_at = 0;
|
||||||
|
private Thread claimed_by;
|
||||||
|
|
||||||
|
public void setClaimed()
|
||||||
|
{
|
||||||
|
claimed_at = Instant.now().getEpochSecond();
|
||||||
|
claim=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean claimed()
|
||||||
|
{
|
||||||
|
if(claimed_by == null)
|
||||||
|
{
|
||||||
|
if(claim)
|
||||||
|
{
|
||||||
|
if(Instant.now().getEpochSecond() > claimed_at+30)
|
||||||
|
{
|
||||||
|
claim=false;
|
||||||
|
claimed_at = 0; // The claim timed out as no thread was set
|
||||||
|
return false;
|
||||||
|
}else return true; // Temporary lock on claim
|
||||||
|
}else return false; // Not claimed
|
||||||
|
}else return true; // Permanent process lock
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClaimedBy(Thread tx){
|
||||||
|
claimed_by=tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public StoredBlock(final BlockPos pos, final BlockState toSave, final ServerLevel lvl)
|
public StoredBlock(final BlockPos pos, final BlockState toSave, final ServerLevel lvl)
|
||||||
{
|
{
|
||||||
position = new WorldPosition(new Vector3(pos), lvl);
|
position = new WorldPosition(new Vector3(pos), lvl);
|
||||||
|
@ -32,6 +90,7 @@ public class StoredBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public final BlockPos getPos()
|
public final BlockPos getPos()
|
||||||
{
|
{
|
||||||
return position.Position.asBlockPos();
|
return position.Position.asBlockPos();
|
||||||
|
@ -100,6 +159,21 @@ public class StoredBlock {
|
||||||
final CompoundTag tmp = tag.getCompound("entity");
|
final CompoundTag tmp = tag.getCompound("entity");
|
||||||
blockEntity = tmp.isEmpty() ? null : tmp;
|
blockEntity = tmp.isEmpty() ? null : tmp;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public int compareTo(Object o) {
|
||||||
|
if(o instanceof StoredBlock)
|
||||||
|
{
|
||||||
|
StoredBlock sb = (StoredBlock)o;
|
||||||
|
if(sb.position.same(position))
|
||||||
|
{
|
||||||
|
if(sb.state.equals(state))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}return -1;
|
||||||
|
}else return -1;
|
||||||
|
|
||||||
|
}return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue