WIP backend logic impl, fixes to config gen/parse

This commit is contained in:
Stephen Seo 2018-09-07 16:41:22 +09:00
parent 0520e163f8
commit 97cfdaf0f7
5 changed files with 533 additions and 354 deletions

View file

@ -20,6 +20,7 @@ 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.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side; 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)
@ -32,7 +33,8 @@ public class TurnBasedMinecraftMod
public static final String CONFIG_FILENAME = "TBM_Config.xml"; public static final String CONFIG_FILENAME = "TBM_Config.xml";
public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/"; public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/";
public static final String CONFIG_FILE_PATH = CONFIG_DIRECTORY + CONFIG_FILENAME; public static final String CONFIG_FILE_PATH = CONFIG_DIRECTORY + CONFIG_FILENAME;
public static final int CONFIG_FILE_VERSION = 1; // TODO derive this from internal config public static final String CONFIG_INTERNAL_PATH = "/assets/TurnBasedMinecraft/" + CONFIG_FILENAME;
private static int CONFIG_FILE_VERSION = 0;
private static Logger logger; private static Logger logger;
private static BattleManager battleManager; private static BattleManager battleManager;
@ -47,6 +49,7 @@ public class TurnBasedMinecraftMod
public void preInit(FMLPreInitializationEvent event) public void preInit(FMLPreInitializationEvent event)
{ {
logger = event.getModLog(); logger = event.getModLog();
logger.debug("PREINIT");
} }
@EventHandler @EventHandler
@ -83,6 +86,7 @@ public class TurnBasedMinecraftMod
PacketBattleMessage.class, PacketBattleMessage.class,
packetHandlerID++, packetHandlerID++,
Side.CLIENT); Side.CLIENT);
logger.debug("INIT");
} }
@EventHandler @EventHandler
@ -92,9 +96,10 @@ public class TurnBasedMinecraftMod
{ {
config = new Config(logger); config = new Config(logger);
} }
logger.debug("POSTINIT");
} }
@EventHandler @SubscribeEvent
public void entityAttacked(LivingAttackEvent event) public void entityAttacked(LivingAttackEvent event)
{ {
if(battleManager == null) if(battleManager == null)
@ -113,4 +118,14 @@ public class TurnBasedMinecraftMod
{ {
return battleManager; return battleManager;
} }
public static void setConfigVersion(int version)
{
CONFIG_FILE_VERSION = version;
}
public static int getConfigVersion()
{
return CONFIG_FILE_VERSION;
}
} }

View file

@ -21,6 +21,13 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemLingeringPotion;
import net.minecraft.item.ItemPotion;
import net.minecraft.item.ItemSplashPotion;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource; import net.minecraft.util.DamageSource;
public class Battle public class Battle
@ -43,8 +50,7 @@ public class Battle
public enum State public enum State
{ {
DECISION, DECISION,
ACTION, ACTION
HEALTH_CHECK
} }
public enum Decision public enum Decision
@ -357,6 +363,76 @@ public class Battle
} }
} }
private void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount, String custom)
{
if(!isServer)
{
return;
}
for(Combatant p : players.values())
{
if(p.entity.isEntityAlive())
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(type, from, to, amount, custom), (EntityPlayerMP)p.entity);
}
}
}
/**
* @return true if at least one combatant was removed
*/
private boolean healthCheck()
{
Queue<Integer> removeQueue = new ArrayDeque<Integer>();
for(Combatant c : sideA.values())
{
if(!c.entity.isEntityAlive())
{
removeQueue.add(c.entity.getEntityId());
if(c.entity instanceof EntityPlayer)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, c.entity.getEntityId(), 0, 0);
}
}
for(Combatant c : sideB.values())
{
if(!c.entity.isEntityAlive())
{
removeQueue.add(c.entity.getEntityId());
if(c.entity instanceof EntityPlayer)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, c.entity.getEntityId(), 0, 0);
}
}
boolean didRemove = !removeQueue.isEmpty();
Integer toRemove = removeQueue.poll();
while(toRemove != null)
{
sideA.remove(toRemove);
sideB.remove(toRemove);
if(players.remove(toRemove) != null)
{
playerCount.decrementAndGet();
}
toRemove = removeQueue.poll();
}
if(players.isEmpty() || sideA.isEmpty() || sideB.isEmpty())
{
battleEnded = true;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENDED, 0, 0, 0);
}
else if(didRemove)
{
notifyPlayersBattleInfo();
}
return didRemove;
}
private boolean update(final Duration dt) private boolean update(final Duration dt)
{ {
if(battleEnded) if(battleEnded)
@ -421,330 +497,303 @@ public class Battle
} }
update(Duration.ZERO); update(Duration.ZERO);
} }
else
{
healthCheck();
}
break; break;
case ACTION: case ACTION:
{
Combatant next = turnOrderQueue.poll();
while(next != null)
{ {
if(!next.entity.isEntityAlive()) Combatant next = turnOrderQueue.poll();
while(next != null)
{ {
next = turnOrderQueue.poll(); if(!next.entity.isEntityAlive())
continue;
}
switch(next.decision)
{
case UNDECIDED:
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DID_NOTHING, next.entity.getEntityId(), 0, 0);
next = turnOrderQueue.poll();
continue;
case ATTACK:
Combatant target = null;
if(next.entity instanceof EntityPlayer)
{ {
if(next.isSideA) next = turnOrderQueue.poll();
{ continue;
target = sideB.get(next.targetEntityID);
}
else
{
target = sideA.get(next.targetEntityID);
}
if(target == null || !target.entity.isEntityAlive())
{
next = turnOrderQueue.poll();
continue;
}
int hitChance = TurnBasedMinecraftMod.config.getPlayerAttackProbability();
if(target.entity instanceof EntityPlayer)
{
hitChance -= TurnBasedMinecraftMod.config.getPlayerEvasion();
}
else
{
hitChance -= target.entityInfo.evasion;
}
if((int)(Math.random() * 100) < hitChance)
{
if(target.remainingDefenses <= 0)
{
// attack
// TODO damage via bow and arrow
TurnBasedMinecraftMod.attackingEntity = next.entity;
((EntityPlayer)next.entity).attackTargetEntityWithCurrentItem(target.entity);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), TurnBasedMinecraftMod.attackingDamage);
if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0)
{
if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability)
{
// defense damage
DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)target.entity);
TurnBasedMinecraftMod.attackingEntity = target.entity;
next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage);
}
}
}
else
{
// blocked
--target.remainingDefenses;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
}
}
else
{
// miss
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
}
} }
else switch(next.decision)
{ {
if(next.isSideA) case UNDECIDED:
{ sendMessageToAllPlayers(PacketBattleMessage.MessageType.DID_NOTHING, next.entity.getEntityId(), 0, 0);
int randomTargetIndex = (int)(Math.random() * sideB.size()); break;
for(Combatant c : sideB.values()) case ATTACK:
{ Combatant target = null;
if(randomTargetIndex-- == 0)
{
target = c;
break;
}
}
}
else
{
int randomTargetIndex = (int)(Math.random() * sideA.size());
for(Combatant c : sideA.values())
{
if(randomTargetIndex-- == 0)
{
target = c;
break;
}
}
}
if(target == null || !target.entity.isEntityAlive())
{
next = turnOrderQueue.poll();
continue;
}
int hitChance = next.entityInfo.attackProbability;
if(target.entity instanceof EntityPlayer)
{
hitChance -= TurnBasedMinecraftMod.config.getPlayerEvasion();
}
else
{
hitChance -= target.entityInfo.evasion;
}
if((int)(Math.random() * 100) < hitChance)
{
if(target.remainingDefenses <= 0)
{
DamageSource damageSource = DamageSource.causeMobDamage((EntityLivingBase)next.entity);
int damageAmount = next.entityInfo.attackPower;
if(next.entityInfo.attackVariance > 0)
{
damageAmount += (int)(Math.random() * (next.entityInfo.attackVariance * 2 + 1)) - next.entityInfo.attackVariance;
}
// attack
TurnBasedMinecraftMod.attackingEntity = next.entity;
target.entity.attackEntityFrom(damageSource, damageAmount);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), damageAmount);
if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0)
{
if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability)
{
// defense damage
DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)target.entity);
TurnBasedMinecraftMod.attackingEntity = target.entity;
next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage);
}
}
}
else
{
// blocked
--target.remainingDefenses;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
}
}
else
{
// miss
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
}
}
break;
case DEFEND:
next.remainingDefenses = TurnBasedMinecraftMod.config.getDefenseDuration();
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENDING, next.entity.getEntityId(), 0, 0);
break;
case FLEE:
int fastestEnemySpeed = 0;
if(next.isSideA)
{
for(Combatant c : sideB.values())
{
if(c.entity instanceof EntityPlayer)
{
if(TurnBasedMinecraftMod.config.getPlayerSpeed() > fastestEnemySpeed)
{
fastestEnemySpeed = TurnBasedMinecraftMod.config.getPlayerSpeed();
}
}
else
{
if(c.entityInfo.speed > fastestEnemySpeed)
{
fastestEnemySpeed = c.entityInfo.speed;
}
}
}
}
else
{
for(Combatant c : sideA.values())
{
if(c.entity instanceof EntityPlayer)
{
if(TurnBasedMinecraftMod.config.getPlayerSpeed() > fastestEnemySpeed)
{
fastestEnemySpeed = TurnBasedMinecraftMod.config.getPlayerSpeed();
}
}
else
{
if(c.entityInfo.speed > fastestEnemySpeed)
{
fastestEnemySpeed = c.entityInfo.speed;
}
}
}
}
int fleeProbability = 0;
if(next.entity instanceof EntityPlayer)
{
if(fastestEnemySpeed >= TurnBasedMinecraftMod.config.getPlayerSpeed())
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeBadProbability();
}
else
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeGoodProbability();
}
}
else
{
if(fastestEnemySpeed >= next.entityInfo.speed)
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeBadProbability();
}
else
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeGoodProbability();
}
}
if((int)(Math.random() * 100) < fleeProbability)
{
// flee success
if(next.isSideA)
{
sideA.remove(next.entity.getEntityId());
}
else
{
sideB.remove(next.entity.getEntityId());
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 1);
if(next.entity instanceof EntityPlayer) if(next.entity instanceof EntityPlayer)
{ {
players.remove(next.entity.getEntityId()); if(next.isSideA)
playerCount.decrementAndGet(); {
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, 0), (EntityPlayerMP)next.entity); target = sideB.get(next.targetEntityID);
}
else
{
target = sideA.get(next.targetEntityID);
}
if(target == null || !target.entity.isEntityAlive())
{
break;
}
int hitChance = TurnBasedMinecraftMod.config.getPlayerAttackProbability();
if(target.entity instanceof EntityPlayer)
{
hitChance -= TurnBasedMinecraftMod.config.getPlayerEvasion();
}
else
{
hitChance -= target.entityInfo.evasion;
}
if((int)(Math.random() * 100) < hitChance)
{
if(target.remainingDefenses <= 0)
{
// attack
// TODO damage via bow and arrow
TurnBasedMinecraftMod.attackingEntity = next.entity;
((EntityPlayer)next.entity).attackTargetEntityWithCurrentItem(target.entity);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), TurnBasedMinecraftMod.attackingDamage);
if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0)
{
if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability)
{
// defense damage
DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)target.entity);
TurnBasedMinecraftMod.attackingEntity = target.entity;
next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage);
}
}
}
else
{
// blocked
--target.remainingDefenses;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
}
}
else
{
// miss
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
}
} }
else
{
if(next.isSideA)
{
int randomTargetIndex = (int)(Math.random() * sideB.size());
for(Combatant c : sideB.values())
{
if(randomTargetIndex-- == 0)
{
target = c;
break;
}
}
}
else
{
int randomTargetIndex = (int)(Math.random() * sideA.size());
for(Combatant c : sideA.values())
{
if(randomTargetIndex-- == 0)
{
target = c;
break;
}
}
}
if(target == null || !target.entity.isEntityAlive())
{
next = turnOrderQueue.poll();
continue;
}
int hitChance = next.entityInfo.attackProbability;
if(target.entity instanceof EntityPlayer)
{
hitChance -= TurnBasedMinecraftMod.config.getPlayerEvasion();
}
else
{
hitChance -= target.entityInfo.evasion;
}
if((int)(Math.random() * 100) < hitChance)
{
if(target.remainingDefenses <= 0)
{
DamageSource damageSource = DamageSource.causeMobDamage((EntityLivingBase)next.entity);
int damageAmount = next.entityInfo.attackPower;
if(next.entityInfo.attackVariance > 0)
{
damageAmount += (int)(Math.random() * (next.entityInfo.attackVariance * 2 + 1)) - next.entityInfo.attackVariance;
}
// attack
TurnBasedMinecraftMod.attackingEntity = next.entity;
target.entity.attackEntityFrom(damageSource, damageAmount);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), damageAmount);
if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0)
{
if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability)
{
// defense damage
DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)target.entity);
TurnBasedMinecraftMod.attackingEntity = target.entity;
next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage);
TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage);
}
}
}
else
{
// blocked
--target.remainingDefenses;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
}
}
else
{
// miss
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
}
}
break;
case DEFEND:
next.remainingDefenses = TurnBasedMinecraftMod.config.getDefenseDuration();
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENDING, next.entity.getEntityId(), 0, 0);
break;
case FLEE:
int fastestEnemySpeed = 0;
if(next.isSideA)
{
for(Combatant c : sideB.values())
{
if(c.entity instanceof EntityPlayer)
{
if(TurnBasedMinecraftMod.config.getPlayerSpeed() > fastestEnemySpeed)
{
fastestEnemySpeed = TurnBasedMinecraftMod.config.getPlayerSpeed();
}
}
else
{
if(c.entityInfo.speed > fastestEnemySpeed)
{
fastestEnemySpeed = c.entityInfo.speed;
}
}
}
}
else
{
for(Combatant c : sideA.values())
{
if(c.entity instanceof EntityPlayer)
{
if(TurnBasedMinecraftMod.config.getPlayerSpeed() > fastestEnemySpeed)
{
fastestEnemySpeed = TurnBasedMinecraftMod.config.getPlayerSpeed();
}
}
else
{
if(c.entityInfo.speed > fastestEnemySpeed)
{
fastestEnemySpeed = c.entityInfo.speed;
}
}
}
}
int fleeProbability = 0;
if(next.entity instanceof EntityPlayer)
{
if(fastestEnemySpeed >= TurnBasedMinecraftMod.config.getPlayerSpeed())
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeBadProbability();
}
else
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeGoodProbability();
}
}
else
{
if(fastestEnemySpeed >= next.entityInfo.speed)
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeBadProbability();
}
else
{
fleeProbability = TurnBasedMinecraftMod.config.getFleeGoodProbability();
}
}
if((int)(Math.random() * 100) < fleeProbability)
{
// flee success
if(next.isSideA)
{
sideA.remove(next.entity.getEntityId());
}
else
{
sideB.remove(next.entity.getEntityId());
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 1);
if(next.entity instanceof EntityPlayer)
{
players.remove(next.entity.getEntityId());
playerCount.decrementAndGet();
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, 0), (EntityPlayerMP)next.entity);
}
}
else
{
// flee fail
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 0);
}
break;
case USE_ITEM:
ItemStack targetItemStack = ((EntityPlayer)next.entity).inventory.getStackInSlot(next.itemToUse);
Item targetItem = targetItemStack.getItem();
if(targetItem == null)
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_NOTHING.getValue());
break;
}
if(targetItem instanceof ItemFood)
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_FOOD.getValue(), targetItemStack.getDisplayName());
((ItemFood)targetItem).onItemUseFinish(targetItemStack, next.entity.world, (EntityLivingBase)next.entity);
}
else if(targetItem instanceof ItemPotion && !(targetItem instanceof ItemSplashPotion) && !(targetItem instanceof ItemLingeringPotion))
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_POTION.getValue(), targetItemStack.getDisplayName());
((ItemPotion)targetItem).onItemUseFinish(targetItemStack, next.entity.world, (EntityLivingBase)next.entity);
((EntityPlayer)next.entity).inventory.setInventorySlotContents(next.itemToUse, new ItemStack(Items.GLASS_BOTTLE));
}
else
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_INVALID.getValue(), targetItemStack.getDisplayName());
}
break;
} }
else next = turnOrderQueue.poll();
{
// flee fail
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 0);
}
break;
case USE_ITEM:
break;
} }
next = turnOrderQueue.poll(); for(Combatant c : sideA.values())
}
for(Combatant c : sideA.values())
{
c.decision = Decision.UNDECIDED;
}
for(Combatant c : sideB.values())
{
c.decision = Decision.UNDECIDED;
}
state = State.HEALTH_CHECK;
update(Duration.ZERO);
break;
}
case HEALTH_CHECK:
Queue<Integer> removeQueue = new ArrayDeque<Integer>();
for(Combatant c : sideA.values())
{
if(!c.entity.isEntityAlive())
{ {
removeQueue.add(c.entity.getEntityId()); c.decision = Decision.UNDECIDED;
if(c.entity instanceof EntityPlayer)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, c.entity.getEntityId(), 0, 0);
} }
} for(Combatant c : sideB.values())
for(Combatant c : sideB.values())
{
if(!c.entity.isEntityAlive())
{ {
removeQueue.add(c.entity.getEntityId()); c.decision = Decision.UNDECIDED;
if(c.entity instanceof EntityPlayer)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, c.entity.getEntityId(), 0, 0);
} }
} state = State.DECISION;
boolean didRemove = !removeQueue.isEmpty(); healthCheck();
Integer toRemove = removeQueue.poll(); break;
while(toRemove != null) } // case ACTION
{ } // switch(state)
sideA.remove(toRemove);
sideB.remove(toRemove);
if(players.remove(toRemove) != null)
{
playerCount.decrementAndGet();
}
toRemove = removeQueue.poll();
}
if(players.isEmpty() || sideA.isEmpty() || sideB.isEmpty())
{
battleEnded = true;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENDED, 0, 0, 0);
}
else if(didRemove)
{
notifyPlayersBattleInfo();
}
state = State.DECISION;
undecidedCount.set(playerCount.get());
timer = TurnBasedMinecraftMod.BattleDecisionTime;
break;
}
return battleEnded; return battleEnded;
} } // update(final Duration dt)
} }

View file

@ -2,10 +2,11 @@ package com.seodisparate.TurnBasedMinecraft.common;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.time.Instant; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -36,18 +37,32 @@ public class Config
private int fleeGoodProbability = 90; private int fleeGoodProbability = 90;
private int fleeBadProbability = 40; private int fleeBadProbability = 40;
private enum ConfigParseResult
{
IS_OLD,
SUCCESS
}
public Config(Logger logger) public Config(Logger logger)
{ {
entityInfoMap = new HashMap<String, EntityInfo>(); entityInfoMap = new HashMap<String, EntityInfo>();
ignoreBattleTypes = new HashSet<EntityInfo.Category>(); ignoreBattleTypes = new HashSet<EntityInfo.Category>();
this.logger = logger; this.logger = logger;
int internalVersion = 0;
try
{
InputStream is = getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_INTERNAL_PATH);
if(is == null)
{
logger.error("Internal resource is null");
}
internalVersion = getConfigFileVersion(is);
} catch (Exception e) {}
if(internalVersion == 0)
{
logger.error("Failed to check version of internal config file");
}
else
{
TurnBasedMinecraftMod.setConfigVersion(internalVersion);
}
try try
{ {
File testLoad = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH); File testLoad = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
@ -68,27 +83,26 @@ public class Config
logger.error("Failed to read/parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH); logger.error("Failed to read/parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH);
return; return;
} }
int configVersion = getConfigFileVersion(configFile);
if(configVersion < TurnBasedMinecraftMod.getConfigVersion())
{
logger.warn("Config file " + TurnBasedMinecraftMod.CONFIG_FILENAME + " is older version, renaming...");
moveOldConfig();
try
{
writeConfig();
} catch (Exception e)
{
logger.error("Failed to write config file!");
}
}
try try
{ {
ConfigParseResult result = parseConfig(configFile); parseConfig(configFile);
if(result == ConfigParseResult.IS_OLD)
{
logger.warn("Config file " + TurnBasedMinecraftMod.CONFIG_FILENAME + " is older version, renaming...");
moveOldConfig();
writeConfig();
ConfigParseResult resultSecond = parseConfig(configFile);
if(resultSecond != ConfigParseResult.SUCCESS)
{
logger.error("Failed to parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH);
}
}
else if(result != ConfigParseResult.SUCCESS)
{
logger.error("Failed to parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH);
}
} catch (Exception e) } catch (Exception e)
{ {
logger.error("Failed to parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH); logger.error("Failed to parse config file!");
} }
} }
@ -97,7 +111,7 @@ public class Config
File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH); File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
File dirs = configFile.getParentFile(); File dirs = configFile.getParentFile();
dirs.mkdirs(); dirs.mkdirs();
InputStream configStream = this.getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_FILENAME); InputStream configStream = this.getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_INTERNAL_PATH);
FileOutputStream configOutput = new FileOutputStream(configFile); FileOutputStream configOutput = new FileOutputStream(configFile);
byte[] buf = new byte[4096]; byte[] buf = new byte[4096];
int read = 0; int read = 0;
@ -120,12 +134,12 @@ public class Config
{ {
configFile.renameTo(new File(TurnBasedMinecraftMod.CONFIG_DIRECTORY configFile.renameTo(new File(TurnBasedMinecraftMod.CONFIG_DIRECTORY
+ "TBM_Config_" + "TBM_Config_"
+ DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(Instant.now()) + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())
+ ".xml")); + ".xml"));
} }
} }
private ConfigParseResult parseConfig(File configFile) throws XMLStreamException, FactoryConfigurationError, IOException private boolean parseConfig(File configFile) throws XMLStreamException, FactoryConfigurationError, IOException
{ {
FileInputStream fis = new FileInputStream(configFile); FileInputStream fis = new FileInputStream(configFile);
XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(fis); XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(fis);
@ -140,13 +154,6 @@ public class Config
} }
else if(xmlReader.getLocalName().equals("Version")) else if(xmlReader.getLocalName().equals("Version"))
{ {
if(Integer.parseInt(xmlReader.getElementText()) < TurnBasedMinecraftMod.CONFIG_FILE_VERSION)
{
logger.info("Config file is older version, moving it and writing a new one in its place");
xmlReader.close();
fis.close();
return ConfigParseResult.IS_OLD;
}
continue; continue;
} }
else if(xmlReader.getLocalName().equals("IgnoreBattleTypes")) else if(xmlReader.getLocalName().equals("IgnoreBattleTypes"))
@ -217,7 +224,6 @@ public class Config
} catch (ClassNotFoundException e) } catch (ClassNotFoundException e)
{ {
logger.error("Failed to get class of name " + classType); logger.error("Failed to get class of name " + classType);
continue;
} }
do do
{ {
@ -322,7 +328,10 @@ public class Config
} }
} }
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals(classType))); } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals(classType)));
entityInfoMap.put(eInfo.classType.getName(), eInfo); if(eInfo.classType != null)
{
entityInfoMap.put(eInfo.classType.getName(), eInfo);
}
} }
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("EntityStats"))); } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("EntityStats")));
} }
@ -330,7 +339,7 @@ public class Config
} }
xmlReader.close(); xmlReader.close();
fis.close(); fis.close();
return ConfigParseResult.SUCCESS; return true;
} }
public int getPlayerSpeed() public int getPlayerSpeed()
@ -408,4 +417,40 @@ public class Config
} }
return null; return null;
} }
private int getConfigFileVersion(File configFile)
{
try
{
return getConfigFileVersion(new FileInputStream(configFile));
} catch(FileNotFoundException e)
{
return 0;
}
}
private int getConfigFileVersion(InputStream configStream)
{
int configVersion = 1;
try
{
XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(configStream);
while(xmlReader.hasNext())
{
xmlReader.next();
if(xmlReader.isStartElement() && xmlReader.getLocalName().equals("Version"))
{
configVersion = Integer.parseInt(xmlReader.getElementText());
break;
}
}
xmlReader.close();
} catch (Exception e)
{
return 0;
}
return configVersion;
}
} }

View file

@ -13,6 +13,7 @@ import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.scoreboard.ScorePlayerTeam; import net.minecraft.scoreboard.ScorePlayerTeam;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
@ -30,7 +31,8 @@ public class PacketBattleMessage implements IMessage
DEFENSE_DAMAGE(6), DEFENSE_DAMAGE(6),
MISS(7), MISS(7),
DEFENDING(8), DEFENDING(8),
DID_NOTHING(9); DID_NOTHING(9),
USED_ITEM(10);
private int value; private int value;
private static Map<Integer, MessageType> map = new HashMap<Integer, MessageType>(); private static Map<Integer, MessageType> map = new HashMap<Integer, MessageType>();
@ -59,12 +61,47 @@ public class PacketBattleMessage implements IMessage
} }
} }
public enum UsedItemAction
{
USED_NOTHING(0),
USED_INVALID(1),
USED_FOOD(2),
USED_POTION(3);
private int value;
private static Map<Integer, UsedItemAction> map = new HashMap<Integer, UsedItemAction>();
private UsedItemAction(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
static
{
for(UsedItemAction type : UsedItemAction.values())
{
map.put(type.getValue(), type);
}
}
public static UsedItemAction valueOf(int value)
{
return map.get(value);
}
}
MessageType messageType; MessageType messageType;
int entityIDFrom; int entityIDFrom;
int entityIDTo; int entityIDTo;
int amount; int amount;
String custom;
public PacketBattleMessage() {} public PacketBattleMessage() { custom = new String(); }
public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, int amount) public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, int amount)
{ {
@ -72,6 +109,16 @@ public class PacketBattleMessage implements IMessage
this.entityIDFrom = entityIDFrom; this.entityIDFrom = entityIDFrom;
this.entityIDTo = entityIDTo; this.entityIDTo = entityIDTo;
this.amount = amount; this.amount = amount;
custom = new String();
}
public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, int amount, String custom)
{
this.messageType = messageType;
this.entityIDFrom = entityIDFrom;
this.entityIDTo = entityIDTo;
this.amount = amount;
this.custom = custom;
} }
@Override @Override
@ -81,6 +128,7 @@ public class PacketBattleMessage implements IMessage
entityIDFrom = buf.readInt(); entityIDFrom = buf.readInt();
entityIDTo = buf.readInt(); entityIDTo = buf.readInt();
amount = buf.readInt(); amount = buf.readInt();
custom = ByteBufUtils.readUTF8String(buf);
} }
@Override @Override
@ -90,6 +138,7 @@ public class PacketBattleMessage implements IMessage
buf.writeInt(entityIDFrom); buf.writeInt(entityIDFrom);
buf.writeInt(entityIDTo); buf.writeInt(entityIDTo);
buf.writeInt(amount); buf.writeInt(amount);
ByteBufUtils.writeUTF8String(buf, custom);
} }
public static class HandlerBattleMessage implements IMessageHandler<PacketBattleMessage, IMessage> public static class HandlerBattleMessage implements IMessageHandler<PacketBattleMessage, IMessage>
@ -226,6 +275,27 @@ public class PacketBattleMessage implements IMessage
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString( Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " did nothing!")); from + " did nothing!"));
break; break;
case USED_ITEM:
switch(UsedItemAction.valueOf(message.amount))
{
case USED_NOTHING:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " tried to use nothing!"));
break;
case USED_INVALID:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " tried to consume " + message.custom + " and failed!"));
break;
case USED_FOOD:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " ate a " + message.custom + "!"));
break;
case USED_POTION:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " drank a " + message.custom + "!"));
break;
}
break;
} }
return null; return null;
} }

View file

@ -212,7 +212,7 @@
<Flee>0</Flee> <Flee>0</Flee>
</Decision> </Decision>
</net.minecraft.entity.monster.EntityShulker> </net.minecraft.entity.monster.EntityShulker>
<net.minecraft.entity.monster.EntitySilverFish> <net.minecraft.entity.monster.EntitySilverfish>
<AttackPower Probability="85">1</AttackPower> <AttackPower Probability="85">1</AttackPower>
<Evasion>37</Evasion> <Evasion>37</Evasion>
<Category>monster</Category> <Category>monster</Category>
@ -222,7 +222,7 @@
<Defend>0</Defend> <Defend>0</Defend>
<Flee>0</Flee> <Flee>0</Flee>
</Decision> </Decision>
</net.minecraft.entity.monster.EntitySilverFish> </net.minecraft.entity.monster.EntitySilverfish>
<net.minecraft.entity.monster.EntitySkeleton> <net.minecraft.entity.monster.EntitySkeleton>
<AttackPower Probability="75" Variance="1">3</AttackPower> <AttackPower Probability="75" Variance="1">3</AttackPower>
<Evasion>13</Evasion> <Evasion>13</Evasion>