From cb7b5156264d7793c4444c41ba5e16817cec1cf5 Mon Sep 17 00:00:00 2001 From: MysteriousAges Date: Sat, 21 Mar 2015 20:45:36 -0700 Subject: [PATCH] Added network event for updating bit flags. Magic Apiary pulls charges from Aura Providers. --- .../client/gui/ContainerMagicApiary.java | 2 +- .../magicbees/client/gui/GuiMagicApiary.java | 30 ++++-- .../main/utils/net/EventFlagsUpdate.java | 77 ++++++++++++++ .../main/utils/net/NetworkEventHandler.java | 17 ++++ .../tileentity/ITileEntityFlags.java | 6 ++ .../tileentity/TileEntityMagicApiary.java | 96 +++++++++++++++--- .../assets/magicbees/textures/gui/apiary.png | Bin 5194 -> 4840 bytes 7 files changed, 204 insertions(+), 24 deletions(-) create mode 100644 src/main/java/magicbees/main/utils/net/EventFlagsUpdate.java create mode 100644 src/main/java/magicbees/tileentity/ITileEntityFlags.java diff --git a/src/main/java/magicbees/client/gui/ContainerMagicApiary.java b/src/main/java/magicbees/client/gui/ContainerMagicApiary.java index 6e1a59b..92fe6d5 100644 --- a/src/main/java/magicbees/client/gui/ContainerMagicApiary.java +++ b/src/main/java/magicbees/client/gui/ContainerMagicApiary.java @@ -56,7 +56,7 @@ public class ContainerMagicApiary extends ContainerMB { j++; } - addPlayerInventory(inventoryPlayer, 0, 109); + addPlayerInventory(inventoryPlayer, 0, 110); maxSlot = currentSlot; diff --git a/src/main/java/magicbees/client/gui/GuiMagicApiary.java b/src/main/java/magicbees/client/gui/GuiMagicApiary.java index 324286f..2b39482 100644 --- a/src/main/java/magicbees/client/gui/GuiMagicApiary.java +++ b/src/main/java/magicbees/client/gui/GuiMagicApiary.java @@ -1,15 +1,18 @@ package magicbees.client.gui; +import magicbees.main.CommonProxy; +import magicbees.tileentity.TileEntityMagicApiary; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.ResourceLocation; + +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import magicbees.main.CommonProxy; -import magicbees.tileentity.TileEntityMagicApiary; -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.Container; -import net.minecraft.util.ResourceLocation; - -import org.lwjgl.opengl.GL11; @SideOnly(Side.CLIENT) public class GuiMagicApiary extends GuiContainer @@ -52,12 +55,15 @@ public class GuiMagicApiary extends GuiContainer private static final int MUTATIONBOOST_DEST_Y = 17; private static final int MUTATIONBOOST_SRC_X = 176; private static final int MUTATIONBOOST_SRC_Y = 71; + + private GuiButton mutationButton; public GuiMagicApiary(InventoryPlayer inventoryPlayer, TileEntityMagicApiary thaumicApiary) { super(new ContainerMagicApiary(inventoryPlayer, thaumicApiary)); this.xSize = WIDTH; this.ySize = HEIGHT; + } @Override @@ -97,7 +103,7 @@ public class GuiMagicApiary extends GuiContainer } private void drawWorkBoostIcon(TileEntityMagicApiary apiary) { - if (apiary.isWorkBoosted()) { + if (apiary.isProductionBoosted()) { this.drawTexturedModalRect(this.guiLeft + WORKBOOST_DEST_X, this.guiTop + WORKBOOST_DEST_Y, WORKBOOST_SRC_X, WORKBOOST_SRC_Y, WORKBOOST_WIDTH, WORKBOOST_HEIGHT); } @@ -128,4 +134,10 @@ public class GuiMagicApiary extends GuiContainer return LIFEBAR_SRC_STAGE5_X; } } + + @Override + protected void mouseClicked(int p_73864_1_, int p_73864_2_, int p_73864_3_) { + // TODO Auto-generated method stub + super.mouseClicked(p_73864_1_, p_73864_2_, p_73864_3_); + } } diff --git a/src/main/java/magicbees/main/utils/net/EventFlagsUpdate.java b/src/main/java/magicbees/main/utils/net/EventFlagsUpdate.java new file mode 100644 index 0000000..e5042c9 --- /dev/null +++ b/src/main/java/magicbees/main/utils/net/EventFlagsUpdate.java @@ -0,0 +1,77 @@ +package magicbees.main.utils.net; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.tileentity.TileEntity; +import cpw.mods.fml.client.FMLClientHandler; +import magicbees.main.utils.ChunkCoords; +import magicbees.main.utils.LogHelper; +import magicbees.main.utils.net.NetworkEventHandler.EventType; +import magicbees.tileentity.ITileEntityFlags; + +public class EventFlagsUpdate extends EventCoords { + + private int[] flags; + + public EventFlagsUpdate(ChunkCoords position, int[] flagValues) { + super(EventType.FLAGS_UPDATE, position); + flags = flagValues; + } + + public EventFlagsUpdate(DataInputStream byteStream) { + super(EventType.FLAGS_UPDATE, byteStream); + + this.readDataFromInputStream(byteStream); + } + + public int[] getFlags() { + return flags; + } + + @Override + protected void writeDataToOutputStream(DataOutputStream byteStream) { + super.writeDataToOutputStream(byteStream); + + try { + byteStream.writeByte(flags.length); + for (int index = 0; index < flags.length; ++index) { + byteStream.writeInt(flags[index]); + } + } + catch (IOException e) { + LogHelper.error("Could not write EventFlagsUpdate data to stream."); + e.printStackTrace(); + } + } + + @Override + protected void readDataFromInputStream(DataInputStream byteStream) { + super.readDataFromInputStream(byteStream); + + try { + byte length = byteStream.readByte(); + + this.flags = new int[length]; + for (int index = 0; index < length; ++index) { + flags[index] = byteStream.readInt(); + } + } + catch (IOException e) { + LogHelper.error("Could not read EventFlagsUpdate data from stream."); + e.printStackTrace(); + } + } + + @Override + public void process(EntityPlayerMP player) { + TileEntity tile = FMLClientHandler.instance().getClient().theWorld.getTileEntity(getCoords().x, getCoords().y, getCoords().z); + + if (tile != null && tile instanceof ITileEntityFlags) { + ((ITileEntityFlags) tile).setFlags(this.flags); + } + } + +} diff --git a/src/main/java/magicbees/main/utils/net/NetworkEventHandler.java b/src/main/java/magicbees/main/utils/net/NetworkEventHandler.java index f8d880a..4d0df50 100644 --- a/src/main/java/magicbees/main/utils/net/NetworkEventHandler.java +++ b/src/main/java/magicbees/main/utils/net/NetworkEventHandler.java @@ -6,6 +6,7 @@ import io.netty.buffer.ByteBufInputStream; import java.io.DataInputStream; import java.io.IOException; +import magicbees.main.MagicBees; import magicbees.main.utils.ChunkCoords; import magicbees.main.utils.LogHelper; import magicbees.main.utils.VersionInfo; @@ -26,9 +27,14 @@ public class NetworkEventHandler { public static final String CHANNEL_NAME = VersionInfo.ModName; + public static NetworkEventHandler getInstance() { + return MagicBees.object.netHandler; + } + public enum EventType { UNKNOWN, INVENTORY_UPDATE, + FLAGS_UPDATE, ; } @@ -56,6 +62,13 @@ public class NetworkEventHandler { sendPacket(packet); } + public void sendFlagsUpdate(TileEntity entity, int[] flags) { + EventFlagsUpdate event = new EventFlagsUpdate(new ChunkCoords(entity), flags); + FMLProxyPacket packet = event.getPacket(); + + sendPacket(packet); + } + private void sendPacket(FMLProxyPacket packet) { if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { channel.sendToAll(packet); @@ -85,6 +98,10 @@ public class NetworkEventHandler { EventInventoryUpdate eventData = new EventInventoryUpdate(data); eventData.process(player); } + else if (eventId == EventType.FLAGS_UPDATE.ordinal()) { + EventFlagsUpdate eventData = new EventFlagsUpdate(data); + eventData.process(player); + } else { throw new InvalidEventTypeIndexException(""); } diff --git a/src/main/java/magicbees/tileentity/ITileEntityFlags.java b/src/main/java/magicbees/tileentity/ITileEntityFlags.java new file mode 100644 index 0000000..8506fac --- /dev/null +++ b/src/main/java/magicbees/tileentity/ITileEntityFlags.java @@ -0,0 +1,6 @@ +package magicbees.tileentity; + +public interface ITileEntityFlags { + + public void setFlags(int[] flags); +} diff --git a/src/main/java/magicbees/tileentity/TileEntityMagicApiary.java b/src/main/java/magicbees/tileentity/TileEntityMagicApiary.java index 5ff04a1..d421230 100644 --- a/src/main/java/magicbees/tileentity/TileEntityMagicApiary.java +++ b/src/main/java/magicbees/tileentity/TileEntityMagicApiary.java @@ -7,6 +7,8 @@ import magicbees.main.MagicBees; import magicbees.main.utils.ChunkCoords; import magicbees.main.utils.ItemStackUtils; import magicbees.main.utils.LogHelper; +import magicbees.main.utils.net.EventFlagsUpdate; +import magicbees.main.utils.net.NetworkEventHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.ICrafting; @@ -33,7 +35,7 @@ import forestry.api.core.IErrorState; import forestry.api.genetics.IIndividual; import forestry.core.utils.Utils; -public class TileEntityMagicApiary extends TileEntity implements ISidedInventory, IBeeHousing { +public class TileEntityMagicApiary extends TileEntity implements ISidedInventory, IBeeHousing, ITileEntityFlags { public static final String tileEntityName = CommonProxy.DOMAIN + ".magicApiary"; private GameProfile ownerProfile; @@ -47,9 +49,11 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory private static final int SLOT_PRODUCTS_COUNT = 7; private static final int AURAPROVIDER_SEARCH_RADIUS = 6; + private static int CHARGE_TIME_MUTATION = 240; + private static int CHARGE_TIME_DEATH = 80; + private static int CHARGE_TIME_PRODUCTION = 60; private IBeekeepingLogic logic; - private boolean hasAuraProvider = false; private IMagicApiaryAuraProvider auraProvider; private ChunkCoords auraProviderPosition; private BiomeGenBase biome; @@ -57,9 +61,13 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory private int displayHealth = 0; private boolean init = false; - private static final int FLAG_MUTATIONCHARGE = 1 << 0; - private static final int FLAG_DEATHCHARGE = 1 << 1; - private static final int FLAG_PRODUCTION = 1 << 2; + private static final int OFFSET_MUTATION = 0; + private static final int OFFSET_DEATH = 1; + private static final int OFFSET_PRODUCTION = 2; + private static final int FLAG_MUTATIONCHARGE = 1 << OFFSET_MUTATION; + private static final int FLAG_DEATHCHARGE = 1 << OFFSET_DEATH; + private static final int FLAG_PRODUCTIONCHARGE = 1 << OFFSET_PRODUCTION; + private long[] chargeTimestamps = new long[3]; private int flags; private IErrorState errorState = ErrorStateRegistry.getErrorState("ok"); @@ -196,7 +204,7 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory mod *= ((IHiveFrame) getStackInSlot(slotIndex).getItem()).getProductionModifier(genome, mod); } } - if (this.isWorkBoosted()) { + if (this.isProductionBoosted()) { mod = mod * 2f; } return mod; @@ -506,6 +514,9 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory ChunkCoords.writeToNBT(this.auraProviderPosition, compound); compound.setInteger("flags", this.flags); + compound.setLong("timestamp0", chargeTimestamps[0]); + compound.setLong("timestamp1", chargeTimestamps[1]); + compound.setLong("timestamp2", chargeTimestamps[2]); } @Override @@ -529,6 +540,9 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory this.auraProviderPosition = ChunkCoords.readFromNBT(compound); this.flags = compound.getInteger("flags"); + this.chargeTimestamps[0] = compound.getLong("timestamp0"); + this.chargeTimestamps[1] = compound.getLong("timestamp1"); + this.chargeTimestamps[2] = compound.getLong("timestamp2"); } public float getExactTemperature() { @@ -576,7 +590,7 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory } public void updateServerSide() { - if (!this.hasAuraProvider) { + if (this.auraProvider == null) { findAuraProvider(); } else { @@ -618,20 +632,65 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory iCrafting.sendProgressBarUpdate(container, 1, logic.getTotalBreedingTime()); } - public boolean isWorkBoosted() { - return false; + public boolean isProductionBoosted() { + return (flags & FLAG_PRODUCTIONCHARGE) == FLAG_PRODUCTIONCHARGE; } public boolean isDeathRateBoosted() { - return false; + return (flags & FLAG_DEATHCHARGE) == FLAG_DEATHCHARGE; } public boolean isMutationBoosted() { - return false; + return (flags & FLAG_MUTATIONCHARGE) == FLAG_MUTATIONCHARGE; } private void updateAuraProvider() { + int oldFlags = flags; + if (!isMutationBoosted()) { + if (this.auraProvider.getMutationCharge()) { + flags |= FLAG_MUTATIONCHARGE; + chargeTimestamps[OFFSET_MUTATION] = worldObj.getTotalWorldTime(); + } + } + else { + if (chargeTimestamps[OFFSET_MUTATION] + CHARGE_TIME_MUTATION <= worldObj.getTotalWorldTime()) { + if (!this.auraProvider.getMutationCharge()) { + flags = flags & ~FLAG_MUTATIONCHARGE; + } + } + } + + if (!isDeathRateBoosted()) { + if (this.auraProvider.getDeathRateCharge()) { + flags |= FLAG_DEATHCHARGE; + chargeTimestamps[OFFSET_DEATH] = worldObj.getTotalWorldTime(); + } + } + else { + if (chargeTimestamps[OFFSET_DEATH] + CHARGE_TIME_DEATH <= worldObj.getTotalWorldTime()) { + if (!this.auraProvider.getDeathRateCharge()) { + flags = flags & ~FLAG_DEATHCHARGE; + } + } + } + + if (!isProductionBoosted()) { + if (this.auraProvider.getProductionCharge()) { + flags |= FLAG_PRODUCTIONCHARGE; + chargeTimestamps[OFFSET_PRODUCTION] = worldObj.getTotalWorldTime(); + } + } + else { + if (chargeTimestamps[OFFSET_PRODUCTION] + CHARGE_TIME_PRODUCTION <= worldObj.getTotalWorldTime()) { + if (!this.auraProvider.getProductionCharge()) { + flags = flags & ~FLAG_PRODUCTIONCHARGE; + } + } + } + if (oldFlags != flags) { + NetworkEventHandler.getInstance().sendFlagsUpdate(this, new int[] {flags}); + } } private static final int MAX_BLOCKS_SEARCH_PER_CHECK = (AURAPROVIDER_SEARCH_RADIUS * 2 + 1) * 2; @@ -650,10 +709,13 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory else { // Will end up here after loading from save with a valid auraProvider. if (locationHasAuraProvider(auraProviderPosition.x, auraProviderPosition.y, auraProviderPosition.z)) { - this.auraProvider = (IMagicApiaryAuraProvider)(worldObj.getTileEntity(auraProviderPosition.x, + IMagicApiaryAuraProvider provider = (IMagicApiaryAuraProvider)(worldObj.getTileEntity(auraProviderPosition.x, auraProviderPosition.y, auraProviderPosition.x)); - this.hasAuraProvider = true; + if (provider == null) { + // ... well, it WAS here... + this.auraProviderPosition = null; + } return; } } @@ -668,7 +730,6 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory if (locationHasAuraProvider(x, y, z)) { LogHelper.info("Apiary found aura provider!"); this.auraProvider = (IMagicApiaryAuraProvider)(worldObj.getTileEntity(x, y, z)); - this.hasAuraProvider = true; saveAuraProviderPosition(x, y, z); return; } @@ -711,4 +772,11 @@ public class TileEntityMagicApiary extends TileEntity implements ISidedInventory } return false; } + + @Override + public void setFlags(int[] flagArray) { + if (flagArray.length == 1) { + this.flags = flagArray[0]; + } + } } diff --git a/src/main/resources/assets/magicbees/textures/gui/apiary.png b/src/main/resources/assets/magicbees/textures/gui/apiary.png index 6dae19a06c2a4cd560e9723c82b3f247bb281ad2..720edde3565ee2b76eb75c2efad268b32cd8efa7 100644 GIT binary patch delta 3858 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 Bkb?jK delta 4264 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