Reorganized Tick Receivers

1. Reorganized our code to initialize tick receivers each time the
server starts rather than once when the mod is initialized. This is
needed because reusing a single instance of each class across different
single-player sessions could cause scheduled events for one world to
leak into another world. This approach ensures that we discard all
pending events.
2. Separated the implementation of Limbo decay from a tick receiver that
periodically triggers fast decay. All of the decay code has been kept in
LimboDecay, while the ticking is handled by LimboDecayScheduler. This
change separates some functionality that should be independent, but
also, it's needed so that BlockLimbo can have access to LimboDecay's
methods without holding on to a tick receiver instance.
3. Minor change: renamed ChunkLoaderHelper.loadChunkForcedWorlds() to
loadForcedChunkWorlds().
This commit is contained in:
SenseiKiwi 2014-07-10 15:11:44 -04:00
parent c22479c0e8
commit c00c65eeee
10 changed files with 75 additions and 37 deletions

View file

@ -9,7 +9,7 @@ import net.minecraft.util.Icon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
import StevenDimDoors.mod_pocketDim.ticking.LimboDecay;
import StevenDimDoors.mod_pocketDim.world.LimboDecay;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

View file

@ -83,7 +83,7 @@ public class ChunkLoaderHelper implements LoadingCallback
}
}
public static void loadChunkForcedWorlds(FMLServerStartingEvent event)
public static void loadForcedChunkWorlds(FMLServerStartingEvent event)
{
for (NewDimData data : PocketManager.getDimensions())
{

View file

@ -54,7 +54,7 @@ import StevenDimDoors.mod_pocketDim.items.ItemWorldThread;
import StevenDimDoors.mod_pocketDim.items.itemRiftRemover;
import StevenDimDoors.mod_pocketDim.ticking.CustomLimboPopulator;
import StevenDimDoors.mod_pocketDim.ticking.FastRiftRegenerator;
import StevenDimDoors.mod_pocketDim.ticking.LimboDecay;
import StevenDimDoors.mod_pocketDim.ticking.LimboDecayScheduler;
import StevenDimDoors.mod_pocketDim.ticking.MobMonolith;
import StevenDimDoors.mod_pocketDim.ticking.RiftRegenerator;
import StevenDimDoors.mod_pocketDim.ticking.ServerTickHandler;
@ -65,6 +65,7 @@ import StevenDimDoors.mod_pocketDim.tileentities.TileEntityTransTrapdoor;
import StevenDimDoors.mod_pocketDim.world.BiomeGenLimbo;
import StevenDimDoors.mod_pocketDim.world.BiomeGenPocket;
import StevenDimDoors.mod_pocketDim.world.DDBiomeGenBase;
import StevenDimDoors.mod_pocketDim.world.LimboDecay;
import StevenDimDoors.mod_pocketDim.world.LimboProvider;
import StevenDimDoors.mod_pocketDim.world.PocketProvider;
import StevenDimDoors.mod_pocketDim.world.gateways.GatewayGenerator;
@ -142,9 +143,13 @@ public class mod_pocketDim
public static DDProperties properties;
public static DDWorldProperties worldProperties;
public static CustomLimboPopulator spawner; //Added this field temporarily. Will be refactored out later.
private static RiftRegenerator riftRegenerator;
public static FastRiftRegenerator fastRiftRegenerator;
public static GatewayGenerator gatewayGenerator;
public static DeathTracker deathTracker;
private static ServerTickHandler serverTickHandler;
private static LimboDecayScheduler limboDecayScheduler;
private static LimboDecay limboDecay;
private static EventHookContainer hooks;
//TODO this is a temporary workaround for saving data
@ -182,16 +187,14 @@ public class mod_pocketDim
@EventHandler
public void onInitialization(FMLInitializationEvent event)
{
ServerTickHandler commonTickHandler = new ServerTickHandler();
TickRegistry.registerTickHandler(commonTickHandler, Side.SERVER);
//MonolithSpawner should be initialized before any provider instances are created
//Register the other regular tick receivers as well
spawner = new CustomLimboPopulator(commonTickHandler, properties);
new RiftRegenerator(commonTickHandler); //No need to store the reference
LimboDecay decay = new LimboDecay(commonTickHandler, properties);
fastRiftRegenerator = new FastRiftRegenerator(commonTickHandler);
// Initialize ServerTickHandler instance
serverTickHandler = new ServerTickHandler();
TickRegistry.registerTickHandler(serverTickHandler, Side.SERVER);
// Initialize LimboDecay instance: required for BlockLimbo
limboDecay = new LimboDecay(properties);
// Initialize blocks and items
transientDoor = new TransientDoor(properties.TransientDoorID, Material.iron, properties).setHardness(1.0F) .setUnlocalizedName("transientDoor");
goldenDimensionalDoor = new BlockGoldDimDoor(properties.GoldenDimensionalDoorID, Material.iron, properties).setHardness(1.0F) .setUnlocalizedName("dimDoorGold");
@ -200,7 +203,7 @@ public class mod_pocketDim
blockDimWallPerm = (new BlockDimWallPerm(properties.PermaFabricBlockID, 0, Material.iron)).setLightValue(1.0F).setBlockUnbreakable().setResistance(6000000.0F).setUnlocalizedName("blockDimWallPerm");
warpDoor = new WarpDoor(properties.WarpDoorID, Material.wood, properties).setHardness(1.0F) .setUnlocalizedName("dimDoorWarp");
blockRift = (BlockRift) (new BlockRift(properties.RiftBlockID, 0, Material.air, properties).setHardness(1.0F) .setUnlocalizedName("rift"));
blockLimbo = new BlockLimbo(properties.LimboBlockID, 15, Material.iron, properties.LimboDimensionID, decay).setHardness(.2F).setUnlocalizedName("BlockLimbo").setLightValue(.0F);
blockLimbo = new BlockLimbo(properties.LimboBlockID, 15, Material.iron, properties.LimboDimensionID, limboDecay).setHardness(.2F).setUnlocalizedName("BlockLimbo").setLightValue(.0F);
unstableDoor = (new UnstableDoor(properties.UnstableDoorID, Material.iron, properties).setHardness(.2F).setUnlocalizedName("chaosDoor").setLightValue(.0F) );
dimensionalDoor = (DimensionalDoor) (new DimensionalDoor(properties.DimensionalDoorID, Material.iron, properties).setHardness(1.0F).setResistance(2000.0F) .setUnlocalizedName("dimDoor"));
transTrapdoor = (TransTrapdoor) (new TransTrapdoor(properties.TransTrapdoorID, Material.wood).setHardness(1.0F) .setUnlocalizedName("dimHatch"));
@ -317,7 +320,11 @@ public class mod_pocketDim
deathTracker.writeToFile();
deathTracker = null;
worldProperties = null;
this.currrentSaveRootDirectory=null;
currrentSaveRootDirectory = null;
// Unregister all tick receivers from serverTickHandler to avoid leaking
// scheduled tasks between single-player game sessions
serverTickHandler.unregisterReceivers();
}
catch (Exception e)
{
@ -333,9 +340,16 @@ public class mod_pocketDim
// Load the config file that's specific to this world
worldProperties = new DDWorldProperties(new File(currrentSaveRootDirectory + "/DimensionalDoors/DimDoorsWorld.cfg"));
hooks.setWorldProperties(worldProperties);
// Initialize a new DeathTracker
deathTracker = new DeathTracker(currrentSaveRootDirectory + "/DimensionalDoors/data/deaths.txt");
// Register regular tick receivers
// CustomLimboPopulator should be initialized before any provider instances are created
spawner = new CustomLimboPopulator(serverTickHandler, properties);
riftRegenerator = new RiftRegenerator(serverTickHandler);
limboDecayScheduler = new LimboDecayScheduler(serverTickHandler, limboDecay);
fastRiftRegenerator = new FastRiftRegenerator(serverTickHandler);
}
@EventHandler
@ -353,7 +367,7 @@ public class mod_pocketDim
try
{
ChunkLoaderHelper.loadChunkForcedWorlds(event);
ChunkLoaderHelper.loadForcedChunkWorlds(event);
}
catch (Exception e)
{

View file

@ -30,7 +30,7 @@ public class CustomLimboPopulator implements IRegularTickReceiver {
{
this.properties = properties;
this.locations = new ConcurrentLinkedQueue<ChunkLocation>();
sender.registerForTicking(this, MONOLITH_SPAWNING_INTERVAL, false);
sender.registerReceiver(this, MONOLITH_SPAWNING_INTERVAL, false);
}
@Override

View file

@ -20,7 +20,7 @@ public class FastRiftRegenerator implements IRegularTickReceiver {
public FastRiftRegenerator(IRegularTickSender sender)
{
sender.registerForTicking(this, RIFT_REGENERATION_INTERVAL, false);
sender.registerReceiver(this, RIFT_REGENERATION_INTERVAL, false);
}
@Override
@ -33,6 +33,7 @@ public class FastRiftRegenerator implements IRegularTickReceiver {
{
if (!locationsToRegen.isEmpty())
{
@SuppressWarnings("cast")
List<Integer> loadedWorlds = (List<Integer>) Arrays.asList(DimensionManager.getIDs());
for (Point4D point: locationsToRegen)
{

View file

@ -3,6 +3,7 @@ package StevenDimDoors.mod_pocketDim.ticking;
public interface IRegularTickSender {
public void registerForTicking(IRegularTickReceiver receiver, int interval, boolean onTickStart);
public void registerReceiver(IRegularTickReceiver receiver, int interval, boolean onTickStart);
public void unregisterReceivers();
}

View file

@ -0,0 +1,28 @@
package StevenDimDoors.mod_pocketDim.ticking;
import StevenDimDoors.mod_pocketDim.world.LimboDecay;
/**
* Handles scheduling of periodic fast Limbo decay operations.
*/
public class LimboDecayScheduler implements IRegularTickReceiver {
private static final int LIMBO_DECAY_INTERVAL = 10; //Apply fast decay every 10 ticks
private LimboDecay decay;
public LimboDecayScheduler(IRegularTickSender tickSender, LimboDecay decay)
{
this.decay = decay;
tickSender.registerReceiver(this, LIMBO_DECAY_INTERVAL, false);
}
/**
* Applies fast Limbo decay periodically.
*/
@Override
public void notifyTick()
{
decay.applyRandomFastDecay();
}
}

View file

@ -20,7 +20,7 @@ public class RiftRegenerator implements IRegularTickReceiver {
public RiftRegenerator(IRegularTickSender sender)
{
sender.registerForTicking(this, RIFT_REGENERATION_INTERVAL, false);
sender.registerReceiver(this, RIFT_REGENERATION_INTERVAL, false);
}
@Override

View file

@ -14,18 +14,23 @@ public class ServerTickHandler implements ITickHandler, IRegularTickSender
private int tickCount = 0;
private ArrayList<RegularTickReceiverInfo> receivers;
public ServerTickHandler()
{
this.receivers = new ArrayList<RegularTickReceiverInfo>();
}
@Override
public void registerForTicking(IRegularTickReceiver receiver, int interval, boolean onTickStart)
public void registerReceiver(IRegularTickReceiver receiver, int interval, boolean onTickStart)
{
RegularTickReceiverInfo info = new RegularTickReceiverInfo(receiver, interval, onTickStart);
receivers.add(info);
}
@Override
public void unregisterReceivers()
{
receivers.clear();
}
@Override
public void tickStart(EnumSet<TickType> type, Object... tickData)

View file

@ -1,4 +1,4 @@
package StevenDimDoors.mod_pocketDim.ticking;
package StevenDimDoors.mod_pocketDim.world;
import java.util.Random;
@ -13,13 +13,12 @@ import StevenDimDoors.mod_pocketDim.config.DDProperties;
* Provides methods for applying Limbo decay. Limbo decay refers to the effect that most blocks placed in Limbo
* naturally change into stone, then cobble, then gravel, and finally Unraveled Fabric as time passes.
*/
public class LimboDecay implements IRegularTickReceiver {
public class LimboDecay {
private static final int MAX_DECAY_SPREAD_CHANCE = 100;
private static final int DECAY_SPREAD_CHANCE = 50;
private static final int CHUNK_SIZE = 16;
private static final int SECTION_HEIGHT = 16;
private static final int LIMBO_DECAY_INTERVAL = 10; //Apply spread decay every 10 ticks
//Provides a reversed list of the block IDs that blocks cycle through during decay.
private final int[] decaySequence;
@ -28,7 +27,7 @@ public class LimboDecay implements IRegularTickReceiver {
private final DDProperties properties;
private final int[] blocksImmuneToDecay;
public LimboDecay(IRegularTickSender tickSender, DDProperties properties)
public LimboDecay(DDProperties properties)
{
decaySequence = new int[] {
properties.LimboBlockID,
@ -51,16 +50,6 @@ public class LimboDecay implements IRegularTickReceiver {
this.properties = properties;
this.random = new Random();
tickSender.registerForTicking(this, LIMBO_DECAY_INTERVAL, false);
}
/**
* Applies fast Limbo decay periodically.
*/
@Override
public void notifyTick()
{
applyRandomFastDecay();
}
/**
@ -88,7 +77,7 @@ public class LimboDecay implements IRegularTickReceiver {
* Picks random blocks from each active chunk in Limbo and, if decay is applicable, converts them directly to Unraveled Fabric.
* This decay method is designed to stop players from avoiding Limbo decay by building floating structures.
*/
private void applyRandomFastDecay()
public void applyRandomFastDecay()
{
int x, y, z;
int sectionY;