From 2c49c49441971082fc9a31bd75a53c6038a95f6f Mon Sep 17 00:00:00 2001 From: WayofTime Date: Sun, 21 Feb 2016 20:10:56 -0500 Subject: [PATCH] Started work on Demon Will Inversion system. --- .../bloodmagic/api/soul/DemonWillHolder.java | 99 +++++++++++++ .../WayofTime/bloodmagic/demonAura/PosXY.java | 36 +++++ .../bloodmagic/demonAura/WillChunk.java | 41 ++++++ .../bloodmagic/demonAura/WillWorld.java | 41 ++++++ .../demonAura/WorldDemonWillHandler.java | 135 ++++++++++++++++++ .../bloodmagic/util/handler/EventHandler.java | 88 ++++++++++++ 6 files changed, 440 insertions(+) create mode 100644 src/main/java/WayofTime/bloodmagic/api/soul/DemonWillHolder.java create mode 100644 src/main/java/WayofTime/bloodmagic/demonAura/PosXY.java create mode 100644 src/main/java/WayofTime/bloodmagic/demonAura/WillChunk.java create mode 100644 src/main/java/WayofTime/bloodmagic/demonAura/WillWorld.java create mode 100644 src/main/java/WayofTime/bloodmagic/demonAura/WorldDemonWillHandler.java diff --git a/src/main/java/WayofTime/bloodmagic/api/soul/DemonWillHolder.java b/src/main/java/WayofTime/bloodmagic/api/soul/DemonWillHolder.java new file mode 100644 index 00000000..70c9719a --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/soul/DemonWillHolder.java @@ -0,0 +1,99 @@ +package WayofTime.bloodmagic.api.soul; + +import java.util.HashMap; +import java.util.Map.Entry; + +import net.minecraft.nbt.NBTTagCompound; + +public class DemonWillHolder +{ + public HashMap willMap = new HashMap(); + + public double addWill(EnumDemonWillType type, double amount, double max) + { + double current = 0; + if (willMap.containsKey(type)) + { + current = willMap.get(type); + } + + double added = Math.min(max - current, amount); + addWill(type, amount); + + return added; + } + + public void addWill(EnumDemonWillType type, double amount) + { + if (willMap.containsKey(type)) + { + willMap.put(type, amount + willMap.get(type)); + } else + { + willMap.put(type, amount); + } + } + + public double drainWill(EnumDemonWillType type, double amount) + { + if (willMap.containsKey(type)) + { + double current = willMap.get(type); + double reduced = Math.min(current, amount); + + if (reduced >= current) + { + willMap.remove(type); + } else + { + willMap.put(type, current - reduced); + } + + return reduced; + } + + return 0; + } + + public double getWill(EnumDemonWillType type) + { + if (willMap.containsKey(type)) + { + return willMap.get(type); + } + + return 0; + } + + public void readFromNBT(NBTTagCompound tag, String key) + { + NBTTagCompound willTag = tag.getCompoundTag(key); + + willMap.clear(); + + for (EnumDemonWillType type : EnumDemonWillType.values()) + { + double amount = willTag.getDouble("EnumWill" + type.getName()); + if (amount > 0) + { + willMap.put(type, amount); + } + } + } + + public void writeToNBT(NBTTagCompound tag, String key) + { + NBTTagCompound willTag = new NBTTagCompound(); + for (Entry entry : willMap.entrySet()) + { + willTag.setDouble("EnumWill" + entry.getKey().getName(), entry.getValue()); + } + + tag.setTag(key, willTag); + } + + public void clearWill() + { + willMap.clear(); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/demonAura/PosXY.java b/src/main/java/WayofTime/bloodmagic/demonAura/PosXY.java new file mode 100644 index 00000000..b3971dd7 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/demonAura/PosXY.java @@ -0,0 +1,36 @@ +package WayofTime.bloodmagic.demonAura; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@EqualsAndHashCode +@ToString +@NoArgsConstructor +@AllArgsConstructor +@Setter +public class PosXY implements Comparable +{ + public int x; + public int y; + + @Override + public int compareTo(PosXY c) + { + return this.y == c.y ? this.x - c.x : this.y - c.y; + } + + public float getDistanceSquared(int x, int z) + { + float f = this.x - x; + float f2 = this.y - z; + return f * f + f2 * f2; + } + + public float getDistanceSquaredToChunkCoordinates(PosXY c) + { + return getDistanceSquared(c.x, c.y); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/demonAura/WillChunk.java b/src/main/java/WayofTime/bloodmagic/demonAura/WillChunk.java new file mode 100644 index 00000000..abe0617b --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/demonAura/WillChunk.java @@ -0,0 +1,41 @@ +package WayofTime.bloodmagic.demonAura; + +import java.lang.ref.WeakReference; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.world.chunk.Chunk; +import WayofTime.bloodmagic.api.soul.DemonWillHolder; + +@Getter +@Setter +public class WillChunk +{ + PosXY loc; + private short base; + private DemonWillHolder currentWill = new DemonWillHolder(); + private WeakReference chunkRef; + + public WillChunk(PosXY loc) + { + this.loc = loc; + } + + public WillChunk(Chunk chunk, short base, DemonWillHolder currentWill) + { + this.loc = new PosXY(chunk.xPosition, chunk.zPosition); + this.chunkRef = new WeakReference(chunk); + this.base = base; + this.currentWill = currentWill; + } + + public boolean isModified() + { + if ((this.chunkRef != null) && (this.chunkRef.get() != null)) + { + return ((Chunk) this.chunkRef.get()).needsSaving(false); + } + + return false; + } +} diff --git a/src/main/java/WayofTime/bloodmagic/demonAura/WillWorld.java b/src/main/java/WayofTime/bloodmagic/demonAura/WillWorld.java new file mode 100644 index 00000000..c932b363 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/demonAura/WillWorld.java @@ -0,0 +1,41 @@ +package WayofTime.bloodmagic.demonAura; + +import java.util.concurrent.ConcurrentHashMap; + +import lombok.Getter; +import lombok.Setter; + +public class WillWorld +{ + int dim; + @Getter + @Setter + ConcurrentHashMap willChunks = new ConcurrentHashMap(); + +// private static ConcurrentHashMap nodeTickets = new ConcurrentHashMap(); + + public WillWorld(int dim) + { + this.dim = dim; + } + + public WillChunk getWillChunkAt(int x, int y) + { + return getWillChunkAt(new PosXY(x, y)); + } + + public WillChunk getWillChunkAt(PosXY loc) + { + return this.willChunks.get(loc); + } + +// public static ConcurrentHashMap getNodeTickets() +// { +// return nodeTickets; +// } +// +// public static void setNodeTickets(ConcurrentHashMap nodeTickets) +// { +// nodeTickets = nodeTickets; +// } +} diff --git a/src/main/java/WayofTime/bloodmagic/demonAura/WorldDemonWillHandler.java b/src/main/java/WayofTime/bloodmagic/demonAura/WorldDemonWillHandler.java new file mode 100644 index 00000000..31f3347e --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/demonAura/WorldDemonWillHandler.java @@ -0,0 +1,135 @@ +package WayofTime.bloodmagic.demonAura; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import WayofTime.bloodmagic.api.BloodMagicAPI; +import WayofTime.bloodmagic.api.soul.DemonWillHolder; +import WayofTime.bloodmagic.api.soul.EnumDemonWillType; + +public class WorldDemonWillHandler +{ + static ConcurrentHashMap containedWills = new ConcurrentHashMap(); + public static ConcurrentHashMap> dirtyChunks = new ConcurrentHashMap>(); + public static ConcurrentHashMap taintTrigger = new ConcurrentHashMap(); + + public static WillWorld getAuraWorld(int dim) + { + return containedWills.get(dim); + } + + public static WillChunk getWillChunk(int dim, int x, int y) + { + if (containedWills.containsKey(dim)) + { + return (containedWills.get(dim)).getWillChunkAt(x, y); + } + + return null; + } + + public static void addWillWorld(int dim) + { + if (!containedWills.containsKey(dim)) + { + containedWills.put(dim, new WillWorld(dim)); + BloodMagicAPI.getLogger().info("Creating demon will cache for world " + dim); + } + } + + public static void removeWillWorld(int dim) + { + containedWills.remove(dim); + BloodMagicAPI.getLogger().info("Removing demon will cache for world " + dim); + } + + public static void addWillChunk(int dim, Chunk chunk, short base, DemonWillHolder currentWill) + { + WillWorld aw = containedWills.get(dim); + if (aw == null) + { + aw = new WillWorld(dim); + } + aw.getWillChunks().put(new PosXY(chunk.xPosition, chunk.zPosition), new WillChunk(chunk, base, currentWill)); + + containedWills.put(dim, aw); + } + + public static void removeWillChunk(int dim, int x, int y) + { + WillWorld aw = containedWills.get(dim); + if (aw != null) + { + WillChunk chunk = aw.getWillChunks().remove(new PosXY(x, y)); + if (chunk != null) + { + markChunkAsDirty(chunk, dim); + } + } + } + + public static double drainWill(World world, BlockPos pos, EnumDemonWillType type, double amount, boolean doDrain) + { + WillChunk willChunk = getWillChunk(world, pos); + + DemonWillHolder currentWill = willChunk.getCurrentWill(); + double drain = Math.min(currentWill.getWill(type), amount); + if (!doDrain) + { + return drain; + } + + drain = currentWill.drainWill(type, drain); + markChunkAsDirty(willChunk, world.provider.getDimensionId()); + + return drain; + } + + public static double fillWillToMaximum(World world, BlockPos pos, EnumDemonWillType type, double amount, double max, boolean doFill) + { + WillChunk willChunk = getWillChunk(world, pos); + + DemonWillHolder currentWill = willChunk.getCurrentWill(); + double fill = Math.min(amount, max - currentWill.getWill(type)); + if (!doFill) + { + return fill; + } + + fill = currentWill.addWill(type, amount, max); + markChunkAsDirty(willChunk, world.provider.getDimensionId()); + + return fill; + } + + public static WillChunk getWillChunk(World world, BlockPos pos) + { + return getWillChunk(world.provider.getDimensionId(), pos.getX() >> 4, pos.getZ() >> 4); + } + + private static void markChunkAsDirty(WillChunk chunk, int dim) + { + if (chunk.isModified()) + { + return; + } + PosXY pos = new PosXY(chunk.loc.x, chunk.loc.y); + if (!dirtyChunks.containsKey(dim)) + { + dirtyChunks.put(dim, new CopyOnWriteArrayList()); + } + CopyOnWriteArrayList dc = dirtyChunks.get(dim); + if (!dc.contains(pos)) + { + dc.add(pos); + } + } + + public static void generateWill(Chunk chunk) + { + addWillChunk(chunk.getWorld().provider.getDimensionId(), chunk, (short) 1, new DemonWillHolder()); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/util/handler/EventHandler.java b/src/main/java/WayofTime/bloodmagic/util/handler/EventHandler.java index cd190e3a..2122e9f6 100644 --- a/src/main/java/WayofTime/bloodmagic/util/handler/EventHandler.java +++ b/src/main/java/WayofTime/bloodmagic/util/handler/EventHandler.java @@ -1,8 +1,10 @@ package WayofTime.bloodmagic.util.handler; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Random; +import java.util.concurrent.CopyOnWriteArrayList; import net.minecraft.block.Block; import net.minecraft.enchantment.Enchantment; @@ -16,8 +18,11 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.BlockPos; import net.minecraft.util.DamageSource; +import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.AnvilUpdateEvent; @@ -33,11 +38,15 @@ import net.minecraftforge.event.entity.player.FillBucketEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.fml.client.event.ConfigChangedEvent; import net.minecraftforge.fml.common.eventhandler.Event; import net.minecraftforge.fml.common.eventhandler.Event.Result; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.relauncher.Side; +import thaumcraft.common.lib.aura.AuraHandler; import WayofTime.bloodmagic.ConfigHandler; import WayofTime.bloodmagic.api.BloodMagicAPI; import WayofTime.bloodmagic.api.Constants; @@ -47,6 +56,7 @@ import WayofTime.bloodmagic.api.event.TeleposeEvent; import WayofTime.bloodmagic.api.iface.IBindable; import WayofTime.bloodmagic.api.iface.IUpgradeTrainer; import WayofTime.bloodmagic.api.livingArmour.LivingArmourUpgrade; +import WayofTime.bloodmagic.api.soul.DemonWillHolder; import WayofTime.bloodmagic.api.soul.EnumDemonWillType; import WayofTime.bloodmagic.api.soul.IDemonWill; import WayofTime.bloodmagic.api.soul.IDemonWillWeapon; @@ -55,6 +65,9 @@ import WayofTime.bloodmagic.api.util.helper.BindableHelper; import WayofTime.bloodmagic.api.util.helper.NBTHelper; import WayofTime.bloodmagic.api.util.helper.PlayerHelper; import WayofTime.bloodmagic.block.BlockAltar; +import WayofTime.bloodmagic.demonAura.PosXY; +import WayofTime.bloodmagic.demonAura.WillChunk; +import WayofTime.bloodmagic.demonAura.WorldDemonWillHandler; import WayofTime.bloodmagic.entity.projectile.EntitySentientArrow; import WayofTime.bloodmagic.item.ItemAltarMaker; import WayofTime.bloodmagic.item.ItemUpgradeTome; @@ -87,6 +100,7 @@ import com.google.common.base.Strings; public class EventHandler { Random random = new Random(); + HashMap serverTicks = new HashMap(); @SubscribeEvent(priority = EventPriority.HIGHEST) public void onEntityDeath(LivingDeathEvent event) @@ -118,6 +132,80 @@ public class EventHandler } } + @SubscribeEvent + public void onServerWorldTick(TickEvent.WorldTickEvent event) + { + if (event.side == Side.CLIENT) + { + return; + } + int dim = event.world.provider.getDimensionId(); + if (event.phase == TickEvent.Phase.END) + { + if (!this.serverTicks.containsKey(Integer.valueOf(dim))) + { + this.serverTicks.put(Integer.valueOf(dim), Integer.valueOf(0)); + } + + int ticks = ((Integer) this.serverTicks.get(Integer.valueOf(dim))).intValue(); + + if (ticks % 20 == 0) + { + CopyOnWriteArrayList dirtyChunks = WorldDemonWillHandler.dirtyChunks.get(Integer.valueOf(dim)); + if ((dirtyChunks != null) && (dirtyChunks.size() > 0)) + { + for (PosXY pos : dirtyChunks) + { + event.world.markChunkDirty(new BlockPos(pos.x * 16, 5, pos.y * 16), null); + } + + dirtyChunks.clear(); + } + } + + this.serverTicks.put(Integer.valueOf(dim), Integer.valueOf(ticks + 1)); + } + + } + + @SubscribeEvent + public void chunkSave(ChunkDataEvent.Save event) + { + int dim = event.world.provider.getDimensionId(); + ChunkCoordIntPair loc = event.getChunk().getChunkCoordIntPair(); + + NBTTagCompound nbt = new NBTTagCompound(); + event.getData().setTag("BloodMagic", nbt); + + WillChunk ac = WorldDemonWillHandler.getWillChunk(dim, loc.chunkXPos, loc.chunkZPos); + if (ac != null) + { + nbt.setShort("base", ac.getBase()); + ac.getCurrentWill().writeToNBT(nbt, "current"); + if (!event.getChunk().isLoaded()) + { + WorldDemonWillHandler.removeWillChunk(dim, loc.chunkXPos, loc.chunkZPos); + } + } + } + + @SubscribeEvent + public void chunkLoad(ChunkDataEvent.Load event) + { + int dim = event.world.provider.getDimensionId(); + if (event.getData().getCompoundTag("BloodMagic").hasKey("base")) + { + NBTTagCompound nbt = event.getData().getCompoundTag("BloodMagic"); + short base = nbt.getShort("base"); + DemonWillHolder current = new DemonWillHolder(); + current.readFromNBT(nbt, "current"); + WorldDemonWillHandler.addWillChunk(dim, event.getChunk(), base, current); + } else + { + WorldDemonWillHandler.generateWill(event.getChunk()); + } + } + @SubscribeEvent(priority = EventPriority.HIGHEST) public void onEntityUpdate(LivingEvent.LivingUpdateEvent event) {