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()
|
||||
|
||||
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 {
|
||||
name = "CurseMaven"
|
||||
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.
|
||||
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")
|
||||
compileOnly fg.deobf("dev.zontreck:libzontreck:${libz_version}:dev")
|
||||
runtimeOnly fg.deobf("dev.zontreck:libzontreck:${libz_version}")
|
||||
|
|
|
@ -7,5 +7,4 @@ my_version=1.3.4.4
|
|||
|
||||
mc_version=1.19.2
|
||||
forge_version=43.1.40
|
||||
jei_version=11.3.0.271
|
||||
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 List<TeleportContainer> TeleportRegistry = new ArrayList<>();
|
||||
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 Thread HEALER_THREAD;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.zontreck.otemod.antigrief;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.zontreck.libzontreck.vectors.Vector3;
|
||||
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
||||
|
@ -60,7 +61,7 @@ public class Handler
|
|||
if(exploder==null)return ; // TODO: Make this check config
|
||||
|
||||
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;
|
||||
|
||||
|
@ -96,7 +97,22 @@ public class Handler
|
|||
}
|
||||
|
||||
// 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();
|
||||
|
||||
}
|
||||
|
|
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.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import dev.zontreck.libzontreck.vectors.Vector3;
|
||||
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
||||
import dev.zontreck.otemod.OTEMod;
|
||||
import dev.zontreck.otemod.configs.OTEServerConfig;
|
||||
import net.minecraft.server.commands.SetBlockCommand;
|
||||
|
@ -15,6 +18,7 @@ import net.minecraft.sounds.SoundEvents;
|
|||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||||
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.SandBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
@ -23,8 +27,18 @@ import net.minecraftforge.common.util.BlockSnapshot;
|
|||
|
||||
public class HealerManager implements Runnable
|
||||
{
|
||||
private List<HealerWorker> Workers = new ArrayList<>();
|
||||
public HealerManager(){
|
||||
|
||||
}
|
||||
public void registerWorker(HealerWorker worker)
|
||||
{
|
||||
Workers.add(worker);
|
||||
}
|
||||
|
||||
public void deregisterWorker(HealerWorker worker)
|
||||
{
|
||||
Workers.remove(worker);
|
||||
}
|
||||
@Override
|
||||
public void run(){
|
||||
|
@ -33,33 +47,158 @@ public class HealerManager implements Runnable
|
|||
long lastSave = 0;
|
||||
final long saveInterval = (2*60); // Every 2 minutes
|
||||
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)
|
||||
{
|
||||
try{
|
||||
// Run the queue
|
||||
// We want to restore one block per run, then halt for number of seconds in config
|
||||
try{
|
||||
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(!skipWait) Thread.sleep(OTEServerConfig.HEALER_TIMER.get());
|
||||
}catch(Exception E){}
|
||||
|
||||
if(!OTEMod.ALIVE)
|
||||
if(lastWait != OTEMod.HEALER_WAIT) OTEMod.LOGGER.info("Healer Wait Flag was Toggled");
|
||||
lastWait = OTEMod.HEALER_WAIT;
|
||||
if(OTEMod.HEALER_WAIT) continue; // Wait to process until import completes
|
||||
|
||||
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)
|
||||
{
|
||||
// Server has begun to shut down while we were sleeping
|
||||
// Begin tear down
|
||||
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
|
||||
if(HealerQueue.ToHeal.size()==0){
|
||||
|
@ -94,13 +233,10 @@ public class HealerManager implements Runnable
|
|||
continue;
|
||||
}
|
||||
|
||||
// Play a popping sound at the block position
|
||||
final SoundEvent pop = SoundEvents.ITEM_PICKUP;
|
||||
// Get the first block in the list
|
||||
final StoredBlock sb = HealerQueue.locateHighestBlock(HealerQueue.ToHeal);
|
||||
final ServerLevel level = sb.getWorldPosition().getActualDimension();
|
||||
|
||||
|
||||
// Remove the block from the queue now to prevent further issues
|
||||
if( !HealerQueue.ToValidate.add(sb) )
|
||||
{
|
||||
|
@ -130,53 +266,6 @@ public class HealerManager implements Runnable
|
|||
}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?)
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
if(!skipWait) // Only save the queue when sleeping appropriately
|
||||
{
|
||||
|
@ -197,7 +286,7 @@ public class HealerManager implements Runnable
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
OTEMod.LOGGER.info("Tearing down healer jobs. Saving remaining queue, stand by...");
|
||||
try {
|
||||
|
|
|
@ -31,9 +31,17 @@ public class HealerQueue {
|
|||
public static final String HealerQueueFile = "OTEHealerLastQueue.nbt";
|
||||
public static final String HealerQueueDebugFile = "OTEHealerLastQueue.snbt";
|
||||
|
||||
public static List<StoredBlock> ToHeal = new ArrayList<StoredBlock>();
|
||||
public static List<StoredBlock> ToValidate = new ArrayList<StoredBlock>();
|
||||
public static List<StoredBlock> FinishedBlocks = 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>(); // This contains all the blocks except air
|
||||
|
||||
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()
|
||||
|
@ -68,6 +76,40 @@ public class HealerQueue {
|
|||
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)
|
||||
{
|
||||
Vector3 realPos = new Vector3(pos);
|
||||
|
@ -134,7 +176,8 @@ public class HealerQueue {
|
|||
tx.start();
|
||||
|
||||
// Set up the HealerManager / Runner
|
||||
Thread txx = new Thread(new HealerManager());
|
||||
ManagerInstance = new HealerManager();
|
||||
Thread txx = new Thread(ManagerInstance);
|
||||
txx.start();
|
||||
|
||||
OTEMod.HEALER_THREAD = txx;
|
||||
|
@ -157,6 +200,7 @@ public class HealerQueue {
|
|||
|
||||
tag.put("queue", lst);
|
||||
tag.put("validate", lst2);
|
||||
tag.putInt("pass", HealerQueue.Pass);
|
||||
|
||||
//OTEMod.LOGGER.info("HEAL ["+HealerQueue.ToHeal.size()+"] / VALIDATE ["+HealerQueue.ToValidate.size()+"]");
|
||||
|
||||
|
@ -165,6 +209,48 @@ public class HealerQueue {
|
|||
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)
|
||||
{
|
||||
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.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
|
||||
{
|
||||
LastToHeal = ToHeal;
|
||||
LastToValidate = ToValidate;
|
||||
LastPass = Pass;
|
||||
CompoundTag serialized = HealerQueue.serialize();
|
||||
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;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
|
||||
import dev.zontreck.libzontreck.vectors.Vector3;
|
||||
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
||||
|
@ -8,17 +10,73 @@ import net.minecraft.nbt.CompoundTag;
|
|||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.Tag;
|
||||
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.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;
|
||||
|
||||
private WorldPosition position;
|
||||
private BlockState state;
|
||||
|
||||
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)
|
||||
{
|
||||
position = new WorldPosition(new Vector3(pos), lvl);
|
||||
|
@ -32,6 +90,7 @@ public class StoredBlock {
|
|||
}
|
||||
|
||||
|
||||
|
||||
public final BlockPos getPos()
|
||||
{
|
||||
return position.Position.asBlockPos();
|
||||
|
@ -100,6 +159,21 @@ public class StoredBlock {
|
|||
final CompoundTag tmp = tag.getCompound("entity");
|
||||
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