diff --git a/src/main/java/vazkii/botania/api/internal/IManaBurst.java b/src/main/java/vazkii/botania/api/internal/IManaBurst.java index 8cf38ed68..12b711211 100644 --- a/src/main/java/vazkii/botania/api/internal/IManaBurst.java +++ b/src/main/java/vazkii/botania/api/internal/IManaBurst.java @@ -10,6 +10,8 @@ */ package vazkii.botania.api.internal; +import java.util.UUID; + import net.minecraft.item.ItemStack; import net.minecraft.util.ChunkCoordinates; @@ -61,5 +63,11 @@ public interface IManaBurst { public int getTicksExisted(); public void setFake(boolean fake); + + public void setShooterUUID(UUID uuid); + + public UUID getShooterUIID(); + + public void ping(); } diff --git a/src/main/java/vazkii/botania/api/mana/IIdentifiable.java b/src/main/java/vazkii/botania/api/mana/IIdentifiable.java new file mode 100644 index 000000000..a8cb6f042 --- /dev/null +++ b/src/main/java/vazkii/botania/api/mana/IIdentifiable.java @@ -0,0 +1,23 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under the + * Botania License: http://botaniamod.net/license.php + * + * File Created @ [Jun 19, 2015, 10:05:24 PM (GMT)] + */ +package vazkii.botania.api.mana; + +import java.util.UUID; + +/** + * This interface marks a TileEntity that can be identified through + * an UUID. This UUID must presist between sessions. + */ +public interface IIdentifiable { + + public UUID getIdentifier(); + +} diff --git a/src/main/java/vazkii/botania/api/mana/IManaSpreader.java b/src/main/java/vazkii/botania/api/mana/IManaSpreader.java index 1121f5f49..0dda30a83 100644 --- a/src/main/java/vazkii/botania/api/mana/IManaSpreader.java +++ b/src/main/java/vazkii/botania/api/mana/IManaSpreader.java @@ -16,7 +16,7 @@ package vazkii.botania.api.mana; * by which can fire mana bursts as a spreader. * */ -public interface IManaSpreader extends IManaBlock { +public interface IManaSpreader extends IManaBlock, IPingable { public float getRotationX(); diff --git a/src/main/java/vazkii/botania/api/mana/IPingable.java b/src/main/java/vazkii/botania/api/mana/IPingable.java new file mode 100644 index 000000000..ad067a16d --- /dev/null +++ b/src/main/java/vazkii/botania/api/mana/IPingable.java @@ -0,0 +1,31 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under the + * Botania License: http://botaniamod.net/license.php + * + * File Created @ [Jun 19, 2015, 9:52:05 PM (GMT)] + */ +package vazkii.botania.api.mana; + +import java.util.UUID; + +import vazkii.botania.api.internal.IManaBurst; + +/** + * This describes an interface of a Mana Sender block that should be able to pingbackable + * by a burst to tell it that the burst is still alive. + */ +public interface IPingable extends IIdentifiable { + + /** + * Pings this object back, telling it that the burst passed in is still alive + * in the world. The UUID parameter should be the UUID with which the burst + * was created, this is used to let the object handle the check for if it's the + * correct ID internally. IManaBurst implementations should do this every tick. + */ + public void pingback(IManaBurst burst, UUID expectedIdentity); + +} diff --git a/src/main/java/vazkii/botania/common/block/tile/mana/TileSpreader.java b/src/main/java/vazkii/botania/common/block/tile/mana/TileSpreader.java index 8912c1be3..ad8506c36 100644 --- a/src/main/java/vazkii/botania/common/block/tile/mana/TileSpreader.java +++ b/src/main/java/vazkii/botania/common/block/tile/mana/TileSpreader.java @@ -11,6 +11,7 @@ package vazkii.botania.common.block.tile.mana; import java.util.List; +import java.util.UUID; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; @@ -62,7 +63,12 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, private static final int MAX_MANA = 1000; private static final int ULTRA_MAX_MANA = 6400; + private static final int TICKS_ALLOWED_WITHOUT_PINGBACK = 20; + private static final double PINGBACK_EXPIRED_SEARCH_DISTANCE = 0.5; + private static final String TAG_HAS_IDENTITY = "hasIdentity"; + private static final String TAG_UUID_MOST = "uuidMost"; + private static final String TAG_UUID_LEAST = "uuidLeast"; private static final String TAG_MANA = "mana"; private static final String TAG_KNOWN_MANA = "knownMana"; private static final String TAG_REQUEST_UPDATE = "requestUpdate"; @@ -70,6 +76,10 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, private static final String TAG_ROTATION_Y = "rotationY"; private static final String TAG_PADDING_COLOR = "paddingColor"; private static final String TAG_CAN_SHOOT_BURST = "canShootBurst"; + private static final String TAG_PINGBACK_TICKS = "pingbackTicks"; + private static final String TAG_LAST_PINGBACK_X = "lastPingbackX"; + private static final String TAG_LAST_PINGBACK_Y = "lastPingbackY"; + private static final String TAG_LAST_PINGBACK_Z = "lastPingbackZ"; private static final String TAG_FORCE_CLIENT_BINDING_X = "forceClientBindingX"; private static final String TAG_FORCE_CLIENT_BINDING_Y = "forceClientBindingY"; @@ -105,6 +115,8 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, public static boolean staticDreamwood = false; public static boolean staticUltra = false; + UUID identity; + int mana; int knownMana = -1; public float rotationX, rotationY; @@ -120,7 +132,12 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, public boolean canShootBurst = true; public int lastBurstDeathTick = -1; public int burstParticleTick = 0; - + + public int pingbackTicks = 0; + public double lastPingbackX = 0; + public double lastPingbackY = -1; + public double lastPingbackZ = 0; + List lastTentativeBurst; boolean invalidTentativeBurst = false; @@ -179,8 +196,28 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, if(needsNewBurstSimulation()) checkForReceiver(); + if(!canShootBurst) + if(pingbackTicks <= 0) { + double x = lastPingbackX; + double y = lastPingbackY; + double z = lastPingbackZ; + AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(x, y, z, x, y, z).expand(PINGBACK_EXPIRED_SEARCH_DISTANCE, PINGBACK_EXPIRED_SEARCH_DISTANCE, PINGBACK_EXPIRED_SEARCH_DISTANCE); + List bursts = worldObj.getEntitiesWithinAABB(IManaBurst.class, aabb); + IManaBurst found = null; + UUID identity = getIdentifier(); + for(IManaBurst burst : bursts) + if(burst != null && identity.equals(burst.getShooterUIID())) { + found = burst; + break; + } + + if(found != null) + found.ping(); + else setCanShoot(true); + } else pingbackTicks--; + boolean shouldShoot = !redstone; - + if(isRedstone()) shouldShoot = redstone && !redstoneLastTick; @@ -202,12 +239,23 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, @Override public void writeCustomNBT(NBTTagCompound cmp) { super.writeCustomNBT(cmp); + + UUID identity = getIdentifier(); + cmp.setBoolean(TAG_HAS_IDENTITY, true); + cmp.setLong(TAG_UUID_MOST, identity.getMostSignificantBits()); + cmp.setLong(TAG_UUID_LEAST, identity.getLeastSignificantBits()); + cmp.setInteger(TAG_MANA, mana); cmp.setFloat(TAG_ROTATION_X, rotationX); cmp.setFloat(TAG_ROTATION_Y, rotationY); cmp.setBoolean(TAG_REQUEST_UPDATE, requestsClientUpdate); cmp.setInteger(TAG_PADDING_COLOR, paddingColor); cmp.setBoolean(TAG_CAN_SHOOT_BURST, canShootBurst); + + cmp.setInteger(TAG_PINGBACK_TICKS, pingbackTicks); + cmp.setDouble(TAG_LAST_PINGBACK_X, lastPingbackX); + cmp.setDouble(TAG_LAST_PINGBACK_Y, lastPingbackY); + cmp.setDouble(TAG_LAST_PINGBACK_Z, lastPingbackZ); cmp.setString(TAG_INPUT_KEY, inputKey); cmp.setString(TAG_OUTPUT_KEY, outputKey); @@ -223,13 +271,22 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, cmp.setFloat(TAG_FORCED_MANA_LOSS_PER_TICK, mmForcedManaLossPerTick); cmp.setFloat(TAG_FORCED_GRAVITY, mmForcedGravity); cmp.setFloat(TAG_FORCED_VELOCITY_MULTIPLIER, mmForcedVelocityMultiplier); - + requestsClientUpdate = false; } @Override public void readCustomNBT(NBTTagCompound cmp) { super.readCustomNBT(cmp); + + if(cmp.getBoolean(TAG_HAS_IDENTITY)) { + long most = cmp.getLong(TAG_UUID_MOST); + long least = cmp.getLong(TAG_UUID_LEAST); + UUID identity = getIdentifierUnsafe(); + if(identity == null || most != identity.getMostSignificantBits() || least != identity.getLeastSignificantBits()) + identity = new UUID(most, least); + } else getIdentifier(); + mana = cmp.getInteger(TAG_MANA); rotationX = cmp.getFloat(TAG_ROTATION_X); rotationY = cmp.getFloat(TAG_ROTATION_Y); @@ -254,6 +311,11 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, paddingColor = cmp.getInteger(TAG_PADDING_COLOR); if(cmp.hasKey(TAG_CAN_SHOOT_BURST)) canShootBurst = cmp.getBoolean(TAG_CAN_SHOOT_BURST); + + pingbackTicks = cmp.getInteger(TAG_PINGBACK_TICKS); + lastPingbackX = cmp.getDouble(TAG_LAST_PINGBACK_X); + lastPingbackY = cmp.getDouble(TAG_LAST_PINGBACK_Y); + lastPingbackZ = cmp.getDouble(TAG_LAST_PINGBACK_Z); if(requestsClientUpdate && worldObj != null) { int x = cmp.getInteger(TAG_FORCE_CLIENT_BINDING_X); @@ -344,12 +406,12 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, if(burst != null) { if(!worldObj.isRemote) { mana -= burst.getStartingMana(); + burst.setShooterUUID(getIdentifier()); worldObj.spawnEntityInWorld(burst); + burst.ping(); if(!ConfigHandler.silentSpreaders) worldObj.playSoundEffect(xCoord, yCoord, zCoord, "botania:spreaderFire", 0.05F * (paddingColor != -1 ? 0.2F : 1F), 0.7F + 0.3F * (float) Math.random()); } - - canShootBurst = false; } } } @@ -628,4 +690,27 @@ public class TileSpreader extends TileSimpleInventory implements IManaCollector, public void setLastBurstDeathTick(int i) { lastBurstDeathTick = i; } + + @Override + public void pingback(IManaBurst burst, UUID expectedIdentity) { + if(getIdentifier().equals(expectedIdentity)) { + pingbackTicks = TICKS_ALLOWED_WITHOUT_PINGBACK; + Entity e = (Entity) burst; + lastPingbackX = e.posX; + lastPingbackY = e.posY; + lastPingbackZ = e.posZ; + setCanShoot(false); + } + } + + @Override + public UUID getIdentifier() { + if(identity == null) + identity = UUID.randomUUID(); + return identity; + } + + public UUID getIdentifierUnsafe() { + return identity; + } } diff --git a/src/main/java/vazkii/botania/common/entity/EntityManaBurst.java b/src/main/java/vazkii/botania/common/entity/EntityManaBurst.java index 3b578eed6..893f767fc 100644 --- a/src/main/java/vazkii/botania/common/entity/EntityManaBurst.java +++ b/src/main/java/vazkii/botania/common/entity/EntityManaBurst.java @@ -14,6 +14,7 @@ import java.awt.Color; import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.UUID; import net.minecraft.block.Block; import net.minecraft.block.BlockBush; @@ -42,6 +43,7 @@ import vazkii.botania.api.mana.IManaCollisionGhost; import vazkii.botania.api.mana.IManaReceiver; import vazkii.botania.api.mana.IManaSpreader; import vazkii.botania.api.mana.IManaTrigger; +import vazkii.botania.api.mana.IPingable; import vazkii.botania.api.mana.IThrottledPacket; import vazkii.botania.common.Botania; import vazkii.botania.common.core.handler.ConfigHandler; @@ -64,6 +66,9 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { private static final String TAG_LAST_MOTION_X = "lastMotionX"; private static final String TAG_LAST_MOTION_Y = "lastMotionY"; private static final String TAG_LAST_MOTION_Z = "lastMotionZ"; + private static final String TAG_HAS_SHOOTER = "hasShooter"; + private static final String TAG_SHOOTER_UUID_MOST = "shooterUUIDMost"; + private static final String TAG_SHOOTER_UUID_LEAST = "shooterUUIDLeast"; boolean fake = false; @@ -74,6 +79,7 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { boolean fullManaLastTick = true; + UUID shooterIdentity = null; int _ticksExisted = 0; boolean scanBeam = false; public List propsList = new ArrayList(); @@ -352,12 +358,8 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { setTicksExisted(getTicksExisted() + 1); superUpdate(); - if(!fake && !isDead) { - ChunkCoordinates coords = getBurstSourceChunkCoordinates(); - TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ); - if(tile != null && tile instanceof IManaSpreader) - ((IManaSpreader) tile).setCanShoot(false); - } + if(!fake && !isDead) + ping(); ILensEffect lens = getLensInstance(); if(lens != null) @@ -437,6 +439,14 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { par1nbtTagCompound.setDouble(TAG_LAST_MOTION_X, motionX); par1nbtTagCompound.setDouble(TAG_LAST_MOTION_Y, motionY); par1nbtTagCompound.setDouble(TAG_LAST_MOTION_Z, motionZ); + + UUID identity = getShooterUIID(); + boolean hasShooter = identity != null; + par1nbtTagCompound.setBoolean(TAG_HAS_SHOOTER, hasShooter); + if(hasShooter) { + par1nbtTagCompound.setLong(TAG_SHOOTER_UUID_MOST, identity.getMostSignificantBits()); + par1nbtTagCompound.setLong(TAG_SHOOTER_UUID_LEAST, identity.getLeastSignificantBits()); + } } @Override @@ -467,6 +477,15 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { double lastMotionZ = par1nbtTagCompound.getDouble(TAG_LAST_MOTION_Z); setMotion(lastMotionX, lastMotionY, lastMotionZ); + + boolean hasShooter = par1nbtTagCompound.getBoolean(TAG_HAS_SHOOTER); + if(hasShooter) { + long most = par1nbtTagCompound.getLong(TAG_SHOOTER_UUID_MOST); + long least = par1nbtTagCompound.getLong(TAG_SHOOTER_UUID_LEAST); + UUID identity = getShooterUIID(); + if(identity == null || most != identity.getMostSignificantBits() || least != identity.getLeastSignificantBits()) + shooterIdentity = new UUID(most, least); + } } public void particles() { @@ -626,12 +645,17 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { super.setDead(); if(!fake) { - ChunkCoordinates coords = getBurstSourceChunkCoordinates(); - TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ); + TileEntity tile = getShooter(); if(tile != null && tile instanceof IManaSpreader) ((IManaSpreader) tile).setCanShoot(true); } else setDeathTicksForFakeParticle(); } + + public TileEntity getShooter() { + ChunkCoordinates coords = getBurstSourceChunkCoordinates(); + TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ); + return tile; + } @Override protected float getGravityVelocity() { @@ -781,20 +805,35 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { return x + ":" + y + ":" + z; } + @Override + public void setShooterUUID(UUID uuid) { + shooterIdentity = uuid; + } + + @Override + public UUID getShooterUIID() { + return shooterIdentity; + } + + @Override + public void ping() { + TileEntity tile = getShooter(); + if(tile != null && tile instanceof IPingable) + ((IPingable) tile).pingback(this, getShooterUIID()); + } + public boolean shouldDoFakeParticles() { if(ConfigHandler.staticWandBeam) return true; - ChunkCoordinates coords = getBurstSourceChunkCoordinates(); - TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ); + TileEntity tile = getShooter(); if(tile != null && tile instanceof IManaSpreader) return getMana() != getStartingMana() && fullManaLastTick || Math.abs(((IManaSpreader) tile).getBurstParticleTick() - getTicksExisted()) < 4; return false; } public void incrementFakeParticleTick() { - ChunkCoordinates coords = getBurstSourceChunkCoordinates(); - TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ); + TileEntity tile = getShooter(); if(tile != null && tile instanceof IManaSpreader) { IManaSpreader spreader = (IManaSpreader) tile; spreader.setBurstParticleTick(spreader.getBurstParticleTick()+2); @@ -842,4 +881,5 @@ public class EntityManaBurst extends EntityThrowable implements IManaBurst { return block == this.block && meta == this.meta; } } + } diff --git a/src/main/java/vazkii/botania/common/lib/LibMisc.java b/src/main/java/vazkii/botania/common/lib/LibMisc.java index 41a1c2234..f8a98eaa8 100644 --- a/src/main/java/vazkii/botania/common/lib/LibMisc.java +++ b/src/main/java/vazkii/botania/common/lib/LibMisc.java @@ -19,7 +19,7 @@ public final class LibMisc { public static final String MOD_NAME = MOD_ID; public static final String BUILD = "GRADLE:BUILD"; public static final String VERSION = "GRADLE:VERSION-" + BUILD; - public static final String DEPENDENCIES = "required-after:Forge@[10.13.2.1236,);required-after:Baubles;after:Thaumcraft"; + public static final String DEPENDENCIES = "required-after:Baubles;after:Thaumcraft"; // Network Contants public static final String NETWORK_CHANNEL = MOD_ID;