diff --git a/src/main/java/de/ellpeck/naturesaura/ModConfig.java b/src/main/java/de/ellpeck/naturesaura/ModConfig.java index 53069a8c..cbf48e0b 100644 --- a/src/main/java/de/ellpeck/naturesaura/ModConfig.java +++ b/src/main/java/de/ellpeck/naturesaura/ModConfig.java @@ -47,6 +47,8 @@ public final class ModConfig { public boolean removeDragonBreathContainerItem = true; @Comment("If the RF converter block should be enabled") public boolean rfConverter = true; + @Comment("If the chunk loader block should be enabled") + public boolean chunkLoader = true; @Comment("If the Aura Imbalance effect of grass and trees dying in the area if the Aura levels are too low should occur") public boolean grassDieEffect = true; diff --git a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java index f7617413..9d405bb4 100644 --- a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java +++ b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java @@ -26,6 +26,7 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; @@ -48,6 +49,9 @@ public final class NaturesAura { public static final Logger LOGGER = LogManager.getLogger(MOD_NAME); + @Instance(value = MOD_ID) + public static NaturesAura instance; + @SidedProxy(modId = MOD_ID, clientSide = PROXY_LOCATION + "ClientProxy", serverSide = PROXY_LOCATION + "ServerProxy") public static IProxy proxy; diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockChunkLoader.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockChunkLoader.java new file mode 100644 index 00000000..959001f7 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockChunkLoader.java @@ -0,0 +1,76 @@ +package de.ellpeck.naturesaura.blocks; + +import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.api.render.IVisualizable; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityChunkLoader; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeChunkManager; +import net.minecraftforge.common.ForgeChunkManager.Ticket; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.List; + +public class BlockChunkLoader extends BlockContainerImpl implements IVisualizable { + + public BlockChunkLoader() { + super(Material.ROCK, "chunk_loader", TileEntityChunkLoader.class, "chunk_loader"); + this.setSoundType(SoundType.STONE); + this.setHardness(3F); + } + + @Override + public void onInit(FMLInitializationEvent event) { + super.onInit(event); + ForgeChunkManager.setForcedChunkLoadingCallback(NaturesAura.instance, new ChunkLoadingCallback()); + } + + @Override + @SideOnly(Side.CLIENT) + public AxisAlignedBB getVisualizationBounds(World world, BlockPos pos) { + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof TileEntityChunkLoader) { + int range = ((TileEntityChunkLoader) tile).range(); + if (range > 0) { + return new AxisAlignedBB( + (pos.getX() - range) >> 4 << 4, + 0, + (pos.getZ() - range) >> 4 << 4, + ((pos.getX() + range) >> 4 << 4) + 16, + world.getHeight(), + ((pos.getZ() + range) >> 4 << 4) + 16); + } + } + return null; + } + + @Override + @SideOnly(Side.CLIENT) + public int getVisualizationColor(World world, BlockPos pos) { + return 0xc159f9; + } + + public static class ChunkLoadingCallback implements ForgeChunkManager.LoadingCallback { + + @Override + public void ticketsLoaded(List tickets, World world) { + for (Ticket ticket : tickets) { + NBTTagCompound data = ticket.getModData(); + BlockPos pos = BlockPos.fromLong(data.getLong("pos")); + TileEntity tile = world.getTileEntity(pos); + if (!(tile instanceof TileEntityChunkLoader)) + continue; + TileEntityChunkLoader loader = (TileEntityChunkLoader) tile; + loader.updateTicket(ticket); + loader.loadChunks(); + } + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockContainerImpl.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockContainerImpl.java index 7b7cd35d..cbc407b2 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/BlockContainerImpl.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockContainerImpl.java @@ -132,23 +132,27 @@ public class BlockContainerImpl extends BlockContainer implements IModItem, ICre if (tile instanceof TileEntityImpl) { TileEntityImpl impl = (TileEntityImpl) tile; int newPower = world.getRedstonePowerFromNeighbors(pos); - if (impl.redstonePower != newPower) { - boolean pulse = impl.redstonePower <= 0 && newPower > 0; - impl.redstonePower = newPower; - impl.onRedstonePowerChange(); - if (pulse) - world.scheduleUpdate(pos, this, this.tickRate(world)); - } + if (impl.redstonePower != newPower) + world.scheduleUpdate(pos, this, this.tickRate(world)); } } } + @Override + public int tickRate(World worldIn) { + return 4; + } + @Override public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) { if (!worldIn.isRemote) { TileEntity tile = worldIn.getTileEntity(pos); - if (tile instanceof TileEntityImpl) - ((TileEntityImpl) tile).onRedstonePulse(); + if (tile instanceof TileEntityImpl) { + TileEntityImpl impl = (TileEntityImpl) tile; + int newPower = worldIn.getRedstonePowerFromNeighbors(pos); + if (impl.redstonePower != newPower) + ((TileEntityImpl) tile).onRedstonePowerChange(newPower); + } } } } \ No newline at end of file diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java index d4eb5bf7..fe47f74b 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java @@ -53,4 +53,5 @@ public final class ModBlocks { public static final Block POWDER_PLACER = new BlockPowderPlacer(); public static final Block FIREWORK_GENERATOR = new BlockFireworkGenerator(); public static final Block PROJECTILE_GENERATOR = new BlockProjectileGenerator(); + public static final Block CHUNK_LOADER = ModConfig.enabledFeatures.chunkLoader ? new BlockChunkLoader() : null; } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityChunkLoader.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityChunkLoader.java new file mode 100644 index 00000000..f62e02fd --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityChunkLoader.java @@ -0,0 +1,89 @@ +package de.ellpeck.naturesaura.blocks.tiles; + +import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.common.ForgeChunkManager; +import net.minecraftforge.common.ForgeChunkManager.Ticket; +import net.minecraftforge.common.ForgeChunkManager.Type; + +import java.util.HashSet; +import java.util.Set; + +public class TileEntityChunkLoader extends TileEntityImpl implements ITickable { + + private Ticket ticket; + + @Override + public void validate() { + super.validate(); + if (!this.world.isRemote && this.ticket == null) { + Ticket ticket = ForgeChunkManager.requestTicket(NaturesAura.instance, this.world, Type.NORMAL); + this.updateTicket(ticket); + ticket.getModData().setLong("pos", this.pos.toLong()); + } + } + + @Override + public void invalidate() { + super.invalidate(); + if (!this.world.isRemote) + this.updateTicket(null); + } + + @Override + public void onRedstonePowerChange(int newPower) { + super.onRedstonePowerChange(newPower); + if (!this.world.isRemote) { + this.loadChunks(); + this.sendToClients(); + } + } + + public int range() { + return this.redstonePower * 2; + } + + public void updateTicket(Ticket ticket) { + if (this.ticket != null) + ForgeChunkManager.releaseTicket(this.ticket); + this.ticket = ticket; + } + + public void loadChunks() { + if (this.ticket == null) + return; + Set before = new HashSet<>(this.ticket.getChunkList()); + int range = this.range(); + if (range > 0) { + for (int x = (this.pos.getX() - range) >> 4; x <= (this.pos.getX() + range) >> 4; x++) { + for (int z = (this.pos.getZ() - range) >> 4; z <= (this.pos.getZ() + range) >> 4; z++) { + ChunkPos pos = new ChunkPos(x, z); + if (!before.contains(pos)) + ForgeChunkManager.forceChunk(this.ticket, pos); + else + before.remove(pos); + } + } + } + for (ChunkPos pos : before) + ForgeChunkManager.unforceChunk(this.ticket, pos); + } + + @Override + public void update() { + if (!this.world.isRemote) { + if (this.world.getTotalWorldTime() % 20 != 0) + return; + int toUse = MathHelper.ceil(this.range() / 2F); + if (toUse > 0) { + BlockPos spot = IAuraChunk.getHighestSpot(this.world, this.pos, 35, this.pos); + IAuraChunk.getAuraChunk(this.world, spot).drainAura(spot, toUse); + } + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityImpl.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityImpl.java index 1566b303..a050d9bb 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityImpl.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityImpl.java @@ -58,12 +58,8 @@ public class TileEntityImpl extends TileEntity { } } - public void onRedstonePowerChange() { - - } - - public void onRedstonePulse() { - + public void onRedstonePowerChange(int newPower) { + this.redstonePower = newPower; } @Override diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPickupStopper.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPickupStopper.java index f980fb06..aee2f8fa 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPickupStopper.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPickupStopper.java @@ -7,7 +7,8 @@ public class TileEntityPickupStopper extends TileEntityImpl { } @Override - public void onRedstonePowerChange() { + public void onRedstonePowerChange(int newPower) { + super.onRedstonePowerChange(newPower); if (!this.world.isRemote) this.sendToClients(); } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPowderPlacer.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPowderPlacer.java index 53ea8503..20c08e19 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPowderPlacer.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityPowderPlacer.java @@ -15,40 +15,43 @@ import java.util.List; public class TileEntityPowderPlacer extends TileEntityImpl { @Override - public void onRedstonePulse() { - List powders = this.world.getEntitiesWithinAABB(EntityEffectInhibitor.class, - new AxisAlignedBB(this.pos, this.pos.add(1, 2, 1)), EntitySelectors.IS_ALIVE); - for (EnumFacing facing : EnumFacing.HORIZONTALS) { - TileEntity tile = this.world.getTileEntity(this.pos.offset(facing)); - if (tile == null || !tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite())) - continue; - IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); - if (handler == null) - continue; + public void onRedstonePowerChange(int newPower) { + if (this.redstonePower <= 0 && newPower > 0) { + List powders = this.world.getEntitiesWithinAABB(EntityEffectInhibitor.class, + new AxisAlignedBB(this.pos, this.pos.add(1, 2, 1)), EntitySelectors.IS_ALIVE); + for (EnumFacing facing : EnumFacing.HORIZONTALS) { + TileEntity tile = this.world.getTileEntity(this.pos.offset(facing)); + if (tile == null || !tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite())) + continue; + IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); + if (handler == null) + continue; - if (!powders.isEmpty()) { - for (EntityEffectInhibitor powder : powders) { - ItemStack drop = powder.getDrop(); - for (int i = 0; i < handler.getSlots(); i++) { - ItemStack remain = handler.insertItem(i, drop, false); - if (remain.isEmpty()) { - powder.setDead(); - break; - } else if (remain.getCount() != drop.getCount()) { - powder.setAmount(remain.getCount()); + if (!powders.isEmpty()) { + for (EntityEffectInhibitor powder : powders) { + ItemStack drop = powder.getDrop(); + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack remain = handler.insertItem(i, drop, false); + if (remain.isEmpty()) { + powder.setDead(); + break; + } else if (remain.getCount() != drop.getCount()) { + powder.setAmount(remain.getCount()); + } } } - } - } else { - for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = handler.extractItem(i, Integer.MAX_VALUE, true); - if (stack.isEmpty() || stack.getItem() != ModItems.EFFECT_POWDER) - continue; - EntityEffectInhibitor.place(this.world, stack, this.pos.getX() + 0.5, this.pos.getY() + 1, this.pos.getZ() + 0.5); - handler.extractItem(i, Integer.MAX_VALUE, false); - break; + } else { + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.extractItem(i, Integer.MAX_VALUE, true); + if (stack.isEmpty() || stack.getItem() != ModItems.EFFECT_POWDER) + continue; + EntityEffectInhibitor.place(this.world, stack, this.pos.getX() + 0.5, this.pos.getY() + 1, this.pos.getZ() + 0.5); + handler.extractItem(i, Integer.MAX_VALUE, false); + break; + } } } } + super.onRedstonePowerChange(newPower); } } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntitySpawnLamp.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntitySpawnLamp.java index b6abbcf7..68adccde 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntitySpawnLamp.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntitySpawnLamp.java @@ -7,7 +7,8 @@ public class TileEntitySpawnLamp extends TileEntityImpl { } @Override - public void onRedstonePowerChange() { + public void onRedstonePowerChange(int newPower) { + super.onRedstonePowerChange(newPower); if (!this.world.isRemote) this.sendToClients(); }