diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java index eb76f1f..4fc7b07 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java @@ -1,8 +1,17 @@ package com.seodisparate.TurnBasedMinecraft; +import java.time.Duration; + import org.apache.logging.log4j.Logger; +import com.seodisparate.TurnBasedMinecraft.common.Battle; import com.seodisparate.TurnBasedMinecraft.common.BattleManager; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleDecision; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleEntered; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleExited; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleInfo; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleRequestInfo; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketHandler; import net.minecraft.entity.Entity; import net.minecraftforge.event.entity.living.LivingAttackEvent; @@ -10,6 +19,7 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.relauncher.Side; @Mod(modid = TurnBasedMinecraftMod.MODID, name = TurnBasedMinecraftMod.NAME, version = TurnBasedMinecraftMod.VERSION) public class TurnBasedMinecraftMod @@ -17,11 +27,14 @@ public class TurnBasedMinecraftMod public static final String MODID = "com.seodisparate.turnbasedminecraft"; public static final String NAME = "Turn Based Minecraft Mod"; public static final String VERSION = "1.0"; + public static final Duration BattleDecisionTime = Duration.ofSeconds(15); private static Logger logger; - private static BattleManager battleManager; - + public static BattleManager battleManager; + private static int packetHandlerID = 0; public static Entity attackingEntity; + + public static Battle currentBattle; @EventHandler public void preInit(FMLPreInitializationEvent event) @@ -32,13 +45,59 @@ public class TurnBasedMinecraftMod @EventHandler public void init(FMLInitializationEvent event) { - battleManager = new BattleManager(); + currentBattle = null; + if(event.getSide() == Side.SERVER) + { + battleManager = new BattleManager(); + } + else + { + battleManager = null; + } + + // register packets + PacketHandler.INSTANCE.registerMessage( + PacketBattleEntered.HandlerBattleEntered.class, + PacketBattleEntered.class, + packetHandlerID++, + Side.CLIENT); + PacketHandler.INSTANCE.registerMessage( + PacketBattleExited.HandlerBattleExited.class, + PacketBattleExited.class, + packetHandlerID++, + Side.CLIENT); + PacketHandler.INSTANCE.registerMessage( + PacketBattleInfo.HandlerBattleInfo.class, + PacketBattleInfo.class, + packetHandlerID++, + Side.CLIENT); + PacketHandler.INSTANCE.registerMessage( + PacketBattleRequestInfo.HandlerBattleRequestInfo.class, + PacketBattleRequestInfo.class, + packetHandlerID++, + Side.SERVER); + PacketHandler.INSTANCE.registerMessage( + PacketBattleDecision.HandleBattleDecision.class, + PacketBattleDecision.class, + packetHandlerID++, + Side.SERVER); } + + /* + @EventHandler + public void postInit(FMLPostInitializationEvent event) + { + } + */ @EventHandler public void entityAttacked(LivingAttackEvent event) { - if(!event.getEntity().equals(attackingEntity) && battleManager.checkAttack(event)) + if(battleManager == null) + { + return; + } + if(!event.getSource().getTrueSource().equals(attackingEntity) && battleManager.checkAttack(event)) { logger.debug("Canceled LivingAttackEvent between " + attackingEntity + " and " + event.getEntity()); event.setCanceled(true); diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java index e72a906..80b025d 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java @@ -2,35 +2,104 @@ package com.seodisparate.TurnBasedMinecraft.common; import java.time.Duration; import java.time.Instant; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Hashtable; import java.util.Map; +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; + import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; public class Battle { - private int id; - private Map sideA; - private Map sideB; + private final int id; + private Map sideA; + private Map sideB; private Instant lastUpdated; + private State state; + private int playerCount; + private int undecidedCount; + private Duration timer; + + public enum State + { + DECISION, + ATTACK, + HEALTH_CHECK + } + + public enum Decision + { + UNDECIDED(0), + ATTACK(1), + DEFEND(2), + FLEE(3), + USE_ITEM(4); + + private int value; + private static Map map = new HashMap(); + + private Decision(int value) + { + this.value = value; + } + + public int getValue() + { + return value; + } + + static + { + for(Decision decision : Decision.values()) + { + map.put(decision.value, decision); + } + } + + public static Decision valueOf(int decisionType) + { + return map.get(decisionType); + } + } public Battle(int id, Collection sideA, Collection sideB) { this.id = id; - this.sideA = new Hashtable(); - this.sideB = new Hashtable(); - for(Entity e : sideA) + this.sideA = new Hashtable(); + this.sideB = new Hashtable(); + playerCount = 0; + if(sideA != null) { - this.sideA.put(e.getEntityId(), e); + for(Entity e : sideA) + { + this.sideA.put(e.getEntityId(), new Combatant(e)); + if(e instanceof EntityPlayer) + { + ++playerCount; + } + } } - for(Entity e : sideB) + if(sideB != null) { - this.sideB.put(e.getEntityId(), e); + for(Entity e : sideB) + { + this.sideB.put(e.getEntityId(), new Combatant(e)); + if(e instanceof EntityPlayer) + { + ++playerCount; + } + } } lastUpdated = null; + state = State.DECISION; + undecidedCount = playerCount; + timer = TurnBasedMinecraftMod.BattleDecisionTime; } public int getId() @@ -50,12 +119,104 @@ public class Battle public void addCombatantToSideA(Entity e) { - sideA.put(e.getEntityId(), e); + sideA.put(e.getEntityId(), new Combatant(e)); + if(e instanceof EntityPlayer) + { + ++playerCount; + if(state == State.DECISION) + { + ++undecidedCount; + } + } } public void addCombatantToSideB(Entity e) { - sideB.put(e.getEntityId(), e); + sideB.put(e.getEntityId(), new Combatant(e)); + if(e instanceof EntityPlayer) + { + ++playerCount; + if(state == State.DECISION) + { + ++undecidedCount; + } + } + } + + public void clearCombatants() + { + sideA.clear(); + sideB.clear(); + playerCount = 0; + undecidedCount = 0; + } + + public Collection getSideA() + { + return sideA.values(); + } + + public Collection getSideB() + { + return sideB.values(); + } + + public Collection getSideAIDs() + { + Collection sideAIDs = new ArrayList(sideA.size()); + for(Combatant combatant : sideA.values()) + { + sideAIDs.add(combatant.entity.getEntityId()); + } + return sideAIDs; + } + + public Collection getSideBIDs() + { + Collection sideBIDs = new ArrayList(sideB.size()); + for(Combatant combatant : sideB.values()) + { + sideBIDs.add(combatant.entity.getEntityId()); + } + return sideBIDs; + } + + public Combatant getCombatantByID(int entityID) + { + Combatant combatant = sideA.get(entityID); + if(combatant == null) + { + combatant = sideB.get(entityID); + } + return combatant; + } + + public void setDecision(int entityID, Decision decision) + { + if(state != State.DECISION) + { + return; + } + Combatant combatant = sideA.get(entityID); + if(combatant == null) + { + combatant = sideB.get(entityID); + if(combatant == null) + { + return; + } + } + + if(combatant.entity instanceof EntityPlayer) + { + combatant.decision = decision; + --undecidedCount; + } + } + + public State getState() + { + return state; } public void update() @@ -73,7 +234,25 @@ public class Battle } } - private void update(Duration dt) + private void update(final Duration dt) { + switch(state) + { + case DECISION: + timer = timer.minus(dt); + if(timer.isNegative() || timer.isZero()) + { + state = State.ATTACK; + timer = TurnBasedMinecraftMod.BattleDecisionTime; + update(Duration.ZERO); + } + break; + case ATTACK: + // TODO + break; + case HEALTH_CHECK: + // TODO + break; + } } } diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java index 991cae7..39fcbef 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleManager.java @@ -5,8 +5,12 @@ import java.util.Collection; import java.util.Hashtable; import java.util.Map; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleEntered; +import com.seodisparate.TurnBasedMinecraft.common.networking.PacketHandler; + import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.event.entity.living.LivingAttackEvent; public class BattleManager @@ -36,36 +40,39 @@ public class BattleManager Entity inBattle = null; Entity notInBattle = null; Battle battle = null; + for(Battle b : battleMap.values()) { if(b.hasCombatant(event.getSource().getTrueSource().getEntityId())) { - inBattle = event.getSource().getTrueSource(); - battle = b; - break; + if(inBattle != null) + { + // both combatants are in battle + return true; + } + else + { + inBattle = event.getSource().getTrueSource(); + notInBattle = event.getEntity(); + battle = b; + } } - } - if(inBattle != null) - { - notInBattle = event.getEntity(); - } else - { - notInBattle = event.getSource().getTrueSource(); - } - for(Battle b : battleMap.values()) - { if(b.hasCombatant(event.getEntity().getEntityId())) { if(inBattle != null) { - // both combatants in battle + // both combatants are in battle return true; } - inBattle = event.getEntity(); - battle = b; - break; + else + { + inBattle = event.getEntity(); + notInBattle = event.getSource().getTrueSource(); + battle = b; + } } } + if(inBattle == null) { // neither entity is in battle @@ -90,6 +97,11 @@ public class BattleManager { battle.addCombatantToSideA(notInBattle); } + + if(notInBattle instanceof EntityPlayerMP) + { + PacketHandler.INSTANCE.sendTo(new PacketBattleEntered(IDCounter), (EntityPlayerMP)notInBattle); + } return true; } @@ -101,6 +113,25 @@ public class BattleManager } Battle newBattle = new Battle(IDCounter, sideA, sideB); battleMap.put(IDCounter, newBattle); + for(Entity e : sideA) + { + if(e instanceof EntityPlayerMP) + { + PacketHandler.INSTANCE.sendTo(new PacketBattleEntered(IDCounter), (EntityPlayerMP)e); + } + } + for(Entity e : sideB) + { + if(e instanceof EntityPlayerMP) + { + PacketHandler.INSTANCE.sendTo(new PacketBattleEntered(IDCounter), (EntityPlayerMP)e); + } + } return newBattle; } -} + + public Battle getBattleByID(int id) + { + return battleMap.get(id); + } +} \ No newline at end of file diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java index 4f52dc1..aa8732a 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/BattleUpdater.java @@ -2,20 +2,30 @@ package com.seodisparate.TurnBasedMinecraft.common; public class BattleUpdater implements Runnable { - BattleManager manager; + private BattleManager manager; + private boolean isRunning; public BattleUpdater(BattleManager manager) { this.manager = manager; + isRunning = true; } @Override public void run() { - for(Battle e : manager.battleMap.values()) + while(isRunning) { - e.update(); + for(Battle e : manager.battleMap.values()) + { + e.update(); + } + try { Thread.sleep(250); } catch (Exception e) { /* ignored */ } } - try { Thread.sleep(250); } catch (Exception e) { /* ignored */ } + } + + public void setIsRunning(boolean isRunning) + { + this.isRunning = isRunning; } } \ No newline at end of file diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Combatant.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Combatant.java new file mode 100644 index 0000000..e32bb92 --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Combatant.java @@ -0,0 +1,31 @@ +package com.seodisparate.TurnBasedMinecraft.common; + +import net.minecraft.entity.Entity; + +public class Combatant +{ + public Entity entity; + public Battle.Decision decision; + public int itemToUse; + public float speed; + + public Combatant() + { + decision = Battle.Decision.UNDECIDED; + speed = 0.5f; + } + + public Combatant(Entity e) + { + entity = e; + decision = Battle.Decision.UNDECIDED; + speed = 0.5f; + } + + public Combatant(Entity e, float speed) + { + entity = e; + decision = Battle.Decision.UNDECIDED; + this.speed = speed; + } +} diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleDecision.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleDecision.java new file mode 100644 index 0000000..8a7f313 --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleDecision.java @@ -0,0 +1,55 @@ +package com.seodisparate.TurnBasedMinecraft.common.networking; + +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; +import com.seodisparate.TurnBasedMinecraft.common.Battle; +import com.seodisparate.TurnBasedMinecraft.common.Battle.Decision; +import com.seodisparate.TurnBasedMinecraft.common.Combatant; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketBattleDecision implements IMessage +{ + private int battleID; + private Battle.Decision decision; + + public PacketBattleDecision() {} + + public PacketBattleDecision(int battleID, Battle.Decision decision) + { + this.battleID = battleID; + this.decision = decision; + } + + @Override + public void fromBytes(ByteBuf buf) + { + battleID = buf.readInt(); + decision = Decision.valueOf(buf.readInt()); + } + + @Override + public void toBytes(ByteBuf buf) + { + buf.writeInt(battleID); + buf.writeInt(decision.getValue()); + } + + public static class HandleBattleDecision implements IMessageHandler + { + @Override + public IMessage onMessage(PacketBattleDecision message, MessageContext ctx) + { + Battle b = TurnBasedMinecraftMod.battleManager.getBattleByID(message.battleID); + if(b != null && b.getState() == Battle.State.DECISION) + { + EntityPlayerMP player = ctx.getServerHandler().player; + b.setDecision(player.getEntityId(), message.decision); + } + return null; + } + } +} diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleEntered.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleEntered.java new file mode 100644 index 0000000..7039f71 --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleEntered.java @@ -0,0 +1,43 @@ +package com.seodisparate.TurnBasedMinecraft.common.networking; + +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; +import com.seodisparate.TurnBasedMinecraft.common.Battle; + +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketBattleEntered implements IMessage +{ + private int battleID; + + public PacketBattleEntered() {} + + public PacketBattleEntered(int battleID) + { + this.battleID = battleID; + } + + @Override + public void fromBytes(ByteBuf buf) + { + battleID = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf) + { + buf.writeInt(battleID); + } + + public static class HandlerBattleEntered implements IMessageHandler + { + @Override + public PacketBattleRequestInfo onMessage(PacketBattleEntered message, MessageContext ctx) + { + TurnBasedMinecraftMod.currentBattle = new Battle(message.battleID, null, null); + return new PacketBattleRequestInfo(message.battleID); + } + } +} diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleExited.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleExited.java new file mode 100644 index 0000000..e89e061 --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleExited.java @@ -0,0 +1,31 @@ +package com.seodisparate.TurnBasedMinecraft.common.networking; + +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; + +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketBattleExited implements IMessage +{ + @Override + public void fromBytes(ByteBuf buf) + { + } + + @Override + public void toBytes(ByteBuf buf) + { + } + + public static class HandlerBattleExited implements IMessageHandler + { + @Override + public IMessage onMessage(PacketBattleExited message, MessageContext ctx) + { + TurnBasedMinecraftMod.currentBattle = null; + return null; + } + } +} diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleInfo.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleInfo.java new file mode 100644 index 0000000..259171a --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleInfo.java @@ -0,0 +1,82 @@ +package com.seodisparate.TurnBasedMinecraft.common.networking; + +import java.util.ArrayList; +import java.util.Collection; + +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; + +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketBattleInfo implements IMessage +{ + private Collection sideA; + private Collection sideB; + + public PacketBattleInfo() + { + sideA = new ArrayList(); + sideB = new ArrayList(); + } + + public PacketBattleInfo(Collection sideA, Collection sideB) + { + this.sideA = sideA; + this.sideB = sideB; + } + + @Override + public void fromBytes(ByteBuf buf) + { + int sideACount = buf.readInt(); + int sideBCount = buf.readInt(); + for(int i = 0; i < sideACount; ++i) + { + sideA.add(buf.readInt()); + } + for(int i = 0; i < sideBCount; ++i) + { + sideB.add(buf.readInt()); + } + } + + @Override + public void toBytes(ByteBuf buf) + { + buf.writeInt(sideA.size()); + buf.writeInt(sideB.size()); + for(Integer id : sideA) + { + buf.writeInt(id); + } + for(Integer id : sideB) + { + buf.writeInt(id); + } + } + + public static class HandlerBattleInfo implements IMessageHandler + { + @Override + public IMessage onMessage(PacketBattleInfo message, MessageContext ctx) + { + if(TurnBasedMinecraftMod.currentBattle == null) + { + return null; + } + TurnBasedMinecraftMod.currentBattle.clearCombatants(); + for(Integer id : message.sideA) + { + TurnBasedMinecraftMod.currentBattle.addCombatantToSideA(Minecraft.getMinecraft().world.getEntityByID(id)); + } + for(Integer id : message.sideB) + { + TurnBasedMinecraftMod.currentBattle.addCombatantToSideB(Minecraft.getMinecraft().world.getEntityByID(id)); + } + return null; + } + } +} diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleRequestInfo.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleRequestInfo.java new file mode 100644 index 0000000..04d6746 --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketBattleRequestInfo.java @@ -0,0 +1,48 @@ +package com.seodisparate.TurnBasedMinecraft.common.networking; + +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; +import com.seodisparate.TurnBasedMinecraft.common.Battle; + +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PacketBattleRequestInfo implements IMessage +{ + private int battleID; + + public PacketBattleRequestInfo() {} + + public PacketBattleRequestInfo(int battleID) + { + this.battleID = battleID; + } + + @Override + public void fromBytes(ByteBuf buf) + { + battleID = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf) + { + buf.writeInt(battleID); + } + + public static class HandlerBattleRequestInfo implements IMessageHandler + { + @Override + public PacketBattleInfo onMessage(PacketBattleRequestInfo message, MessageContext ctx) + { + Battle b = TurnBasedMinecraftMod.battleManager.getBattleByID(message.battleID); + if(b == null) + { + return null; + } + PacketBattleInfo battleInfo = new PacketBattleInfo(b.getSideAIDs(), b.getSideBIDs()); + return battleInfo; + } + } +} diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketHandler.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketHandler.java new file mode 100644 index 0000000..353a8bb --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/networking/PacketHandler.java @@ -0,0 +1,11 @@ +package com.seodisparate.TurnBasedMinecraft.common.networking; + +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; + +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; + +public class PacketHandler +{ + public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(TurnBasedMinecraftMod.MODID); +}