Implement use of vanilla bow/arrows in battle

This commit is contained in:
Stephen Seo 2018-09-17 15:49:10 +09:00
parent b684310be8
commit 9778c6a7d5
8 changed files with 144 additions and 9 deletions

View file

@ -1,10 +1,60 @@
package com.seodisparate.TurnBasedMinecraft.common; package com.seodisparate.TurnBasedMinecraft.common;
import java.util.ArrayDeque;
import java.util.Queue;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleMessage;
import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class AttackEventHandler public class AttackEventHandler
{ {
private boolean isAttackerValid(LivingAttackEvent event)
{
if(event.getSource().getTrueSource() == null)
{
return false;
}
else if(event.getSource().getTrueSource().equals(TurnBasedMinecraftMod.attackingEntity))
{
return true;
}
else
{
Queue<AttackerViaBow> removeQueue = new ArrayDeque<AttackerViaBow>();
final long now = System.nanoTime();
boolean isValid = false;
synchronized(TurnBasedMinecraftMod.attackerViaBow)
{
for(AttackerViaBow attacker : TurnBasedMinecraftMod.attackerViaBow)
{
if(now - attacker.attackTime >= AttackerViaBow.ATTACK_TIMEOUT)
{
removeQueue.add(attacker);
}
else if(event.getSource().getTrueSource().equals(attacker.entity) && event.getSource().isProjectile())
{
removeQueue.add(attacker);
isValid = true;
Battle b = TurnBasedMinecraftMod.battleManager.getBattleByID(attacker.battleID);
if(b != null)
{
b.sendMessageToAllPlayers(PacketBattleMessage.MessageType.ARROW_HIT, attacker.entity.getEntityId(), event.getEntity().getEntityId(), 0);
}
}
}
AttackerViaBow next = removeQueue.poll();
while(next != null)
{
TurnBasedMinecraftMod.attackerViaBow.remove(next);
next = removeQueue.poll();
}
}
return isValid;
}
}
@SubscribeEvent @SubscribeEvent
public void entityAttacked(LivingAttackEvent event) public void entityAttacked(LivingAttackEvent event)
{ {
@ -17,7 +67,7 @@ public class AttackEventHandler
TurnBasedMinecraftMod.battleManager = new BattleManager(TurnBasedMinecraftMod.logger); TurnBasedMinecraftMod.battleManager = new BattleManager(TurnBasedMinecraftMod.logger);
} }
if(!(event.getSource().getTrueSource() == null || event.getSource().getTrueSource().equals(TurnBasedMinecraftMod.attackingEntity)) && TurnBasedMinecraftMod.battleManager.checkAttack(event)) if(!isAttackerValid(event) && event.getEntity() != null && event.getSource().getTrueSource() != null && TurnBasedMinecraftMod.battleManager.checkAttack(event))
{ {
// TurnBasedMinecraftMod.logger.debug("Canceled LivingAttackEvent between " + TurnBasedMinecraftMod.attackingEntity + " and " + event.getEntity()); // TurnBasedMinecraftMod.logger.debug("Canceled LivingAttackEvent between " + TurnBasedMinecraftMod.attackingEntity + " and " + event.getEntity());
event.setCanceled(true); event.setCanceled(true);

View file

@ -0,0 +1,26 @@
package com.seodisparate.TurnBasedMinecraft.common;
import net.minecraft.entity.Entity;
public class AttackerViaBow
{
public static long ATTACK_TIMEOUT = 10000000000L;
public Entity entity;
public long attackTime;
public int battleID;
public AttackerViaBow()
{
entity = null;
attackTime = 0;
battleID = -1;
}
public AttackerViaBow(Entity entity, int battleID)
{
this.entity = entity;
attackTime = System.nanoTime();
this.battleID = battleID;
}
}

View file

@ -20,6 +20,7 @@ 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.init.Items;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBow;
import net.minecraft.item.ItemFood; import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemLingeringPotion; import net.minecraft.item.ItemLingeringPotion;
import net.minecraft.item.ItemPotion; import net.minecraft.item.ItemPotion;
@ -135,6 +136,7 @@ public class Battle
} }
Combatant newCombatant = new Combatant(e, entityInfo); Combatant newCombatant = new Combatant(e, entityInfo);
newCombatant.isSideA = true; newCombatant.isSideA = true;
newCombatant.battleID = getId();
this.sideA.put(e.getEntityId(), newCombatant); this.sideA.put(e.getEntityId(), newCombatant);
if(e instanceof EntityPlayer) if(e instanceof EntityPlayer)
{ {
@ -155,6 +157,7 @@ public class Battle
} }
Combatant newCombatant = new Combatant(e, entityInfo); Combatant newCombatant = new Combatant(e, entityInfo);
newCombatant.isSideA = false; newCombatant.isSideA = false;
newCombatant.battleID = getId();
this.sideB.put(e.getEntityId(), newCombatant); this.sideB.put(e.getEntityId(), newCombatant);
if(e instanceof EntityPlayer) if(e instanceof EntityPlayer)
{ {
@ -236,6 +239,7 @@ public class Battle
} }
Combatant newCombatant = new Combatant(e, entityInfo); Combatant newCombatant = new Combatant(e, entityInfo);
newCombatant.isSideA = true; newCombatant.isSideA = true;
newCombatant.battleID = getId();
sideA.put(e.getEntityId(), newCombatant); sideA.put(e.getEntityId(), newCombatant);
if(e instanceof EntityPlayer) if(e instanceof EntityPlayer)
{ {
@ -267,6 +271,7 @@ public class Battle
} }
Combatant newCombatant = new Combatant(e, entityInfo); Combatant newCombatant = new Combatant(e, entityInfo);
newCombatant.isSideA = false; newCombatant.isSideA = false;
newCombatant.battleID = getId();
sideB.put(e.getEntityId(), newCombatant); sideB.put(e.getEntityId(), newCombatant);
if(e instanceof EntityPlayer) if(e instanceof EntityPlayer)
{ {
@ -404,7 +409,7 @@ public class Battle
} }
} }
private void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount) protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount)
{ {
if(!isServer) if(!isServer)
{ {
@ -419,7 +424,7 @@ public class Battle
} }
} }
private void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount, String custom) protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount, String custom)
{ {
if(!isServer) if(!isServer)
{ {
@ -631,6 +636,32 @@ public class Battle
{ {
break; break;
} }
ItemStack heldItemStack = ((EntityPlayer)next.entity).getHeldItemMainhand();
if(heldItemStack.getItem() instanceof ItemBow)
{
if(Utility.doesPlayerHaveArrows((EntityPlayer)next.entity))
{
final Entity nextEntity = next.entity;
final Entity targetEntity = target.entity;
next.entity.getServer().addScheduledTask(() -> {
// have player look at attack target
((EntityPlayerMP)nextEntity).connection.setPlayerLocation(nextEntity.posX, nextEntity.posY, nextEntity.posZ, Utility.yawDirection(nextEntity.posX, nextEntity.posZ, targetEntity.posX, targetEntity.posZ), Utility.pitchDirection(nextEntity.posX, nextEntity.posY, nextEntity.posZ, targetEntity.posX, targetEntity.posY, targetEntity.posZ));
ItemBow itemBow = (ItemBow)heldItemStack.getItem();
synchronized(TurnBasedMinecraftMod.attackerViaBow)
{
TurnBasedMinecraftMod.attackerViaBow.add(new AttackerViaBow(nextEntity, getId()));
}
itemBow.onPlayerStoppedUsing(((EntityPlayer)nextEntity).getHeldItemMainhand(), nextEntity.getEntityWorld(), (EntityLivingBase)nextEntity, (int)(Math.random() * (itemBow.getMaxItemUseDuration(heldItemStack)) / 3));
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FIRED_ARROW, nextEntity.getEntityId(), targetEntity.getEntityId(), 0);
});
}
else
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.BOW_NO_AMMO, next.entity.getEntityId(), 0, 0);
}
next = turnOrderQueue.poll();
continue;
}
int hitChance = TurnBasedMinecraftMod.config.getPlayerAttackProbability(); int hitChance = TurnBasedMinecraftMod.config.getPlayerAttackProbability();
if(target.entity instanceof EntityPlayer) if(target.entity instanceof EntityPlayer)
{ {
@ -649,12 +680,11 @@ public class Battle
if(target.remainingDefenses <= 0) if(target.remainingDefenses <= 0)
{ {
// attack // attack
// TODO damage via bow and arrow
// have player look at attack target
final Entity nextEntity = next.entity; final Entity nextEntity = next.entity;
final Entity targetEntity = target.entity; final Entity targetEntity = target.entity;
final EntityInfo targetEntityInfo = target.entityInfo; final EntityInfo targetEntityInfo = target.entityInfo;
next.entity.getServer().addScheduledTask(() -> { next.entity.getServer().addScheduledTask(() -> {
// have player look at attack target
((EntityPlayerMP)nextEntity).connection.setPlayerLocation(nextEntity.posX, nextEntity.posY, nextEntity.posZ, Utility.yawDirection(nextEntity.posX, nextEntity.posZ, targetEntity.posX, targetEntity.posZ), Utility.pitchDirection(nextEntity.posX, nextEntity.posY, nextEntity.posZ, targetEntity.posX, targetEntity.posY, targetEntity.posZ)); ((EntityPlayerMP)nextEntity).connection.setPlayerLocation(nextEntity.posX, nextEntity.posY, nextEntity.posZ, Utility.yawDirection(nextEntity.posX, nextEntity.posZ, targetEntity.posX, targetEntity.posZ), Utility.pitchDirection(nextEntity.posX, nextEntity.posY, nextEntity.posZ, targetEntity.posX, targetEntity.posY, targetEntity.posZ));
TurnBasedMinecraftMod.attackingEntity = nextEntity; TurnBasedMinecraftMod.attackingEntity = nextEntity;
TurnBasedMinecraftMod.attackingDamage = 0; TurnBasedMinecraftMod.attackingDamage = 0;

View file

@ -18,6 +18,7 @@ public class Combatant
public int targetEntityID; public int targetEntityID;
public boolean isSideA; public boolean isSideA;
public int remainingDefenses; public int remainingDefenses;
public int battleID;
public Combatant() public Combatant()
{ {

View file

@ -1,8 +1,5 @@
package com.seodisparate.TurnBasedMinecraft.common; package com.seodisparate.TurnBasedMinecraft.common;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.MobEffects; import net.minecraft.init.MobEffects;
import net.minecraft.potion.PotionEffect; import net.minecraft.potion.PotionEffect;

View file

@ -1,6 +1,8 @@
package com.seodisparate.TurnBasedMinecraft.common; package com.seodisparate.TurnBasedMinecraft.common;
import java.time.Duration; import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -45,6 +47,7 @@ public class TurnBasedMinecraftMod
private static int packetHandlerID = 0; private static int packetHandlerID = 0;
protected static Entity attackingEntity; protected static Entity attackingEntity;
protected static int attackingDamage = 0; protected static int attackingDamage = 0;
protected static Set<AttackerViaBow> attackerViaBow;
protected static Config config; protected static Config config;
public static Battle currentBattle = null; public static Battle currentBattle = null;
@ -64,6 +67,7 @@ public class TurnBasedMinecraftMod
{ {
currentBattle = null; currentBattle = null;
battleManager = null; battleManager = null;
attackerViaBow = new HashSet<AttackerViaBow>();
commonProxy.setLogger(logger); commonProxy.setLogger(logger);
// register packets // register packets

View file

@ -1,5 +1,8 @@
package com.seodisparate.TurnBasedMinecraft.common; package com.seodisparate.TurnBasedMinecraft.common;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemArrow;
public class Utility public class Utility
{ {
public static float yawDirection(double posX, double posZ, double targetX, double targetZ) public static float yawDirection(double posX, double posZ, double targetX, double targetZ)
@ -28,4 +31,16 @@ public class Utility
return (float)(-Math.atan(diffY / distance) * 180.0 / Math.PI); return (float)(-Math.atan(diffY / distance) * 180.0 / Math.PI);
} }
} }
public static boolean doesPlayerHaveArrows(EntityPlayer player)
{
for(int i = 0; i < player.inventory.getSizeInventory(); ++i)
{
if(player.inventory.getStackInSlot(i).getItem() instanceof ItemArrow)
{
return true;
}
}
return false;
}
} }

View file

@ -34,7 +34,10 @@ public class PacketBattleMessage implements IMessage
TURN_END(12), TURN_END(12),
SWITCHED_ITEM(13), SWITCHED_ITEM(13),
WAS_AFFECTED(14), WAS_AFFECTED(14),
BECAME_CREATIVE(15); BECAME_CREATIVE(15),
FIRED_ARROW(16),
ARROW_HIT(17),
BOW_NO_AMMO(18);
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>();
@ -326,6 +329,15 @@ public class PacketBattleMessage implements IMessage
case BECAME_CREATIVE: case BECAME_CREATIVE:
TurnBasedMinecraftMod.commonProxy.displayString(from + " entered creative mode and left battle!"); TurnBasedMinecraftMod.commonProxy.displayString(from + " entered creative mode and left battle!");
break; break;
case FIRED_ARROW:
TurnBasedMinecraftMod.commonProxy.displayString(from + " let loose an arrow towards " + to + "!");
break;
case ARROW_HIT:
TurnBasedMinecraftMod.commonProxy.displayString(to + " was hit by " + from + "'s arrow!");
break;
case BOW_NO_AMMO:
TurnBasedMinecraftMod.commonProxy.displayString(from + " tried to use their bow but ran out of ammo!");
break;
} }
return null; return null;
} }