Finish fixing bugs and downgrading
This commit is contained in:
parent
db76b314e5
commit
1126306c2c
11 changed files with 171 additions and 840 deletions
|
@ -38,8 +38,6 @@ import net.minecraftforge.registries.ForgeRegistries;
|
|||
import org.slf4j.Logger;
|
||||
|
||||
import dev.zontreck.libzontreck.chat.ChatColor;
|
||||
import dev.zontreck.otemod.antigrief.HealerManager;
|
||||
import dev.zontreck.otemod.antigrief.HealerQueue;
|
||||
import dev.zontreck.otemod.blocks.ModBlocks;
|
||||
import dev.zontreck.otemod.chat.ChatServerOverride;
|
||||
import dev.zontreck.otemod.commands.CommandRegistry;
|
||||
|
@ -155,7 +153,7 @@ public class OTEMod
|
|||
try {
|
||||
OTEMod.DB = new Database(this);
|
||||
OTEMod.ALIVE=true;
|
||||
HealerQueue.Initialize(); // Set up the queue
|
||||
//HealerQueue.Initialize(); // Set up the queue
|
||||
|
||||
|
||||
// Validate that the database has been established and that tables exist
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
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;
|
||||
import dev.zontreck.otemod.OTEMod;
|
||||
import dev.zontreck.otemod.configs.OTEServerConfig;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.BlockEventData;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.event.entity.item.ItemEvent;
|
||||
import net.minecraftforge.event.level.BlockEvent;
|
||||
import net.minecraftforge.event.level.ChunkDataEvent;
|
||||
import net.minecraftforge.event.level.ExplosionEvent;
|
||||
import net.minecraftforge.event.level.BlockEvent.NeighborNotifyEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
|
||||
@EventBusSubscriber(modid = OTEMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||
public class Handler
|
||||
{
|
||||
private static final String EXPLOSION_HEAL_TAG = "OTEEH";
|
||||
|
||||
|
||||
/*@OnlyIn(Dist.DEDICATED_SERVER)
|
||||
@SubscribeEvent
|
||||
public void onChunkLoad(final ChunkDataEvent.Load event)
|
||||
{
|
||||
final CompoundTag EHTag = event.getData().getCompound(EXPLOSION_HEAL_TAG);
|
||||
if(!EHTag.isEmpty())
|
||||
{
|
||||
final CompoundTag healer = EHTag.getCompound("healer");
|
||||
if(!healer.isEmpty()){
|
||||
// This would re-queue the healer
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@OnlyIn(Dist.DEDICATED_SERVER)
|
||||
@SubscribeEvent
|
||||
public void onDetonation(ExplosionEvent.Detonate event)
|
||||
{
|
||||
ServerLevel level = (ServerLevel)event.getLevel();
|
||||
|
||||
Entity exploder = event.getExplosion().getExploder();
|
||||
|
||||
if(exploder==null)return ; // TODO: Make this check config
|
||||
|
||||
final Collection<StoredBlock> affectedBlocks = buildBlocks(level, event.getAffectedBlocks());
|
||||
Collection<StoredBlock> toHeal = new ArrayList<StoredBlock>(affectedBlocks.size());
|
||||
|
||||
Block tnt = Blocks.TNT;
|
||||
|
||||
for(final StoredBlock data : affectedBlocks)
|
||||
{
|
||||
// Check an exclusions list
|
||||
if(!OTEServerConfig.EXCLUDE_DIMENSIONS.get().contains(data.getWorldPosition().Dimension))
|
||||
if(!data.getState().is(tnt))
|
||||
toHeal.add(data);
|
||||
}
|
||||
|
||||
// Process Block Entities
|
||||
|
||||
for(final StoredBlock sb : toHeal)
|
||||
{
|
||||
if(sb.getState().hasBlockEntity())
|
||||
{
|
||||
BlockEntity be = level.getBlockEntity(sb.getPos());
|
||||
if(be != null){
|
||||
sb.setBlockEntity(be);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the existing blocks from the world to prevent item duplication
|
||||
// Begin
|
||||
for(StoredBlock data : toHeal)
|
||||
{
|
||||
if(data.getBlockEntity()!=null)
|
||||
data.getWorldPosition().getActualDimension().removeBlockEntity(data.getPos());
|
||||
|
||||
data.getWorldPosition().getActualDimension().destroyBlock(data.getPos(), false);
|
||||
}
|
||||
|
||||
// Add to the healing queue
|
||||
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.Shuffle();
|
||||
|
||||
}
|
||||
|
||||
private Collection<StoredBlock> buildBlocks(ServerLevel level, Collection<BlockPos> positions)
|
||||
{
|
||||
Collection<StoredBlock> healables = new LinkedList<StoredBlock>();
|
||||
for(final BlockPos pos : positions)
|
||||
{
|
||||
final BlockState state = level.getBlockState(pos);
|
||||
StoredBlock sb = new StoredBlock(pos, state, level);
|
||||
|
||||
if(state !=null)
|
||||
healables.add(sb);
|
||||
|
||||
}
|
||||
|
||||
return healables;
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package dev.zontreck.otemod.antigrief;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.zontreck.otemod.OTEMod;
|
||||
import dev.zontreck.otemod.configs.OTEServerConfig;
|
||||
|
||||
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(){
|
||||
boolean skipWait=false;
|
||||
int skipCount=0;
|
||||
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{
|
||||
try{
|
||||
if(!skipWait) Thread.sleep(OTEServerConfig.HEALER_TIMER.get());
|
||||
}catch(Exception E){}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}catch(Exception e){}
|
||||
}
|
||||
|
||||
OTEMod.LOGGER.info("Tearing down healer jobs. Saving remaining queue, stand by...");
|
||||
try {
|
||||
HealerQueue.dump();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
OTEMod.LOGGER.info("Finished tearing down Healer - Good bye");
|
||||
}
|
||||
}
|
|
@ -1,327 +0,0 @@
|
|||
package dev.zontreck.otemod.antigrief;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
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.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraftforge.fml.loading.FMLConfig;
|
||||
import net.minecraftforge.fml.loading.FMLPaths;
|
||||
|
||||
public class HealerQueue {
|
||||
// Healer Queue's data source is a NBT File in the config folder
|
||||
public static final String HealerQueueFile = "OTEHealerLastQueue.nbt";
|
||||
public static final String HealerQueueDebugFile = "OTEHealerLastQueue.snbt";
|
||||
|
||||
public static List<StoredBlock> ToHeal = new ArrayList<StoredBlock>(); // Air and Solid Blocks get set to bedrock initially
|
||||
|
||||
public static int Pass = 0;
|
||||
|
||||
|
||||
private static List<StoredBlock> LastToHeal = new ArrayList<StoredBlock>();
|
||||
private static int LastPass = 0;
|
||||
|
||||
public static HealerManager ManagerInstance=null;
|
||||
|
||||
|
||||
public static Path getPath()
|
||||
{
|
||||
|
||||
Path configDir = FMLPaths.GAMEDIR.get().resolve(FMLConfig.defaultConfigPath());
|
||||
Path configFile = null;
|
||||
if(OTEServerConfig.DEBUG_HEALER.get())
|
||||
{
|
||||
configFile = configDir.resolve(HealerQueue.HealerQueueDebugFile);
|
||||
|
||||
}else {
|
||||
configFile = configDir.resolve(HealerQueue.HealerQueueFile);
|
||||
}
|
||||
|
||||
//OTEMod.LOGGER.info("OTE HEALER TEMPORARY FILE: "+configFile.toFile().getAbsolutePath());
|
||||
return configFile;
|
||||
}
|
||||
|
||||
public static StoredBlock locateHighestBlock(List<StoredBlock> list)
|
||||
{
|
||||
StoredBlock sb = null;
|
||||
double currentY = 0;
|
||||
for (StoredBlock storedBlock : ToHeal) {
|
||||
if(storedBlock.getWorldPosition().Position.y > currentY)
|
||||
{
|
||||
currentY = storedBlock.getWorldPosition().Position.y;
|
||||
sb=storedBlock;
|
||||
}
|
||||
}
|
||||
|
||||
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 locateLowestBlockForWorker(List<StoredBlock> list, HealerWorker worker)
|
||||
{
|
||||
StoredBlock sb = null;
|
||||
double currentY = 300;
|
||||
for (StoredBlock storedBlock : ToHeal) {
|
||||
if(storedBlock.getWorldPosition().Position.y < currentY && storedBlock.isClaimedBy(worker))
|
||||
{
|
||||
currentY = storedBlock.getWorldPosition().Position.y;
|
||||
sb=storedBlock;
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static List<StoredBlock> getBlocksByWorker(HealerWorker worker)
|
||||
{
|
||||
List<StoredBlock> blocks = new ArrayList<>();
|
||||
for (StoredBlock storedBlock : ToHeal) {
|
||||
if(storedBlock.isClaimedBy(worker))blocks.add(storedBlock);
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
public static StoredBlock getExact(WorldPosition wp)
|
||||
{
|
||||
for (StoredBlock storedBlock : ToHeal) {
|
||||
if(storedBlock.getWorldPosition().same(wp))
|
||||
{
|
||||
return storedBlock;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static boolean HasValidatePosition(BlockPos pos, ServerLevel lvl)
|
||||
{
|
||||
Vector3 realPos = new Vector3(pos);
|
||||
WorldPosition real = new WorldPosition(realPos, lvl);
|
||||
|
||||
for (StoredBlock storedBlock : ToHeal) {
|
||||
if(storedBlock.getWorldPosition().same(real))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Thread tx = new Thread(new Runnable(){
|
||||
public void run(){
|
||||
if(OTEServerConfig.DEBUG_HEALER.get())
|
||||
{
|
||||
// Load the sNBT file
|
||||
Path configFile = getPath();
|
||||
File x = configFile.toFile();
|
||||
String FinalStr = "";
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new FileReader(x));
|
||||
while(br.ready())
|
||||
{
|
||||
FinalStr += br.readLine();
|
||||
}
|
||||
br.close();
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch(IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
HealerQueue.deserialize(NbtUtils.snbtToStructure(FinalStr));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
// Load from normal NBT
|
||||
Path configFile = getPath();
|
||||
File x = configFile.toFile();
|
||||
// Load binary
|
||||
try {
|
||||
CompoundTag tag = NbtIo.readCompressed(x);
|
||||
HealerQueue.deserialize(tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
OTEMod.HEALER_WAIT=false;
|
||||
}
|
||||
});
|
||||
tx.start();
|
||||
|
||||
// Set up the HealerManager / Runner
|
||||
ManagerInstance = new HealerManager();
|
||||
Thread txx = new Thread(ManagerInstance);
|
||||
txx.start();
|
||||
|
||||
HealerWorker worker = new HealerWorker(ToHeal);
|
||||
Thread txxx = new Thread(worker);
|
||||
ManagerInstance.registerWorker(worker);
|
||||
txxx.start();
|
||||
|
||||
OTEMod.HEALER_THREAD = txx;
|
||||
}
|
||||
|
||||
public static CompoundTag serialize()
|
||||
{
|
||||
CompoundTag tag = new CompoundTag();
|
||||
// Save entire list
|
||||
ListTag lst = new ListTag();
|
||||
for(final StoredBlock block : HealerQueue.ToHeal)
|
||||
{
|
||||
lst.add(block.serialize());
|
||||
}
|
||||
|
||||
tag.put("queue", lst);
|
||||
tag.putInt("pass", HealerQueue.Pass);
|
||||
|
||||
//OTEMod.LOGGER.info("HEAL ["+HealerQueue.ToHeal.size()+"] / VALIDATE ["+HealerQueue.ToValidate.size()+"]");
|
||||
|
||||
// OK
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static List<StoredBlock> removeSame(List<StoredBlock> other)
|
||||
{
|
||||
other=removeSameFrom(ToHeal, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void deserialize(CompoundTag tag)
|
||||
{
|
||||
OTEMod.HEALER_WAIT=true;
|
||||
// Begin parsing
|
||||
if(tag.contains("queue"))
|
||||
{
|
||||
HealerQueue.ToHeal.clear();
|
||||
// Read the list
|
||||
|
||||
ListTag items = tag.getList("queue", Tag.TAG_COMPOUND);
|
||||
|
||||
|
||||
for(int i=0;i<items.size();i++)
|
||||
{
|
||||
CompoundTag stored = items.getCompound(i);
|
||||
StoredBlock sb = new StoredBlock(stored);
|
||||
HealerQueue.ToHeal.add(sb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OTEMod.LOGGER.info("Finished loading the queue ["+HealerQueue.ToHeal.size()+"] items");
|
||||
|
||||
|
||||
HealerQueue.Pass = tag.getInt("pass");
|
||||
|
||||
OTEMod.HEALER_WAIT=false;
|
||||
}
|
||||
|
||||
public static boolean dirty()
|
||||
{
|
||||
if(ToHeal!=LastToHeal)return true;
|
||||
if(Pass != LastPass)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void dump() throws IOException
|
||||
{
|
||||
LastToHeal = ToHeal;
|
||||
LastPass = Pass;
|
||||
CompoundTag serialized = HealerQueue.serialize();
|
||||
if(OTEServerConfig.DEBUG_HEALER.get())
|
||||
{
|
||||
// Save to sNBT
|
||||
String prettyOutput = NbtUtils.structureToSnbt(serialized);
|
||||
Path storage = getPath();
|
||||
File x = storage.toFile();
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(x));
|
||||
bw.write(prettyOutput);
|
||||
bw.close();
|
||||
|
||||
}else {
|
||||
NbtIo.writeCompressed(serialized, getPath().toFile());
|
||||
}
|
||||
}
|
||||
|
||||
public static void Shuffle()
|
||||
{
|
||||
Collections.shuffle(ToHeal);
|
||||
|
||||
if(OTEServerConfig.DEBUG_HEALER.get())
|
||||
try {
|
||||
dump();// Push contents to disk if in debug mode for easier analyzing on change
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,198 +0,0 @@
|
|||
package dev.zontreck.otemod.antigrief;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import dev.zontreck.libzontreck.vectors.WorldPosition;
|
||||
import dev.zontreck.otemod.OTEMod;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class HealerWorker implements Runnable
|
||||
{
|
||||
private List<StoredBlock> proc;
|
||||
public boolean alive=false; // These are the
|
||||
public boolean doTick = false;
|
||||
public Thread MyThread;
|
||||
|
||||
private boolean skipWait;
|
||||
|
||||
public int Pass; // A local pass for this worker
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
alive=true;
|
||||
MyThread=Thread.currentThread();
|
||||
HealerQueue.ManagerInstance.registerWorker(this);
|
||||
OTEMod.LOGGER.info("Hello from Healer Worker "+Thread.currentThread().getName());
|
||||
|
||||
for(int i=0;i<proc.size();i++){
|
||||
StoredBlock sb = proc.get(i);
|
||||
sb.setClaimedBy(MyThread);
|
||||
}
|
||||
|
||||
while(alive && OTEMod.ALIVE){
|
||||
// Stay alive
|
||||
// The tick event will be fired when appropriate
|
||||
if(doTick)tick();
|
||||
if(skipWait)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()
|
||||
{
|
||||
|
||||
try{
|
||||
|
||||
// A tick in the healer worker tells it to repair a block
|
||||
// The healer manager is responsible for dispatching ticks
|
||||
|
||||
|
||||
if(proc.size()==0 && HealerQueue.getBlocksByWorker(this).size()==0)
|
||||
{
|
||||
alive=false;
|
||||
if(HealerQueue.dirty())
|
||||
HealerQueue.dump();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the first block in the list
|
||||
final StoredBlock sb = HealerQueue.locateLowestBlock(proc);
|
||||
ServerLevel level = null;
|
||||
StoredBlock below = null;
|
||||
|
||||
if(sb != null)
|
||||
{
|
||||
level = sb.getWorldPosition().getActualDimension();
|
||||
below = HealerQueue.getExact(new WorldPosition(sb.getWorldPosition().Position.moveDown(), level));
|
||||
}
|
||||
|
||||
|
||||
switch(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(proc.size()==0)
|
||||
{
|
||||
// Move the validate list back into healer queue, and increment pass
|
||||
OTEMod.LOGGER.info("Pass 1 completed, moving to pass 2");
|
||||
Pass=1;
|
||||
proc = HealerQueue.getBlocksByWorker(this);
|
||||
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;
|
||||
}
|
||||
}
|
||||
proc.remove(sb);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// Pass 2 only sets the solid blocks
|
||||
if(proc.size()==0)
|
||||
{
|
||||
OTEMod.LOGGER.info("Pass 2 completed, moving to pass 3");
|
||||
Pass++;
|
||||
proc = HealerQueue.getBlocksByWorker(this);
|
||||
HealerQueue.dump();
|
||||
break;
|
||||
}
|
||||
|
||||
if(!sb.getState().isAir())
|
||||
{
|
||||
skipWait=false;
|
||||
HealRunner.scheduleHeal(sb);
|
||||
HealerQueue.ToHeal.remove(sb);
|
||||
}else{
|
||||
skipWait=true;
|
||||
|
||||
}
|
||||
proc.remove(sb);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
// Pass 3 removes bedrock by setting blocks that are air
|
||||
if(proc.size()==0)
|
||||
{
|
||||
OTEMod.LOGGER.info("Pass 3 has been completed. Ending restore");
|
||||
Pass=0;
|
||||
proc.clear();
|
||||
HealerQueue.dump();
|
||||
break;
|
||||
}
|
||||
proc.remove(sb);
|
||||
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;
|
||||
return;
|
||||
}
|
||||
if(!bs.isAir()){
|
||||
skipWait=false;
|
||||
HealRunner.scheduleHeal(sb);
|
||||
}else skipWait=true;
|
||||
}else skipWait=true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Pass=0;
|
||||
OTEMod.LOGGER.info("/!\\ ALERT /!\\\n\nWARNING: Unknown pass operation was added to the HealQueue");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}catch(Exception e){}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package dev.zontreck.otemod.antigrief2;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import dev.zontreck.otemod.OTEMod;
|
||||
import dev.zontreck.otemod.antigrief.HealRunner;
|
||||
import dev.zontreck.otemod.antigrief.StoredBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.saveddata.SavedData;
|
||||
import net.minecraftforge.event.level.ExplosionEvent;
|
||||
|
||||
public class Healer extends SavedData implements Supplier<Object>
|
||||
{
|
||||
private Level world;
|
||||
private TickingHealerTask task;
|
||||
static final String DATAKEY = OTEMod.MOD_ID+":"+Healer.class.getSimpleName();
|
||||
|
||||
public Healer()
|
||||
{
|
||||
task = new TickingHealerTask();
|
||||
}
|
||||
|
||||
public void onTick()
|
||||
{
|
||||
Collection<StoredBlock> blocks = task.tick();
|
||||
if(blocks != null)
|
||||
{
|
||||
for(StoredBlock bdata : blocks)
|
||||
{
|
||||
HealRunner.scheduleHeal(bdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onDetonate(ExplosionEvent.Detonate event)
|
||||
{
|
||||
Level world = event.getLevel();
|
||||
int maxTicks = 0;
|
||||
for(BlockPos posExplode : event.getAffectedBlocks())
|
||||
{
|
||||
BlockState stateExplode = world.getBlockState(posExplode);
|
||||
if(!isValid(stateExplode))
|
||||
continue;
|
||||
|
||||
if(!stateExplode.isAir())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag save(CompoundTag p_77763_) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package dev.zontreck.otemod.antigrief2.handlers;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import dev.zontreck.otemod.antigrief2.Healer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraftforge.event.level.LevelEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class WorldEventHandler {
|
||||
private Map<ServerLevel, Healer> healers = new HashMap<ServerLevel, Healer>();
|
||||
|
||||
public Map<ServerLevel, Healer> getHealers()
|
||||
{
|
||||
return healers;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onLoadLevel(LevelEvent.Load ev)
|
||||
{
|
||||
if(!ev.getLevel().isClientSide() && ev.getLevel() instanceof ServerLevel)
|
||||
{
|
||||
healers.put((ServerLevel)ev.getLevel(), Healer.acquire((ServerLevel)ev.getLevel()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onUnload(LevelEvent.Unload ev)
|
||||
{
|
||||
if(!ev.getLevel().isClientSide())
|
||||
{
|
||||
healers.remove(ev.getLevel());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ public class BlockContainerList {
|
|||
private final Lock lock;
|
||||
private final List<StoredBlock> containers;
|
||||
|
||||
private BlockContainerList()
|
||||
public BlockContainerList()
|
||||
{
|
||||
this.lock = new ReentrantLock();
|
||||
this.containers = new ArrayList<>();
|
||||
|
|
|
@ -25,11 +25,6 @@ public class BlockSaver {
|
|||
executor=service;
|
||||
}
|
||||
|
||||
public static void InitialLoad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
executor.scheduleAtFixedRate(()->{
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
package dev.zontreck.otemod.zschem;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.level.ExplosionEvent;
|
||||
import net.minecraftforge.event.level.LevelEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class EventHandler {
|
||||
|
@ -8,6 +15,51 @@ public class EventHandler {
|
|||
@SubscribeEvent
|
||||
public void onDetonate(ExplosionEvent.Detonate ev)
|
||||
{
|
||||
|
||||
if(ev.getLevel().isClientSide)return;
|
||||
|
||||
Entity explodes = ev.getExplosion().getSourceMob();
|
||||
// Register blocks to be healed
|
||||
WorldProp wp = WorldProp.acquire((ServerLevel)ev.getLevel());
|
||||
if(wp!=null){
|
||||
wp.onDetonate(ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Map<ServerLevel, WorldProp> healers = new HashMap<ServerLevel, WorldProp>();
|
||||
|
||||
public Map<ServerLevel, WorldProp> getHealers()
|
||||
{
|
||||
return healers;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onLoadLevel(LevelEvent.Load ev)
|
||||
{
|
||||
if(!ev.getLevel().isClientSide() && ev.getLevel() instanceof ServerLevel)
|
||||
{
|
||||
healers.put((ServerLevel)ev.getLevel(), WorldProp.acquire((ServerLevel)ev.getLevel()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onUnload(LevelEvent.Unload ev)
|
||||
{
|
||||
if(!ev.getLevel().isClientSide())
|
||||
{
|
||||
healers.remove(ev.getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onLevelTick(TickEvent.LevelTickEvent ev)
|
||||
{
|
||||
if(!ev.level.isClientSide){
|
||||
WorldProp wp = WorldProp.acquire((ServerLevel)ev.level);
|
||||
if(wp!=null){
|
||||
wp.onTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
116
src/main/java/dev/zontreck/otemod/zschem/WorldProp.java
Normal file
116
src/main/java/dev/zontreck/otemod/zschem/WorldProp.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
package dev.zontreck.otemod.zschem;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import dev.zontreck.otemod.OTEMod;
|
||||
import dev.zontreck.otemod.configs.OTEServerConfig;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.saveddata.SavedData;
|
||||
import net.minecraft.world.level.storage.DimensionDataStorage;
|
||||
import net.minecraftforge.event.level.ExplosionEvent;
|
||||
|
||||
public class WorldProp extends SavedData implements Supplier<Object>
|
||||
{
|
||||
private Level world;
|
||||
private BlockContainerList task;
|
||||
static final String KEY = OTEMod.MOD_ID + ":" + WorldProp.class.getSimpleName();
|
||||
|
||||
public WorldProp(){
|
||||
task = new BlockContainerList();
|
||||
}
|
||||
|
||||
public void onTick()
|
||||
{
|
||||
task.tick();
|
||||
}
|
||||
|
||||
public void onDetonate(ExplosionEvent.Detonate ev)
|
||||
{
|
||||
Level w = ev.getLevel();
|
||||
int maxTicks = 0;
|
||||
|
||||
for(BlockPos p : ev.getAffectedBlocks())
|
||||
{
|
||||
BlockState bsExplode = w.getBlockState(p);
|
||||
if(!isValid(bsExplode))continue;
|
||||
|
||||
if(!bsExplode.isAir()){
|
||||
int ticks = OTEServerConfig.HEALER_TIMER.get() + w.random.nextInt();
|
||||
if(ticks > maxTicks){
|
||||
maxTicks = ticks;
|
||||
}
|
||||
|
||||
|
||||
addHeal(p, bsExplode, world);
|
||||
}
|
||||
}
|
||||
maxTicks ++;
|
||||
for(BlockPos p : ev.getAffectedBlocks())
|
||||
{
|
||||
BlockState bsE = w.getBlockState(p);
|
||||
if(!isValid(bsE))continue;
|
||||
if(!bsE.isAir()){
|
||||
addHeal(p, bsE, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addHeal(BlockPos p, BlockState s, Level w)
|
||||
{
|
||||
task.add(new StoredBlock(p, s, (ServerLevel)w));
|
||||
world.removeBlockEntity(p);
|
||||
world.setBlock(p, Blocks.AIR.defaultBlockState(), 7);
|
||||
}
|
||||
|
||||
private boolean isValid(BlockState bs)
|
||||
{
|
||||
if(bs.is(BlockTags.DOORS) || bs.is(BlockTags.BEDS) || bs.is(BlockTags.TALL_FLOWERS)){
|
||||
return false;
|
||||
} else return true;
|
||||
}
|
||||
|
||||
public CompoundTag save(CompoundTag tag){
|
||||
|
||||
return (CompoundTag) tag.put("task", task.save(tag));
|
||||
|
||||
}
|
||||
|
||||
public void load(CompoundTag tag)
|
||||
{
|
||||
CompoundTag ct = tag.getCompound("task");
|
||||
task = BlockContainerList.load(ct);
|
||||
}
|
||||
|
||||
public static WorldProp acquire(ServerLevel w)
|
||||
{
|
||||
DimensionDataStorage dds = w.getDataStorage();
|
||||
WorldProp wp = dds.computeIfAbsent(p->{
|
||||
WorldProp swp = new WorldProp();
|
||||
swp.load(p);
|
||||
return swp;
|
||||
}, ()->{
|
||||
return new WorldProp();
|
||||
}, KEY);
|
||||
wp.world = w;
|
||||
return wp;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDirty(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
Reference in a new issue