Add support for battles in different dimensions

This commit is contained in:
Stephen Seo 2019-11-29 13:47:39 +09:00
parent ac2a012bd3
commit 532cb21731
10 changed files with 231 additions and 163 deletions

View file

@ -169,12 +169,6 @@ public class ClientProxy extends CommonProxy
Minecraft.getInstance().player.sendMessage(text);
}
@Override
public Entity getEntityByID(int id)
{
return Minecraft.getInstance().world.getEntityByID(id);
}
private void checkBattleTypes()
{
float percentage = 0.0f;
@ -232,6 +226,6 @@ public class ClientProxy extends CommonProxy
@Override
public void createLocalBattle(int id)
{
localBattle = new Battle(null, id, null, null, false);
localBattle = new Battle(null, id, null, null, false, Minecraft.getInstance().world.dimension.getType());
}
}

View file

@ -125,6 +125,7 @@ public class AttackEventHandler
&& event.getEntity() != event.getSource().getTrueSource()
&& !config.getBattleIgnoringPlayers().contains(event.getSource().getTrueSource().getEntityId())
&& !config.getBattleIgnoringPlayers().contains(event.getEntity().getEntityId())
&& event.getEntity().dimension == event.getSource().getTrueSource().dimension
&& battleManager.checkAttack(event))
{
// TurnBasedMinecraftMod.logger.debug("Canceled LivingAttackEvent between " + TurnBasedMinecraftMod.proxy.getAttackingEntity() + " and " + event.getEntity());
@ -155,7 +156,8 @@ public class AttackEventHandler
else if(event.getEntity() != null
&& event.getTarget() != null
&& !config.getBattleIgnoringPlayers().contains(event.getEntity().getEntityId())
&& !config.getBattleIgnoringPlayers().contains(event.getTarget().getEntityId()))
&& !config.getBattleIgnoringPlayers().contains(event.getTarget().getEntityId())
&& event.getEntity().dimension == event.getTarget().dimension)
{
TurnBasedMinecraftMod.proxy.getBattleManager().checkTargeted(event);
}

View file

@ -14,6 +14,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.*;
import net.minecraft.util.DamageSource;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.fml.network.PacketDistributor;
public class Battle
@ -41,6 +42,8 @@ public class Battle
public String debugLog; // TODO remove after freeze bug has been found
private DimensionType dimension;
public enum State
{
DECISION(0),
@ -110,7 +113,7 @@ public class Battle
}
}
public Battle(BattleManager battleManager, int id, Collection<Entity> sideA, Collection<Entity> sideB, boolean isServer)
public Battle(BattleManager battleManager, int id, Collection<Entity> sideA, Collection<Entity> sideB, boolean isServer, DimensionType dimension)
{
this.battleManager = battleManager;
this.isServer = isServer;
@ -124,6 +127,7 @@ public class Battle
playerCount = new AtomicInteger(0);
undecidedCount = new AtomicInteger(0);
random = new Random();
this.dimension = dimension;
if(sideA != null)
{
for(Entity e : sideA)
@ -573,7 +577,7 @@ public class Battle
{
return;
}
PacketBattleMessage packet = new PacketBattleMessage(type, from, to, amount, custom);
PacketBattleMessage packet = new PacketBattleMessage(type, from, to, dimension, amount, custom);
for(Combatant p : players.values())
{
if(p.entity.isAlive())
@ -713,11 +717,33 @@ public class Battle
{
if(c.entity instanceof PlayerEntity)
{
TurnBasedMinecraftMod.getHandler().send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) c.entity), new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, 0));
TurnBasedMinecraftMod.getHandler().send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) c.entity), new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, dimension, 0));
}
battleManager.addRecentlyLeftBattle(c);
}
public void forceRemoveCombatant(EntityIDDimPair e) {
sideA.remove(e.id);
sideB.remove(e.id);
if(players.remove(e.id) != null) {
playerCount.decrementAndGet();
}
for(Iterator<Combatant> iter = sideAEntryQueue.iterator(); iter.hasNext();) {
Combatant c = iter.next();
if(c.entity.getEntityId() == e.id) {
iter.remove();
break;
}
}
for(Iterator<Combatant> iter = sideBEntryQueue.iterator(); iter.hasNext();) {
Combatant c = iter.next();
if(c.entity.getEntityId() == e.id) {
iter.remove();
break;
}
}
}
private void setDecisionState()
{
for(Combatant c : sideA.values())

View file

@ -8,6 +8,7 @@ import java.util.Map;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.network.PacketDistributor;
import org.apache.logging.log4j.Logger;
@ -25,6 +26,7 @@ public class BattleManager
private Logger logger;
private Map<Integer, Combatant> recentlyLeftBattle;
private BattleUpdater battleUpdater;
private Map<EntityIDDimPair, Integer> entityToBattleMap;
public BattleManager(Logger logger)
{
@ -32,6 +34,7 @@ public class BattleManager
battleMap = new HashMap<Integer, Battle>();
recentlyLeftBattle = new HashMap<Integer, Combatant>();
battleUpdater = new BattleUpdater(this);
entityToBattleMap = new HashMap<EntityIDDimPair, Integer>();
MinecraftForge.EVENT_BUS.register(battleUpdater);
}
@ -73,7 +76,7 @@ public class BattleManager
|| !((event.getSource().getTrueSource() instanceof PlayerEntity && !((PlayerEntity)event.getSource().getTrueSource()).isCreative())
|| (config.getEntityInfoReference(attackerClassName) != null || config.getCustomEntityInfoReference(attackerCustomName) != null)))
{
logger.debug("BattleManager: Failed first check, attacker is \"" + attackerClassName + "\", defender is \"" + receiverClassName + "\"");
// logger.debug("BattleManager: Failed first check, attacker is \"" + attackerClassName + "\", defender is \"" + receiverClassName + "\"");
return false;
}
@ -87,19 +90,14 @@ public class BattleManager
if(entityInfo != null && (config.isIgnoreBattleType(entityInfo.category) || entityInfo.ignoreBattle))
{
// attacked entity ignores battle
synchronized(battleMap)
{
for(Battle b : battleMap.values())
{
if(b.hasCombatant(event.getSource().getTrueSource().getEntityId()))
{
logger.debug("Attack Canceled: attacked ignores battle but attacker in battle");
return true;
}
}
Battle battle = battleMap.get(entityToBattleMap.get(new EntityIDDimPair(event.getSource().getTrueSource())));
if(battle != null && battle.hasCombatant(event.getSource().getTrueSource().getEntityId())) {
logger.debug("Attack Canceled: attacked ignores battle but attacker in battle");
return true;
} else {
logger.debug("Attack Not Canceled: attacked ignores battle");
return false;
}
logger.debug("Attack Not Canceled: attacked ignores battle");
return false;
}
entityInfo = config.getCustomEntityInfoReference(attackerCustomName);
@ -111,65 +109,30 @@ public class BattleManager
if(entityInfo != null && (config.isIgnoreBattleType(entityInfo.category) || entityInfo.ignoreBattle))
{
// attacker entity ignores battle
synchronized(battleMap)
{
for(Battle b : battleMap.values())
{
if(b.hasCombatant(event.getEntity().getEntityId()))
{
logger.debug("Attack Canceled: attacker ignores battle but attacked in battle");
return true;
}
}
Battle battle = battleMap.get(entityToBattleMap.get(new EntityIDDimPair(event.getEntity())));
if(battle != null && battle.hasCombatant(event.getEntity().getEntityId())) {
logger.debug("Attack Canceled: attacker ignores battle but attacked in battle");
return true;
} else {
logger.debug("Attack Not Canceled: attacker ignores battle");
return false;
}
logger.debug("Attack Not Canceled: attacker ignores battle");
return false;
}
// check if one is in battle
Entity inBattle = null;
Entity notInBattle = null;
Battle battle = null;
synchronized(battleMap)
{
for(Battle b : battleMap.values())
{
if(b.hasCombatant(event.getSource().getTrueSource().getEntityId()))
{
if(inBattle != null)
{
// both combatants are in battle
logger.debug("Attack Canceled: both are in battle");
return true;
}
else
{
inBattle = event.getSource().getTrueSource();
notInBattle = event.getEntity();
battle = b;
}
}
if(b.hasCombatant(event.getEntity().getEntityId()))
{
if(inBattle != null)
{
// both combatants are in battle
logger.debug("Attack Canceled: both are in battle");
return true;
}
else
{
inBattle = event.getEntity();
notInBattle = event.getSource().getTrueSource();
battle = b;
}
}
}
Battle attackerBattle = battleMap.get(entityToBattleMap.get(new EntityIDDimPair(event.getSource().getTrueSource())));
if(attackerBattle != null && !attackerBattle.hasCombatant(event.getSource().getTrueSource().getEntityId())) {
attackerBattle = null;
}
Battle defenderBattle = battleMap.get(entityToBattleMap.get(new EntityIDDimPair(event.getEntity())));
if(defenderBattle != null && !defenderBattle.hasCombatant(event.getEntity().getEntityId())) {
defenderBattle = null;
}
if(inBattle == null)
{
if(attackerBattle != null && defenderBattle != null) {
// both in battle, attack canceled
return true;
} else if(attackerBattle == null && defenderBattle == null) {
// neither entity is in battle
if(event.getEntity() instanceof PlayerEntity || event.getSource().getTrueSource() instanceof PlayerEntity)
{
@ -178,7 +141,7 @@ public class BattleManager
Collection<Entity> sideB = new ArrayList<Entity>(1);
sideA.add(event.getEntity());
sideB.add(event.getSource().getTrueSource());
createBattle(sideA, sideB);
createBattle(sideA, sideB, event.getEntity().dimension);
logger.debug("Attack Not Canceled: new battle created");
}
else
@ -186,21 +149,29 @@ public class BattleManager
logger.debug("Attack Not Canceled: neither are in battle or players");
}
return false;
}
// at this point only one entity is in battle, so add entity to other side
if(battle.getSize() >= config.getMaxInBattle())
{
// battle limit reached, cannot add to battle
return true;
}
else if(battle.hasCombatantInSideA(inBattle.getEntityId()))
{
battle.addCombatantToSideB(notInBattle);
}
else
{
battle.addCombatantToSideA(notInBattle);
} else {
// at this point only one entity is in battle, so add entity to other side
if(attackerBattle != null) {
if (attackerBattle.getSize() >= config.getMaxInBattle()) {
// battle limit reached, cannot add to battle
return true;
} else if (attackerBattle.hasCombatantInSideA(event.getSource().getTrueSource().getEntityId())) {
attackerBattle.addCombatantToSideB(event.getEntity());
} else {
attackerBattle.addCombatantToSideA(event.getEntity());
}
entityToBattleMap.put(new EntityIDDimPair(event.getEntity()), attackerBattle.getId());
} else {
if (defenderBattle.getSize() >= config.getMaxInBattle()) {
// battle limit reached, cannot add to battle
return true;
} else if (defenderBattle.hasCombatantInSideA(event.getEntity().getEntityId())) {
defenderBattle.addCombatantToSideB(event.getSource().getTrueSource());
} else {
defenderBattle.addCombatantToSideA(event.getSource().getTrueSource());
}
entityToBattleMap.put(new EntityIDDimPair(event.getSource().getTrueSource()), defenderBattle.getId());
}
}
logger.debug("Attack Canceled: one is in battle");
@ -252,47 +223,19 @@ public class BattleManager
return;
}
Entity inBattle = null;
Entity notInBattle = null;
Battle battle = null;
synchronized(battleMap)
{
for(Battle b : battleMap.values())
{
if(b.hasCombatant(event.getEntity().getEntityId()))
{
if(inBattle != null)
{
// both entities already in battle
return;
}
else
{
inBattle = event.getEntity();
notInBattle = event.getTarget();
battle = b;
}
}
if(b.hasCombatant(event.getTarget().getEntityId()))
{
if(inBattle != null)
{
// both entities already in battle
return;
}
else
{
inBattle = event.getTarget();
notInBattle = event.getEntity();
battle = b;
}
}
}
// check if one is in battle
Battle attackerBattle = battleMap.get(entityToBattleMap.get(new EntityIDDimPair(event.getEntity())));
if(attackerBattle != null && !attackerBattle.hasCombatant(event.getEntity().getEntityId())) {
attackerBattle = null;
}
Battle defenderBattle = battleMap.get(entityToBattleMap.get(new EntityIDDimPair(event.getTarget())));
if(defenderBattle != null && !defenderBattle.hasCombatant(event.getTarget().getEntityId())) {
defenderBattle = null;
}
if(battle == null)
{
if(attackerBattle != null && defenderBattle != null) {
return;
} else if(attackerBattle == null && defenderBattle == null) {
// neither in battle
if(event.getEntity() instanceof PlayerEntity || event.getTarget() instanceof PlayerEntity)
{
@ -301,29 +244,36 @@ public class BattleManager
Collection<Entity> sideB = new ArrayList<Entity>(1);
sideA.add(event.getEntity());
sideB.add(event.getTarget());
createBattle(sideA, sideB);
createBattle(sideA, sideB, event.getEntity().dimension);
logger.debug("neither in battle, at least one is player, creating new battle");
}
}
else
{
} else {
// add entity to battle
if(battle.getSize() >= TurnBasedMinecraftMod.proxy.getConfig().getMaxInBattle())
{
// battle max reached, cannot add to battle
return;
}
else if(battle.hasCombatantInSideA(inBattle.getEntityId()))
{
battle.addCombatantToSideB(notInBattle);
}
else
{
battle.addCombatantToSideA(notInBattle);
if(attackerBattle != null) {
if (attackerBattle.getSize() >= TurnBasedMinecraftMod.proxy.getConfig().getMaxInBattle()) {
// battle max reached, cannot add to battle
return;
} else if (attackerBattle.hasCombatantInSideA(event.getEntity().getEntityId())) {
attackerBattle.addCombatantToSideB(event.getTarget());
} else {
attackerBattle.addCombatantToSideA(event.getTarget());
}
entityToBattleMap.put(new EntityIDDimPair(event.getTarget()), attackerBattle.getId());
} else {
if (defenderBattle.getSize() >= TurnBasedMinecraftMod.proxy.getConfig().getMaxInBattle()) {
// battle max reached, cannot add to battle
return;
} else if (defenderBattle.hasCombatantInSideA(event.getTarget().getEntityId())) {
defenderBattle.addCombatantToSideB(event.getEntity());
} else {
defenderBattle.addCombatantToSideA(event.getEntity());
}
entityToBattleMap.put(new EntityIDDimPair(event.getEntity()), defenderBattle.getId());
}
}
}
private Battle createBattle(Collection<Entity> sideA, Collection<Entity> sideB)
private Battle createBattle(Collection<Entity> sideA, Collection<Entity> sideB, DimensionType dimension)
{
Battle newBattle = null;
synchronized(battleMap)
@ -332,9 +282,15 @@ public class BattleManager
{
++IDCounter;
}
newBattle = new Battle(this, IDCounter, sideA, sideB, true);
newBattle = new Battle(this, IDCounter, sideA, sideB, true, dimension);
battleMap.put(IDCounter, newBattle);
}
for(Entity e : sideA) {
entityToBattleMap.put(new EntityIDDimPair(e), newBattle.getId());
}
for(Entity e : sideB) {
entityToBattleMap.put(new EntityIDDimPair(e), newBattle.getId());
}
newBattle.notifyPlayersBattleInfo();
return newBattle;
}
@ -368,6 +324,7 @@ public class BattleManager
synchronized(recentlyLeftBattle) {
recentlyLeftBattle.put(c.entity.getEntityId(), c);
}
entityToBattleMap.remove(new EntityIDDimPair(c.entity));
}
protected void updateRecentlyLeftBattle()
@ -397,4 +354,18 @@ public class BattleManager
return recentlyLeftBattle.containsKey(entityID);
}
}
public boolean forceLeaveBattle(EntityIDDimPair entityInfo) {
boolean result = false;
Integer battleID = entityToBattleMap.get(entityInfo);
if(battleID != null) {
Battle battle = battleMap.get(battleID);
if (battle != null && battle.hasCombatant(entityInfo.id)) {
battle.forceRemoveCombatant(entityInfo);
result = true;
}
entityToBattleMap.remove(entityInfo);
}
return result;
}
}

View file

@ -93,12 +93,6 @@ public class CommonProxy
public void displayTextComponent(ITextComponent textComponent) {}
public Entity getEntityByID(int id)
{
// TODO validate dimension of entity
return ServerLifecycleHooks.getCurrentServer().getWorld(DimensionType.OVERWORLD).getEntityByID(id);
}
public final boolean isServerRunning()
{
return battleManager != null;

View file

@ -0,0 +1,22 @@
package com.burnedkirby.TurnBasedMinecraft.common;
import com.burnedkirby.TurnBasedMinecraft.common.networking.PacketGeneralMessage;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraftforge.event.entity.EntityTravelToDimensionEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.network.PacketDistributor;
public class DimensionChangedHandler {
@SubscribeEvent
public void dimensionChanged(EntityTravelToDimensionEvent event) {
if(event.getEntity().world.isRemote) {
return;
}
if(TurnBasedMinecraftMod.proxy.getBattleManager().forceLeaveBattle(new EntityIDDimPair(event.getEntity()))
&& event.getEntity() instanceof ServerPlayerEntity) {
TurnBasedMinecraftMod.getHandler().send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity)event.getEntity()),
new PacketGeneralMessage("Left battle due to moving to a different dimension"));
}
}
}

View file

@ -0,0 +1,44 @@
package com.burnedkirby.TurnBasedMinecraft.common;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.common.DimensionManager;
public class EntityIDDimPair {
public int id;
public DimensionType dim;
EntityIDDimPair() {
id = 0;
dim = Minecraft.getInstance().world.dimension.getType();
}
EntityIDDimPair(int id, DimensionType dim) {
this.id = id;
this.dim = dim;
}
EntityIDDimPair(Entity entity) {
id = entity.getEntityId();
dim = entity.dimension;
}
public Entity getEntity() {
return Utility.getEntity(id, dim);
}
@Override
public int hashCode() {
return (id + dim.toString()).hashCode();
}
@Override
public boolean equals(Object other) {
if(other instanceof EntityIDDimPair) {
EntityIDDimPair otherPair = (EntityIDDimPair) other;
return otherPair.id == id && otherPair.dim == dim;
}
return false;
}
}

View file

@ -122,6 +122,7 @@ public class TurnBasedMinecraftMod
// register event handler(s)
MinecraftForge.EVENT_BUS.register(new AttackEventHandler());
MinecraftForge.EVENT_BUS.register(new PlayerJoinEventHandler());
MinecraftForge.EVENT_BUS.register(new DimensionChangedHandler());
logger.debug("Init com_burnedkirby_turnbasedminecraft");
}

View file

@ -3,6 +3,8 @@ package com.burnedkirby.TurnBasedMinecraft.common;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ArrowItem;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
public class Utility
{
@ -49,4 +51,8 @@ public class Utility
{
return Math.sqrt(Math.pow(a.posX - b.posX, 2.0) + Math.pow(a.posY - b.posY, 2.0) + Math.pow(a.posZ - b.posZ, 2.0));
}
public static Entity getEntity(int id, DimensionType dimension) {
return ServerLifecycleHooks.getCurrentServer().getWorld(dimension).getEntityByID(id);
}
}

View file

@ -6,8 +6,11 @@ import java.util.function.Supplier;
import com.burnedkirby.TurnBasedMinecraft.common.TurnBasedMinecraftMod;
import com.burnedkirby.TurnBasedMinecraft.common.Utility;
import net.minecraft.entity.Entity;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.fml.network.NetworkEvent;
public class PacketBattleMessage
@ -100,23 +103,26 @@ public class PacketBattleMessage
int entityIDTo;
int amount;
String custom;
DimensionType dimension;
public PacketBattleMessage() { custom = new String(); }
public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, int amount)
public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, DimensionType dimension, int amount)
{
this.messageType = messageType;
this.entityIDFrom = entityIDFrom;
this.entityIDTo = entityIDTo;
this.dimension = dimension;
this.amount = amount;
custom = new String();
}
public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, int amount, String custom)
public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, DimensionType dimension, int amount, String custom)
{
this.messageType = messageType;
this.entityIDFrom = entityIDFrom;
this.entityIDTo = entityIDTo;
this.dimension = dimension;
this.amount = amount;
this.custom = custom;
}
@ -125,6 +131,7 @@ public class PacketBattleMessage
buf.writeInt(pkt.messageType.getValue());
buf.writeInt(pkt.entityIDFrom);
buf.writeInt(pkt.entityIDTo);
buf.writeString(DimensionType.getKey(pkt.dimension).toString());
buf.writeInt(pkt.amount);
buf.writeString(pkt.custom);
}
@ -135,6 +142,7 @@ public class PacketBattleMessage
buf.readInt()),
buf.readInt(),
buf.readInt(),
DimensionType.byName(new ResourceLocation(buf.readString())),
buf.readInt(),
buf.readString());
}
@ -142,7 +150,7 @@ public class PacketBattleMessage
public static class Handler {
public static void handle(final PacketBattleMessage pkt, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
Entity fromEntity = TurnBasedMinecraftMod.proxy.getEntityByID(pkt.entityIDFrom);
Entity fromEntity = Utility.getEntity(pkt.entityIDFrom, pkt.dimension);
String from = "Unknown";
if(fromEntity != null)
{
@ -156,7 +164,7 @@ public class PacketBattleMessage
from = fromEntity.getDisplayName().getFormattedText();
}
}
Entity toEntity = TurnBasedMinecraftMod.proxy.getEntityByID(pkt.entityIDTo);
Entity toEntity = Utility.getEntity(pkt.entityIDTo, pkt.dimension);
String to = "Unknown";
if(toEntity != null)
{