Work In Progress - Some more work done

Added some Packets/Handlers for networking, and more work on Battle
logic.
This commit is contained in:
Stephen Seo 2018-08-29 15:09:44 +09:00
parent 82b52d72be
commit 957ad5ec38
11 changed files with 618 additions and 38 deletions

View file

@ -1,8 +1,17 @@
package com.seodisparate.TurnBasedMinecraft; package com.seodisparate.TurnBasedMinecraft;
import java.time.Duration;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.seodisparate.TurnBasedMinecraft.common.Battle;
import com.seodisparate.TurnBasedMinecraft.common.BattleManager; 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.minecraft.entity.Entity;
import net.minecraftforge.event.entity.living.LivingAttackEvent; 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.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.Side;
@Mod(modid = TurnBasedMinecraftMod.MODID, name = TurnBasedMinecraftMod.NAME, version = TurnBasedMinecraftMod.VERSION) @Mod(modid = TurnBasedMinecraftMod.MODID, name = TurnBasedMinecraftMod.NAME, version = TurnBasedMinecraftMod.VERSION)
public class TurnBasedMinecraftMod public class TurnBasedMinecraftMod
@ -17,12 +27,15 @@ public class TurnBasedMinecraftMod
public static final String MODID = "com.seodisparate.turnbasedminecraft"; public static final String MODID = "com.seodisparate.turnbasedminecraft";
public static final String NAME = "Turn Based Minecraft Mod"; public static final String NAME = "Turn Based Minecraft Mod";
public static final String VERSION = "1.0"; public static final String VERSION = "1.0";
public static final Duration BattleDecisionTime = Duration.ofSeconds(15);
private static Logger logger; private static Logger logger;
private static BattleManager battleManager; public static BattleManager battleManager;
private static int packetHandlerID = 0;
public static Entity attackingEntity; public static Entity attackingEntity;
public static Battle currentBattle;
@EventHandler @EventHandler
public void preInit(FMLPreInitializationEvent event) public void preInit(FMLPreInitializationEvent event)
{ {
@ -32,13 +45,59 @@ public class TurnBasedMinecraftMod
@EventHandler @EventHandler
public void init(FMLInitializationEvent event) 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 @EventHandler
public void entityAttacked(LivingAttackEvent event) 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()); logger.debug("Canceled LivingAttackEvent between " + attackingEntity + " and " + event.getEntity());
event.setCanceled(true); event.setCanceled(true);

View file

@ -2,35 +2,104 @@ package com.seodisparate.TurnBasedMinecraft.common;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
public class Battle public class Battle
{ {
private int id; private final int id;
private Map<Integer, Entity> sideA; private Map<Integer, Combatant> sideA;
private Map<Integer, Entity> sideB; private Map<Integer, Combatant> sideB;
private Instant lastUpdated; 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<Integer, Decision> map = new HashMap<Integer, Decision>();
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<Entity> sideA, Collection<Entity> sideB) public Battle(int id, Collection<Entity> sideA, Collection<Entity> sideB)
{ {
this.id = id; this.id = id;
this.sideA = new Hashtable<Integer, Entity>(); this.sideA = new Hashtable<Integer, Combatant>();
this.sideB = new Hashtable<Integer, Entity>(); this.sideB = new Hashtable<Integer, Combatant>();
for(Entity e : sideA) 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; lastUpdated = null;
state = State.DECISION;
undecidedCount = playerCount;
timer = TurnBasedMinecraftMod.BattleDecisionTime;
} }
public int getId() public int getId()
@ -50,12 +119,104 @@ public class Battle
public void addCombatantToSideA(Entity e) 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) 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<Combatant> getSideA()
{
return sideA.values();
}
public Collection<Combatant> getSideB()
{
return sideB.values();
}
public Collection<Integer> getSideAIDs()
{
Collection<Integer> sideAIDs = new ArrayList<Integer>(sideA.size());
for(Combatant combatant : sideA.values())
{
sideAIDs.add(combatant.entity.getEntityId());
}
return sideAIDs;
}
public Collection<Integer> getSideBIDs()
{
Collection<Integer> sideBIDs = new ArrayList<Integer>(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() 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;
}
} }
} }

View file

@ -5,8 +5,12 @@ import java.util.Collection;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; 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.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent;
public class BattleManager public class BattleManager
@ -36,36 +40,39 @@ public class BattleManager
Entity inBattle = null; Entity inBattle = null;
Entity notInBattle = null; Entity notInBattle = null;
Battle battle = null; Battle battle = null;
for(Battle b : battleMap.values()) for(Battle b : battleMap.values())
{ {
if(b.hasCombatant(event.getSource().getTrueSource().getEntityId())) if(b.hasCombatant(event.getSource().getTrueSource().getEntityId()))
{ {
inBattle = event.getSource().getTrueSource(); if(inBattle != null)
battle = b; {
break; // 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(b.hasCombatant(event.getEntity().getEntityId()))
{ {
if(inBattle != null) if(inBattle != null)
{ {
// both combatants in battle // both combatants are in battle
return true; return true;
} }
inBattle = event.getEntity(); else
battle = b; {
break; inBattle = event.getEntity();
notInBattle = event.getSource().getTrueSource();
battle = b;
}
} }
} }
if(inBattle == null) if(inBattle == null)
{ {
// neither entity is in battle // neither entity is in battle
@ -90,6 +97,11 @@ public class BattleManager
{ {
battle.addCombatantToSideA(notInBattle); battle.addCombatantToSideA(notInBattle);
} }
if(notInBattle instanceof EntityPlayerMP)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleEntered(IDCounter), (EntityPlayerMP)notInBattle);
}
return true; return true;
} }
@ -101,6 +113,25 @@ public class BattleManager
} }
Battle newBattle = new Battle(IDCounter, sideA, sideB); Battle newBattle = new Battle(IDCounter, sideA, sideB);
battleMap.put(IDCounter, newBattle); 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; return newBattle;
} }
public Battle getBattleByID(int id)
{
return battleMap.get(id);
}
} }

View file

@ -2,20 +2,30 @@ package com.seodisparate.TurnBasedMinecraft.common;
public class BattleUpdater implements Runnable public class BattleUpdater implements Runnable
{ {
BattleManager manager; private BattleManager manager;
private boolean isRunning;
public BattleUpdater(BattleManager manager) public BattleUpdater(BattleManager manager)
{ {
this.manager = manager; this.manager = manager;
isRunning = true;
} }
@Override @Override
public void run() 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;
} }
} }

View file

@ -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;
}
}

View file

@ -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<PacketBattleDecision, IMessage>
{
@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;
}
}
}

View file

@ -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<PacketBattleEntered, PacketBattleRequestInfo>
{
@Override
public PacketBattleRequestInfo onMessage(PacketBattleEntered message, MessageContext ctx)
{
TurnBasedMinecraftMod.currentBattle = new Battle(message.battleID, null, null);
return new PacketBattleRequestInfo(message.battleID);
}
}
}

View file

@ -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<PacketBattleExited, IMessage>
{
@Override
public IMessage onMessage(PacketBattleExited message, MessageContext ctx)
{
TurnBasedMinecraftMod.currentBattle = null;
return null;
}
}
}

View file

@ -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<Integer> sideA;
private Collection<Integer> sideB;
public PacketBattleInfo()
{
sideA = new ArrayList<Integer>();
sideB = new ArrayList<Integer>();
}
public PacketBattleInfo(Collection<Integer> sideA, Collection<Integer> 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<PacketBattleInfo, IMessage>
{
@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;
}
}
}

View file

@ -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<PacketBattleRequestInfo, PacketBattleInfo>
{
@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;
}
}
}

View file

@ -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);
}