From b1b80d81065051e18781b0ea3a7aba09c5174854 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Wed, 20 May 2020 18:50:07 -0400 Subject: [PATCH 01/27] some adjustments to these caches to reduce ram use --- .../java/pokecube/core/items/ItemPokedex.java | 2 +- .../world/terrain/PokecubeTerrainChecker.java | 2 +- .../thut/api/terrain/ITerrainProvider.java | 71 +++++++++++++------ .../thut/api/terrain/StructureManager.java | 46 ++++++++---- src/main/java/thut/core/common/ThutCore.java | 2 - 5 files changed, 84 insertions(+), 39 deletions(-) diff --git a/src/main/java/pokecube/core/items/ItemPokedex.java b/src/main/java/pokecube/core/items/ItemPokedex.java index 9d935994cb..6a6634b3eb 100644 --- a/src/main/java/pokecube/core/items/ItemPokedex.java +++ b/src/main/java/pokecube/core/items/ItemPokedex.java @@ -103,7 +103,7 @@ public ActionResultType onItemUse(final ItemUseContext context) SpawnHandler.refreshTerrain(Vector3.getNewVector().set(playerIn), playerIn.getEntityWorld(), true); if (PokecubeMod.debug) { - final Set infos = StructureManager.getFor(pos); + final Set infos = StructureManager.getFor(worldIn.getDimension().getType(), pos); for (final StructureInfo i : infos) playerIn.sendMessage(new StringTextComponent(i.name)); } diff --git a/src/main/java/pokecube/core/world/terrain/PokecubeTerrainChecker.java b/src/main/java/pokecube/core/world/terrain/PokecubeTerrainChecker.java index e749365d45..54bf7d52ae 100644 --- a/src/main/java/pokecube/core/world/terrain/PokecubeTerrainChecker.java +++ b/src/main/java/pokecube/core/world/terrain/PokecubeTerrainChecker.java @@ -127,7 +127,7 @@ public int getSubBiome(final IWorld world, final Vector3 v, final TerrainSegment { if (caveAdjusted) { - final Set set = StructureManager.getFor(v.getPos()); + final Set set = StructureManager.getFor(world.getDimension().getType(), v.getPos()); for (final StructureInfo info : set) { final String name = info.name; diff --git a/src/main/java/thut/api/terrain/ITerrainProvider.java b/src/main/java/thut/api/terrain/ITerrainProvider.java index 1eb724b049..e51d5ddb0d 100644 --- a/src/main/java/thut/api/terrain/ITerrainProvider.java +++ b/src/main/java/thut/api/terrain/ITerrainProvider.java @@ -1,10 +1,7 @@ package thut.api.terrain; -import java.util.Collections; import java.util.Map; -import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; @@ -18,12 +15,46 @@ public interface ITerrainProvider { Object lock = new Object(); + static class TerrainCache + { + TerrainSegment[] segs = new TerrainSegment[16]; + int num = 16; + + public TerrainCache(final ChunkPos temp, final IChunk chunk) + { + for (int i = 0; i < 16; i++) + { + this.segs[i] = new TerrainSegment(temp.x, i, temp.z); + this.segs[i].chunk = chunk; + this.segs[i].real = false; + } + } + + public TerrainSegment remove(final int y) + { + final TerrainSegment seg = this.segs[y]; + if (seg == null) return null; + this.num--; + return seg; + } + + public boolean isValid() + { + return this.num > 0; + } + + public TerrainSegment get(final int y) + { + return this.segs[y]; + } + } + /** * This is a cache of pending terrain segments, it is used as sometimes * segments need to have things set for them which the chunk is still being * generated, ie not completely loaded. */ - public static Map> pendingCache = new Object2ObjectOpenHashMap<>(); + public static Map pendingCache = new Object2ObjectOpenHashMap<>(); /** * This is a cache of loaded chunks, it is used to prevent thread lock @@ -71,7 +102,12 @@ public static IChunk getChunk(final DimensionType dim, final ChunkPos cpos) public static TerrainSegment removeCached(final DimensionType dim, final BlockPos pos) { - return ITerrainProvider.pendingCache.getOrDefault(dim, Collections.emptyMap()).remove(pos); + final GlobalChunkPos wpos = new GlobalChunkPos(dim, new ChunkPos(pos.getX(), pos.getZ())); + final TerrainCache segs = ITerrainProvider.pendingCache.get(wpos); + if (segs == null) return null; + final TerrainSegment var = segs.remove(pos.getY()); + if (!segs.isValid()) ITerrainProvider.pendingCache.remove(wpos); + return var; } /** @@ -93,23 +129,16 @@ default TerrainSegment getTerrain(final IWorld world, final BlockPos p) // This means it occurs during worldgen? if (!real) { - final Map dimMap = ITerrainProvider.pendingCache.getOrDefault(dim, Maps - .newConcurrentMap()); - /** - * Here we need to make a new terrain segment, and cache it, then - * later if the world is actually available, we can get the terrain - * segment. from that. - */ - if (dimMap.containsKey(pos)) return dimMap.get(pos); - // No real world, so lets deal with the cache. - final TerrainSegment segment = new TerrainSegment(pos); - segment.chunk = chunk; - segment.real = false; - dimMap.put(pos, segment); - if (!ITerrainProvider.pendingCache.containsKey(dim)) ITerrainProvider.pendingCache.put(dim, dimMap); - return segment; - } + final GlobalChunkPos wpos = new GlobalChunkPos(dim, temp); + TerrainCache segs = ITerrainProvider.pendingCache.get(wpos); + if (segs == null) + { + segs = new TerrainCache(temp, chunk); + ITerrainProvider.pendingCache.put(wpos, segs); + } + return segs.get(pos.getY()); + } final CapabilityTerrain.ITerrainProvider provider = ((ICapabilityProvider) chunk).getCapability( ThutCaps.TERRAIN_CAP).orElse(null); provider.setChunk(chunk); diff --git a/src/main/java/thut/api/terrain/StructureManager.java b/src/main/java/thut/api/terrain/StructureManager.java index e97d97a4f0..dcb81f8c20 100644 --- a/src/main/java/thut/api/terrain/StructureManager.java +++ b/src/main/java/thut/api/terrain/StructureManager.java @@ -1,15 +1,17 @@ package thut.api.terrain; import java.util.Collections; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; import com.google.common.collect.Sets; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MutableBoundingBox; +import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.feature.structure.StructurePiece; import net.minecraft.world.gen.feature.structure.StructureStart; import net.minecraftforge.event.world.ChunkEvent; @@ -83,23 +85,25 @@ private static boolean sameBounds(final MutableBoundingBox boxA, final MutableBo } } - private static Long2ObjectOpenHashMap> map_by_chunk = new Long2ObjectOpenHashMap<>(); + /** + * This is a cache of loaded chunks, it is used to prevent thread lock + * contention when trying to look up a chunk, as it seems that + * world.chunkExists returning true does not mean that you can just go and + * ask for the chunk... + */ + public static Map> map_by_pos = new Object2ObjectOpenHashMap<>(); - private static Set getOrMake(final long pos) + private static Set getOrMake(final GlobalChunkPos pos) { - final Set set = StructureManager.map_by_chunk.getOrDefault(pos, Sets.newHashSet()); - if (!StructureManager.map_by_chunk.containsKey(pos)) StructureManager.map_by_chunk.put(pos, set); + final Set set = StructureManager.map_by_pos.getOrDefault(pos, Sets.newHashSet()); + if (!StructureManager.map_by_pos.containsKey(pos)) StructureManager.map_by_pos.put(pos, set); return set; } - public static Set getFor(final long pos) + public static Set getFor(final DimensionType dim, final BlockPos loc) { - return StructureManager.map_by_chunk.getOrDefault(pos, Collections.emptySet()); - } - - public static Set getFor(final BlockPos loc) - { - final Set forPos = StructureManager.getFor(new ChunkPos(loc).asLong()); + final GlobalChunkPos pos = new GlobalChunkPos(dim, new ChunkPos(loc)); + final Set forPos = StructureManager.map_by_pos.getOrDefault(pos, Collections.emptySet()); if (forPos.isEmpty()) return forPos; final Set matches = Sets.newHashSet(); for (final StructureInfo i : forPos) @@ -110,6 +114,8 @@ public static Set getFor(final BlockPos loc) @SubscribeEvent public static void onChunkLoad(final ChunkEvent.Load evt) { + if (evt.getWorld().isRemote()) return; + final DimensionType dim = evt.getWorld().getDimension().getType(); for (final Entry entry : evt.getChunk().getStructureStarts().entrySet()) { final StructureInfo info = new StructureInfo(entry); @@ -118,14 +124,26 @@ public static void onChunkLoad(final ChunkEvent.Load evt) for (int z = b.minZ >> 4; z <= b.maxZ >> 4; z++) { final ChunkPos p = new ChunkPos(x, z); - final Set set = StructureManager.getOrMake(p.asLong()); + final GlobalChunkPos pos = new GlobalChunkPos(dim, p); + final Set set = StructureManager.getOrMake(pos); set.add(info); } } } + @SubscribeEvent + public static void onChunkUnload(final ChunkEvent.Unload evt) + { + if (evt.getWorld().isRemote()) return; + final DimensionType dim = evt.getWorld().getDimension().getType(); + final GlobalChunkPos pos = new GlobalChunkPos(dim, evt.getChunk().getPos()); + StructureManager.map_by_pos.remove(pos); + } + public static void clear() { - StructureManager.map_by_chunk.clear(); + StructureManager.map_by_pos.clear(); + ITerrainProvider.loadedChunks.clear(); + ITerrainProvider.pendingCache.clear(); } } diff --git a/src/main/java/thut/core/common/ThutCore.java b/src/main/java/thut/core/common/ThutCore.java index 69c01e260c..f99faecd3e 100644 --- a/src/main/java/thut/core/common/ThutCore.java +++ b/src/main/java/thut/core/common/ThutCore.java @@ -56,7 +56,6 @@ import thut.api.entity.genetics.IMobGenetics; import thut.api.particle.ThutParticles; import thut.api.terrain.CapabilityTerrain; -import thut.api.terrain.ITerrainProvider; import thut.api.terrain.StructureManager; import thut.api.world.mobs.data.DataSync; import thut.core.common.config.Config; @@ -243,7 +242,6 @@ public void onServerAboutToStart(final FMLServerAboutToStartEvent event) { // do something when the server starts ThutCore.LOGGER.debug("Clearing terrain cache"); - ITerrainProvider.pendingCache.clear(); StructureManager.clear(); } From c5429e66af7b80145b857824e35c8dd1a428d7f4 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Wed, 20 May 2020 19:19:30 -0400 Subject: [PATCH 02/27] adjustments to memory tweaks in last commit --- src/main/java/thut/api/terrain/StructureManager.java | 7 ++++--- src/main/java/thut/api/terrain/TerrainManager.java | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/thut/api/terrain/StructureManager.java b/src/main/java/thut/api/terrain/StructureManager.java index dcb81f8c20..fc14b75618 100644 --- a/src/main/java/thut/api/terrain/StructureManager.java +++ b/src/main/java/thut/api/terrain/StructureManager.java @@ -114,7 +114,8 @@ public static Set getFor(final DimensionType dim, final BlockPos @SubscribeEvent public static void onChunkLoad(final ChunkEvent.Load evt) { - if (evt.getWorld().isRemote()) return; + // The world is null when it is loaded off thread during worldgen! + if (evt.getWorld() == null || evt.getWorld().isRemote()) return; final DimensionType dim = evt.getWorld().getDimension().getType(); for (final Entry entry : evt.getChunk().getStructureStarts().entrySet()) { @@ -134,8 +135,8 @@ public static void onChunkLoad(final ChunkEvent.Load evt) @SubscribeEvent public static void onChunkUnload(final ChunkEvent.Unload evt) { - if (evt.getWorld().isRemote()) return; - final DimensionType dim = evt.getWorld().getDimension().getType(); + if (evt.getWorld() == null || evt.getWorld().isRemote()) return; + final DimensionType dim = evt.getChunk().getWorldForge().getDimension().getType(); final GlobalChunkPos pos = new GlobalChunkPos(dim, evt.getChunk().getPos()); StructureManager.map_by_pos.remove(pos); } diff --git a/src/main/java/thut/api/terrain/TerrainManager.java b/src/main/java/thut/api/terrain/TerrainManager.java index d8a2df387e..8508b4d289 100644 --- a/src/main/java/thut/api/terrain/TerrainManager.java +++ b/src/main/java/thut/api/terrain/TerrainManager.java @@ -81,6 +81,8 @@ public static void onChunkLoad(final ChunkEvent.Load evt) DimensionType dim = null; if (evt.getWorld() != null && evt.getWorld().getDimension() != null) dim = evt.getWorld().getDimension() .getType(); + // This is null when this is loaded off-thread, IE before the chunk is + // finished if (dim != null) ITerrainProvider.addChunk(dim, evt.getChunk()); } From b11fda01dcf3b10fb048cb83320f47b7ac0d933c Mon Sep 17 00:00:00 2001 From: Thutmose Date: Wed, 20 May 2020 19:19:40 -0400 Subject: [PATCH 03/27] Update PokemobSexed.java adjustments to breeding criteria --- .../core/interfaces/capabilities/impl/PokemobSexed.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java index 68cdf7a42c..7cf4f90ba1 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java @@ -47,6 +47,10 @@ public boolean canMate(final AgeableEntity otherAnimal) // Not allowed to mate! if (!otherMob.isRoutineEnabled(AIRoutine.MATE)) return false; + // Don't let tame and wild breed, prevents exploits with dittos + if (otherMob.getOwnerId() != null && this.getOwnerId() == null) return false; + if (this.getOwnerId() != null && otherMob.getOwnerId() == null) return false; + PokedexEntry thisEntry = this.getPokedexEntry(); PokedexEntry thatEntry = otherMob.getPokedexEntry(); From c82b66d38f0fdc272d1f6cd5307e38085ba9d04a Mon Sep 17 00:00:00 2001 From: Thutmose Date: Wed, 20 May 2020 19:19:54 -0400 Subject: [PATCH 04/27] Update PlayerPokemobCache.java fixes a client side bug on reverting mega evolutions --- .../pokecube/core/handlers/playerdata/PlayerPokemobCache.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/pokecube/core/handlers/playerdata/PlayerPokemobCache.java b/src/main/java/pokecube/core/handlers/playerdata/PlayerPokemobCache.java index 1db33bc4eb..441711d426 100644 --- a/src/main/java/pokecube/core/handlers/playerdata/PlayerPokemobCache.java +++ b/src/main/java/pokecube/core/handlers/playerdata/PlayerPokemobCache.java @@ -23,6 +23,7 @@ public class PlayerPokemobCache extends PlayerData public static void UpdateCache(final IPokemob mob) { if (!mob.isPlayerOwned() || mob.getOwnerId() == null) return; + if (!mob.getEntity().isServerWorld()) return; final ItemStack stack = PokecubeManager.pokemobToItem(mob); final MinecraftServer server = LogicalSidedProvider.INSTANCE.get(LogicalSide.SERVER); // Schedule this to run at some point, as it takes a while. From 76cb2a94b549a0ec649c4728f69b2b3db6db0b35 Mon Sep 17 00:00:00 2001 From: NelkGames Date: Wed, 20 May 2020 20:23:19 -0300 Subject: [PATCH 05/27] Update Files (Mobs) (#390) # Fix: - corrected shiny Reshiram - corrected materials with incorrect transparency # Rework: - Glalie --- .../gen_3/entity/models/glalie.x3d | 220 ++++++++++++++---- .../gen_3/entity/models/glalie.xml | 47 +++- .../gen_3/entity/models/rayquaza_mega.xml | 6 + .../gen_3/entity/textures/glalie.png | Bin 3348 -> 199 bytes .../gen_3/entity/textures/glalieeye.png | Bin 0 -> 363 bytes .../gen_3/entity/textures/glalieeyes.png | Bin 0 -> 363 bytes .../gen_3/entity/textures/glalies.png | Bin 6755 -> 199 bytes .../gen_5/entity/models/litwick.xml | 2 +- .../gen_5/entity/models/reshiram.x3d | 12 +- .../gen_5/entity/models/virizion.x3d | 8 +- .../gen_5/entity/textures/reshirams.png | Bin 592 -> 365 bytes .../gen_6/entity/models/amaura.xml | 2 +- .../gen_6/entity/models/aurorus.xml | 2 +- .../gen_6/entity/models/litleo.x3d | 8 +- .../gen_6/entity/models/yveltal.x3d | 80 +++---- .../gen_6/entity/models/zygarde_10.xml | 1 + .../gen_6/entity/models/zygarde_100.xml | 2 +- .../gen_7/entity/models/morelull.xml | 2 +- .../gen_7/entity/models/solgaleo_dusk.xml | 2 +- 19 files changed, 286 insertions(+), 108 deletions(-) create mode 100644 src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalieeye.png create mode 100644 src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalieeyes.png diff --git a/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.x3d b/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.x3d index ba2b90c46a..1d19bb1a74 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.x3d +++ b/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.x3d @@ -1,9 +1,8 @@ - - + - + - - - + - + - - - + + + - - - + - + - - - + + + - - - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.xml b/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.xml index eea6be45be..d151595e6e 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/glalie.xml @@ -1,7 +1,50 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/rayquaza_mega.xml b/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/rayquaza_mega.xml index 0b26a94c9e..758744e811 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/rayquaza_mega.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_3/entity/models/rayquaza_mega.xml @@ -6,24 +6,30 @@ + + + + + + diff --git a/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalie.png b/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalie.png index e73b749c41a30f4d82152d151ecc1607c148e224..6c30e167204b7c9f9800bf1fa79ef6673d24ad7b 100644 GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^GC-`w!VDyX7}Ugp6k~CayA#8@b22Z19F}xPUq=Rp zjs4tz5?O(Kg8-ipR|8Y4*-KX5xN+n1>(3uQd;|*P2R8p+yauY^EbxddW?fsG K=d#Wzp$PyN1~C8t literal 3348 zcmeHIi9gic8b6kIEZLe04YH;hDsL*8vQ#r9*%_Heca$_4vKMJAjW@+B_Y#^IycAhy zEX80jSyR!-5}Fapnyh0P;r?|0i~H%E&-t9s^PKa2&h!1A?V+u;xwIrg5&$4=aSm+{ zfbhkwCJuu?K*VXFzX_`Gn3oMM3%Rv0m^ zkTU$_3F|lLFaV_fu|S`84DO%i{z+7JMu^SYXn*yu9Zj>or-T0^QvI3u!!9k}Cpmnv zx@h&z16P=_?8q03yI`ulXEkh|u{5*H3-dW3?-jn;=a%NCqcfJ${^hMTZ{hjo!aj! z;Uay@6LmNQ?~kKTE`iJ=MYyl&3dI^4GBS_C3{XMhK+i{>sV}?FEEPr>k;D6URqs&AW}Ys{S96b%146N7qY&$P^iaj%AkF<(N)U?N=|=qA zI`WL2*Y+!lm5e#1V|?79r=&1|ZWe_G{q??b!3P@N+(IW z+<5JDRrz>%(KDm$ix8{C`?^DtfEe@FrcW5OZ`2LR^|rPUO(dATH+S$1076rrcs#YG zB^VC_GVO3on2v1ivgcWq{F*$ruD4PXE^xD;;SbPF;)-KA=aTGn zL8b(*1g66}*3Lfd$JI$S76Gw22`7PRlQx2lbU4U*CvGo5WsmL4z6hlgU|y1(;v8U3 zkLkZ@ulks|FFOc)D2+%u^xcp)kuzcaud%?OrNGvh6X}QWmyPdOV=Gavd{#_oL9T3$ zG#1$>V!BNP3)gKf3T^XW95QjKS7fzMvglXVhOi#N=jbixg`4A)az&bn;;ZYUEJZKZ zj8)#`B;|qvNS{FDR4^P>CA&u^ zemQI-NU^l-^CefZo_8fuAM@0l3Ii{ApD;hxH*V(Lf1752C{Ev4yn1(ey?1WZT(xCs zX~bbFv!~ZNprJcem8?8S-V8dmKG8BXgHkx$2<13BkMl5;1;K0)EH%^CiLo-j!Cm<_ zk+`zBZpk6f>gl^*`>WswC3bq*mlh7Ic0U4PEhb!?3~-!h3E zr__+#r<=sV(Nl!y3W>SqR@&=o^sFyqlLIr&Cbg@i!rJv8_zqXJs=HOVJlC?vXs4?W zeht(s3-^pi3(9k(ogwaxJ^Tk0!Aic{9MEirHDyOmrUjV)PDOEuA(4_(gAXeBWLa5kIg7{ml;p^KVSX2b~prM^d)C* zyvsR@7-uI~DIc@B%1Je{ftNxEqD4Kf(X3^pM=@^TdvLVuA*B8saF6(U7_kA}Y)&>NL#y%L~BqJ-lEq+Y2 zy(}nUuCixWMn}c`zV&za7xz9hZuR`wr3T8i2z#HFa{S;L354#6njQ4IIc&{F^Ciwi zjlL8v=zEg^-T2AZRZIt!e-{v}g$jx@{~eXHSZATd_H;xMyZyK!-b?uF0A36T#`3TF z0(eV$n5kmpRWFiPb;jLSyTSz{tP*c4e{R)U=8L#2lDISY&>7)0X4cX)(C{^ycCx~! znNoMxud7*BtYz9Lyk@!K^k*hnKRG2==c+BfwQS>kdRcMeu2OB9ur7)oV^t{>ksw4` zq=e%jWh@rgs{O{6-j{Sx12xAQS3D>9KEX7nIAfzL$KQ)P!b{C4-Q~-opi7S7A)z>8 z+*oFYdu0A_zT&k-ywK^5Bl%b{W&Li92rN#aIg{q>qAWWRcvn2sSk&!Per}SL7Q%k+z9n(rm zJ!D|x0vw+!kqS)t$xF)_Du*VAUG~B!Wkh2uJ-V0i1RA36lkw diff --git a/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalieeye.png b/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalieeye.png new file mode 100644 index 0000000000000000000000000000000000000000..cb90c895aa35dc6a05eb9f112144d03f6cbf2352 GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^8bBP#!VDyX{{9RHQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`4FY^ZT!FNxsHlOd6=UBHh8^$z|NjpZ!2|xx{1gn7<}C1tEM{QfI}E~% z$MaXD00obDx;TbdoPK-xAn#!X9tMZ-MgPw+NHZ`i9Ax-g@;}r|_CTAI%PPCa?45oR zM-Q^;9+8UeW9;>|obxoJ=1|A9#EolO^tKj=`X(iESM?P(#+p4lyg_igU%`ogPv$$? zC%rMyV0?c*c8~49*0dx07JZs~+35TKY?q#gtVGN1n=w~i`dPA-yAh0lGrJZzJo5SJIz9ZtRJg)A#Vj9!! cxZuJs-YyAW?&&=?IiN7`boFyt=akR{08M0q^8f$< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalieeyes.png b/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalieeyes.png new file mode 100644 index 0000000000000000000000000000000000000000..0aa12f90e90aa7d0a487b92e3bd7887045aa25a2 GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^8bBP#!VDyX{{9RHQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`4FY^ZT!FNxsHlOd)eQ}X9|;!!|NjSy-~m8*91iU}BEHJw>aHuMG2M;} aF8t!{lJMo8-eZ#k@};M%pUXO@geCwuPk_z< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalies.png b/src/main/resources/assets/pokecube_mobs/gen_3/entity/textures/glalies.png index 19831f26a1f6d80c41b8b67208b89b82d8dfda11..3ce4a9d4a9fe4ec72b6f0c722a7c7d2cdfe592a6 100644 GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^GC-`w!VDyX7}Ugp6k~CayA#8@b22Z19F}xPUq=Rp zjs4tz5?O(Kg8-ipR|8Y4*-KX50D>1UK7RNJ6vhwY*XG6pRd5z~L>4nJ@ErzW#^d=b zQh3(;WRIB>)4<@fW5o`h%5`1b4BC@?6wPCvFoLY`boFyt I=akR{0JHut!TBB>F{Q4m@LB?&en0-_+2Bs8K7IfFEkku0IH zQ9xo3*(MIjM&fJkySIv0HMeH0dbjGmAE!?5U2A{e`qsDh+2?fhbt7$BstZ&A09sug z%^Ls^!%i*=GQv!g>+1=^jq zTzBumU2orU0U%%uY3gQXiepj2Pi?E~M;W(>$a4Mn1>=E;c+n>RHeJba1xka07m!|EPLId9ip4Sv5f3 zLP3+PBV{6kpea!2Wc)q6tG#o2PE<9FitjF9pr~@@_C4e!0=uCQ$W@*e@+LqO@P(QJ zv>2whh+m96re9J|y+wq0Le%0He@&kPaSo^k#j585RV^X}^0j~|$RY*yy-tp^;JOH~ z7ksqv1t5^Ssli0RI+2^1C@UUtopp)Q1n!EUc);Qr6u`v6IamF5dGJjHi0fLq>VWbZ z(1K>5t^^b`K-?rM;tC)Q2KL>&yaC`zDmbULX$jf5TFS5}L{KWV5>m@24-K=X5b+_m zv=rsMjMinndQR4X*da|-v^6mGykwX({qI|S0A$586RO=h3_#PBqS3OkC^|clrDn2Y z9!JO7qxpfNyQ%<8`-NhTgvF{ZAQZ_EUPtfv*GS!Msk83mV_YlgRjWZ3Zp?D)?ujpIrLgwD;HF!{u4raj-1%;AYve|4pUfAH9O1}nTzqKuUR zUcWLU!@vnTe0o2lld0)cM+5)fv>OoDmoA*sPcz1UY(4(S#X_ooSW=|o%2KhP=NrQdU)$ozP@A&in#t()Sk1NT@Ik>fKMZ!86C zYQ!%0M;%h87(T8~QRhr}^y6i8ByK!2<1*Lb*i^blEFXDGt1e!#8%RDrc-o*Xkr-BK zqV$!fTB9~!?!ptTchsMq{Up-jShCVT-+O;S>ACFN#m`0V^kZ?#8eQTo-`U8e+V6;q zcDAWkToa~DaO$n#DW)mvyijgYOi~}c<1|p=Ps$VqZK0GU^;hR|;8fFr8NiIb>Ev@= z05lnSWOLewuuLIE$`+ zPRYBZFBjZd-SM}}zWdcNP9||0rF^y=?8Rw+Px(%=?N3AdlsUXB%I)&`bT)D}xAXpN zWv>l#&wq(I-(@B)C$ao`F_k_QZVnSd2|Z+v@1aW4OA<(87ZNioD9kOKDx@~wGVe8u zE3h>UDb+HUGMz1;{F+>3UWmNDY|3uxR-l+4S?HDzH&gj7)ao#r%&N_x%~<0%ldKB6 z*@jLoYNzv60m9s#v_((vhsm@HRP>KNd>~Z+`jDeOMyasit-OYmo|I+Pjjcpi74q5F zKD!xyMwE+}^HR1#pG}=xzcO=$Jy+VGR>I|$XJK+mGOS3a$fQVnxly)sH4mBF2(7o; z52I7-(i6NTsO=VqK7(8|9W|ZIqsn73R8rU}6)p74VSih%>EG;~xAr=-$rh1m0MDBW zY+T&C7$SCPcIdU2x1&u1Bdem}BO9kdvq3s!eBclcv99qA6Aha-RgD~nB!`sgC-Joy zNcND{3oZKRw>xjm^38g6dUa+CkO^=L=o>B>uBF{Dtj)cWt7xET(AD49|E_;HRVH0Y zVnlK=eKCC`9b036GvKB$Dj)U1MYnS9X0Fv5s=+(rro2@S%>1TJl~xI|gnzicq&|-^ zuhuBRs3>#Tt*v|m^$Ar_bH0538`*d%$_o|Z;O5BcR?|`1wwBPC5K0h+nSlw!U!?&Vh zqV*s5il!)wrn7fWb~n!H`R(}FOa~3_Ak(YTTUYbP%hqJqZm&g7yy=sEb0yPC%J*|y zx5n=#^B5KCH%a22*y2!Q4dXDk>P22LC$V_Tl9BS79REVR!#b<-59NDrW|e0la#NC1 zR(5@IEj8UWy~b_uOuGoI#v|Ti=i{Jb49G+96S+hVRZ$ps`B6E# zs`fmqR*hLL?s3WE`Hv;s?%gXdOStiiuhH@7+jJ4vL%$DyCU;nHh-nL@5sZk8uzac# zdp8Pp0V9zj z87mPglzQ%WvzwPkgvcx1Tr6Fi`=fj0lZ!I1_OJF;^^Cui%UFMNyvo$dH2n&d^Hkqb zgafwFSnMHR3GoRWrhOSuy0pGnA0mka5wfWlCviqd<_MXPE8Bp2r`ni9DC7 z&8g-iLY5~+R&9)7VpiB{hrOprc4g-1XQk)HSyPxFeY-pnFwY(d?`ck*NPJ&V)L!d6 z;5z7vTbL5bw5CfgOj$^w^QIjgdrynCc)z;y13E62(tmlpJ{+Y{o81ig(BP8y3Ei)# zV)mQaw%MMU?AqXDwZq7+H)f4JxZ#KN%FwuV1O8C?Q`5LPk-6cJ>yXR7?tT?sr8K$_ zx0}50Wm970<+IvFGDvbr&P#_Hsr@>{F{osABX0QWvNm1UrKTg~y1xjmEUo#AjLsR} zyPAP>I6Ng5&q=E=_TYJN@ih6DOAk2QIK({E(>Bwz(oNI$tsSlFjQf-^!%I^^2ioJ8 z=rg1tR)Kn3W}j}4;U0fUaN8Vsj!Z&^go^&0upfVi3SM+VV?F5M>var%(}U3Cm_@|~ zMf9!B4}P1KMyuf(qPC9$Ami$ zfcxSAEZGB~@EQPC_$#{(Edc0abv4z@0>)M*CGLz{aJEc0KPHBL$+4j;uVHVzHC|BR z?JmNnA*B$>qN61SebqlYw&7iWC-Tl{5E*fM(`w}?5fw}=^4&;>J|+io#`$)g^AIha z%T0kR&jk1-kCeF(yfJZ-92(7#!MH|P%d#J$(<#V@1Hmzza7feF;|TzJ zd6kX`AX?sycP=lpS2Q&-`Y3FD&D{X1_C(-)zakwGwY04rHtM6jc%c0?2%GkfXT=gH zJrMP`=iuZ-{tRwzUZ|%86vZ*^LumADfp(3ig?4cX^5L5wc)YbdC%9GDqBr9qt)Liw zpXnA)Q3o1{)>keKxLLNg0kUL~b=^v0r93=Z*$D%NZxl!YOq#W}io(q`JvP>e_rpxF z>EtYtYKicdme$qv^^u@PGs2j_*4HO#$H%&p1cX6Z4U87~iKN+R1oAcsIi1AW`l^_M z{~MM*D3O>ksIQHw>>@$vUxKwws}*#)!`+9N)r}a5xynD>IjK5l#{U}RvhP1AsoG}G_Sa;66NI%0qzEFtQQQC#FD0%igl~aL!sb0xCw!z zO`muv9QGFC7%G6o07p&xqtZh22MHSR3P z6TVrBZaC*e7Y(!3_!T=ts$c{$E93b~0RjcvJ6?#3v$I>WduwOY=%M8j*6DOr7JP;@ zLn#1Pxe=iQ9n;hC>pbAI5VC>nYIGqI*#+m6ujTB$4AAqx$8KR!Nsgc+vtVMWDh=+rx4B>^DxQn?-L0XYu`q)CR@S9Q zJo{sHD@=leyZ#Xe^cYt}-Hgg5r1_?AYpU>GlLZLdiNRA5F;AfHz9-t4-0G;dP8h%j z1zd~HZx}5o?hVz(kD1hUHV^bN~H7}xdzFX zzMHg~J1Z0#%7Q)qL-+ywfKgE~Zor0oXuWK{b7<{_%FO^$gUTP zA^}sIErm=}_ai#Gj6>s6nh!5*?D$vIPYygU?)xydrv32Hrr}_9WOw(|dUZpx3r9Gv zti-)ysIgI7Dvl9+e$}G)*ug?NF%S)jwS~mlma(ok;X^ew9h{NTMNt9xMtt_jat9`6 zvAQwSPxeeK+tiChgVMi!~utAq2_U=;$4Nt0p|H+a6KGS3hNl*9p#iukHK%Zc* zks|od3`2>td(!c>-Fv;P8=Ie4-DcbuLf0v&!?9 z3)DgrL!5nISb_*hv%w5|6?T&7-ubaXGgO!#U{=TPNGtT%luNIBGFTEefF$n~${d_{ z4|Pn8H+HC-$r60VwA}pqA~w%Bg#THogr17>`j0KxkN(VF&EyZnh*;8LNpC;M@`Y?G zIYm+57lRExLtiCyuq{CrY|PMMh>!W=YA`^^lX#BGDTvkuDDuqg^|LRkU)^{7Bc{vT z+WQ9$c#lmIXyuvlL*<~yQG8`M0>Ec|DkY(7eR5y26x)FLb~NTkQ`za~!2lGPV9}_F z@7JQE_=?HG2WGO3m0!du|CA>D7I-_<-nh$hpQZ=W{9T@Pk`utL+siOh=}PAuC&oV+ zdhh2hQ-Os}uGD@4gu2Sva#C*VOl6FW$aw^k4Ad(bVD4LvV;?H|POQS4UPK=6?)O#n ztkmF~u1jlSl-rqspLBUz1IA}#)nU_V@#CT5#=xV)edp(wwDV>gfA0R#Wdix|NYKJ! z!MZamfO}v8{v)IMO>wtSFjcvGy@GcuEij`g#>pK8_On~M&_t4N{C$AyV$-m zG??BzeSg?v8+X1c&^7B-cN$$$pxs&US=HW#Pu#UJ+O7Y62AXLeOC_k3kjM{zDnMCJ z*bS*t5U2?%pWSw`M9Xe|+qTkh#Ik}MQ6pKN7Gyd#(V!@mT&QW3dOi(jugl|%>BBT}U%DLO)YD?F#;!c)|P@_PQVVf-kOawO34EXcQ8-`(8_uu>ej z$@3P+1?yB^4(*5Hc{1?JH*Ffn>J5&6@0zW669lH#S{#3pvVgDa&oltIUY2=`Apu`| zX;=u)T4KO(^8XVx0AXhc?gE69;~&G5bCg2(AH!b)oviuGNT)#m%>F0o{v7mAivQyD zzXSSL_J0yT#pzVKQ=orkC&+d(`vHMLGpKrR~Y=UxH34a - + diff --git a/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/reshiram.x3d b/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/reshiram.x3d index 7fac1890d7..9978efb47a 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/reshiram.x3d +++ b/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/reshiram.x3d @@ -1543,7 +1543,7 @@ > - + @@ -3475,7 +3475,7 @@ > - + @@ -3502,7 +3502,7 @@ > - + @@ -4094,7 +4094,7 @@ > - + @@ -5047,7 +5047,7 @@ > - + @@ -5074,7 +5074,7 @@ > - + diff --git a/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/virizion.x3d b/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/virizion.x3d index 2117450568..ad0e3e2ba8 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/virizion.x3d +++ b/src/main/resources/assets/pokecube_mobs/gen_5/entity/models/virizion.x3d @@ -58,11 +58,11 @@ - - - + + + diff --git a/src/main/resources/assets/pokecube_mobs/gen_5/entity/textures/reshirams.png b/src/main/resources/assets/pokecube_mobs/gen_5/entity/textures/reshirams.png index 0a4bc3861d66090c6270e554f74ce7080bc5efd8..611d3a4ee240cb1d701b2b377f9cd0ee26c7589b 100644 GIT binary patch delta 322 zcmcb>@|J0W1SbnK0|Ud{+q&@+6&30Y0(?STfqYR>(dE7#rx^JE8#>-A-ut$8+SQ{; zN4LIzf8p7$AFscE|Nj5~f1ol5__f+I1jynn@Q5sCVBk9l!i+m6X1@gr9`kf@4DmSr z_R3zt!wNjC35CzQxYkY(ox`|ebJz*4NJZ_6){-kxirOhFI_xE_>#v0DIraTxgL7-6 z>F%^g95tDCvpSVOEUU~?>pRf?Z0$@7ru}nG{x4M)V0dG%WOduIWV+D?L6!PPO)7UB zZ#hU>gs7~latijF=32bq^S0(E+^7DjzOsG9Cb{&M!p*MK{qZSB(`~*jZ_YjROiOdo z>4?>@wOn0h%PU@8@=3$xgfE}oq6y1{)+U6oFic*f#Qt(gVR7>((Z$R=+kUdk{i&6g Sj5_)ZfUTf$^!Qi(^QJ^V?gF zeuo@Hj(xl)@%Wsm_y-oJM~o$jcV4LOm{k5j+gSoj+@Bg|=OGejD@9>G^t`#!6Y>Om1k`%fcHDHVtpT5^;zx&nwtL&SY zo868ha0w_Q>r3O)-={af)_=8p_jQ9$2UXn+1&%t1FbDFuKpBhqbyokp@>RU_qlDbt zf=+}4M8%aC%%`)Id)!a{mEXHJmwEj<^@lI_oy|@xu`7L$QY5i6>TNyKdC6J4AyTXS zBxB;6cY1KHS;qhH<}>Hh=M8R28tn*AIKx(beAgXz)wpf%AEi|OuDQRi z__^v`i<8Pte6_-1Dwn94*|h3_0 Y;r(n2x^B(50Zb7Lp00i_>zopr0AC3DNdN!< diff --git a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/amaura.xml b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/amaura.xml index cd9780be1b..ad4b04023a 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/amaura.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/amaura.xml @@ -8,7 +8,7 @@ - + diff --git a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/aurorus.xml b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/aurorus.xml index eba362f67a..c595564e5c 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/aurorus.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/aurorus.xml @@ -8,7 +8,7 @@ - + diff --git a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/litleo.x3d b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/litleo.x3d index 9c08777a28..f1e3932e82 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/litleo.x3d +++ b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/litleo.x3d @@ -192,11 +192,11 @@ - - - + + + diff --git a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/yveltal.x3d b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/yveltal.x3d index 67682f7b4a..bcd7b34a82 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/yveltal.x3d +++ b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/yveltal.x3d @@ -2680,6 +2680,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_10.xml b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_10.xml index ed05bcbef6..b111aa08ca 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_10.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_10.xml @@ -3,6 +3,7 @@ + diff --git a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_100.xml b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_100.xml index 03c5af82ad..8905520d6c 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_100.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_6/entity/models/zygarde_100.xml @@ -24,7 +24,7 @@ - + diff --git a/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/morelull.xml b/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/morelull.xml index 180b1b90f3..d760087a9d 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/morelull.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/morelull.xml @@ -7,7 +7,7 @@ - + diff --git a/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/solgaleo_dusk.xml b/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/solgaleo_dusk.xml index f532453f3a..9127458e2e 100644 --- a/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/solgaleo_dusk.xml +++ b/src/main/resources/assets/pokecube_mobs/gen_7/entity/models/solgaleo_dusk.xml @@ -5,7 +5,7 @@ - + From f5a3b515622a007f67d3819fd32f685bda7b278e Mon Sep 17 00:00:00 2001 From: Thutmose Date: Wed, 20 May 2020 19:32:43 -0400 Subject: [PATCH 06/27] Update ITerrainProvider.java ensure this is in bounds --- src/main/java/thut/api/terrain/ITerrainProvider.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/thut/api/terrain/ITerrainProvider.java b/src/main/java/thut/api/terrain/ITerrainProvider.java index e51d5ddb0d..a06ae79a69 100644 --- a/src/main/java/thut/api/terrain/ITerrainProvider.java +++ b/src/main/java/thut/api/terrain/ITerrainProvider.java @@ -121,15 +121,17 @@ default TerrainSegment getTerrain(final IWorld world, final BlockPos p) { // Convert the pos to a chunk pos final ChunkPos temp = new ChunkPos(p); + int y = p.getY() >> 4; + if (y < 0) y = 0; + if (y > 15) y = 15; // Include the value for y - final BlockPos pos = new BlockPos(temp.x, p.getY() / 16, temp.z); + final BlockPos pos = new BlockPos(temp.x, y, temp.z); final DimensionType dim = world.getDimension().getType(); final IChunk chunk = ITerrainProvider.getChunk(dim, temp); final boolean real = chunk != null && chunk instanceof ICapabilityProvider; // This means it occurs during worldgen? if (!real) { - final GlobalChunkPos wpos = new GlobalChunkPos(dim, temp); TerrainCache segs = ITerrainProvider.pendingCache.get(wpos); if (segs == null) @@ -137,7 +139,7 @@ default TerrainSegment getTerrain(final IWorld world, final BlockPos p) segs = new TerrainCache(temp, chunk); ITerrainProvider.pendingCache.put(wpos, segs); } - return segs.get(pos.getY()); + return segs.get(y); } final CapabilityTerrain.ITerrainProvider provider = ((ICapabilityProvider) chunk).getCapability( ThutCaps.TERRAIN_CAP).orElse(null); From 353dcf0b39ea6ddfeb8c5e7eb2019b2236c9fe81 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Thu, 21 May 2020 16:36:51 -0400 Subject: [PATCH 07/27] more strict controls over what can breed --- .../java/pokecube/core/events/EggEvent.java | 33 ++++++++++++++++--- .../capabilities/impl/PokemobSexed.java | 6 +++- .../conditions/LegendaryConditions.java | 2 ++ .../legends/handlers/GeneProtector.java | 23 +++++++++++-- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/main/java/pokecube/core/events/EggEvent.java b/src/main/java/pokecube/core/events/EggEvent.java index 9c59d53835..76349c7e24 100644 --- a/src/main/java/pokecube/core/events/EggEvent.java +++ b/src/main/java/pokecube/core/events/EggEvent.java @@ -1,15 +1,38 @@ package pokecube.core.events; import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.eventbus.api.Cancelable; import net.minecraftforge.eventbus.api.Event; import pokecube.core.items.pokemobeggs.EntityPokemobEgg; public class EggEvent extends Event { + @Cancelable + /** + * This is called when two pokemobs try to decide if they can breed, if + * cancelled, they are not compatible. + */ + public static class CanBreed extends LivingEvent + { + private final LivingEntity other; + + public CanBreed(final LivingEntity first, final LivingEntity other) + { + super(first); + this.other = other; + } + + public LivingEntity getOther() + { + return this.other; + } + } + public static class Hatch extends EggEvent { - public Hatch(Entity egg) + public Hatch(final Entity egg) { super((EntityPokemobEgg) egg); } @@ -22,7 +45,7 @@ public Hatch(Entity egg) */ public static class Lay extends EggEvent { - public Lay(Entity egg) + public Lay(final Entity egg) { super((EntityPokemobEgg) egg); } @@ -34,7 +57,7 @@ public Lay(Entity egg) */ public static class Place extends EggEvent { - public Place(Entity egg) + public Place(final Entity egg) { super((EntityPokemobEgg) egg); } @@ -47,7 +70,7 @@ public Place(Entity egg) */ public static class PreHatch extends EggEvent { - public PreHatch(Entity egg) + public PreHatch(final Entity egg) { super((EntityPokemobEgg) egg); } @@ -57,7 +80,7 @@ public PreHatch(Entity egg) public final EntityPokemobEgg egg; - private EggEvent(EntityPokemobEgg egg) + private EggEvent(final EntityPokemobEgg egg) { this.placer = egg.getEggOwner(); this.egg = egg; diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java index 7cf4f90ba1..6d77711c1e 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java @@ -51,6 +51,10 @@ public boolean canMate(final AgeableEntity otherAnimal) if (otherMob.getOwnerId() != null && this.getOwnerId() == null) return false; if (this.getOwnerId() != null && otherMob.getOwnerId() == null) return false; + if (PokecubeCore.POKEMOB_BUS.post(new EggEvent.CanBreed(this.getEntity(), otherAnimal))) return false; + + if (!otherMob.getPokedexEntry().breeds || !this.getPokedexEntry().breeds) return false; + PokedexEntry thisEntry = this.getPokedexEntry(); PokedexEntry thatEntry = otherMob.getPokedexEntry(); @@ -60,7 +64,7 @@ public boolean canMate(final AgeableEntity otherAnimal) // Check if pokedex entries state they can breed, and then if so, // ensure sexe is different. final boolean neutral = this.getSexe() == IPokemob.NOSEXE || otherMob.getSexe() == IPokemob.NOSEXE; - if (thisEntry.areRelated(thatEntry) || thatEntry.areRelated(thisEntry) && (neutral || otherMob + if ((thisEntry.areRelated(thatEntry) || thatEntry.areRelated(thisEntry)) && (neutral || otherMob .getSexe() != this.getSexe())) return true; // Otherwise check for transform. diff --git a/src/main/java/pokecube/legends/conditions/LegendaryConditions.java b/src/main/java/pokecube/legends/conditions/LegendaryConditions.java index d597b41355..2de7d809ad 100644 --- a/src/main/java/pokecube/legends/conditions/LegendaryConditions.java +++ b/src/main/java/pokecube/legends/conditions/LegendaryConditions.java @@ -6,6 +6,7 @@ import net.minecraft.block.Blocks; import net.minecraftforge.common.MinecraftForge; +import pokecube.core.PokecubeCore; import pokecube.core.database.Pokedex; import pokecube.core.database.PokedexEntry; import pokecube.core.database.stats.ISpecialCaptureCondition; @@ -63,6 +64,7 @@ public void init() // Register the thng that prevents genetic modification of protected // mobs MinecraftForge.EVENT_BUS.register(new GeneProtector()); + PokecubeCore.POKEMOB_BUS.register(new GeneProtector()); MinecraftForge.EVENT_BUS.register(LegendarySpawn.class); List> foundClasses; diff --git a/src/main/java/pokecube/legends/handlers/GeneProtector.java b/src/main/java/pokecube/legends/handlers/GeneProtector.java index e665a8feba..c23111b8c1 100644 --- a/src/main/java/pokecube/legends/handlers/GeneProtector.java +++ b/src/main/java/pokecube/legends/handlers/GeneProtector.java @@ -8,14 +8,15 @@ import pokecube.core.entity.pokemobs.genetics.GeneticsManager; import pokecube.core.entity.pokemobs.genetics.genes.SpeciesGene; import pokecube.core.entity.pokemobs.genetics.genes.SpeciesGene.SpeciesInfo; +import pokecube.core.events.EggEvent.CanBreed; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; import thut.api.entity.genetics.Alleles; public class GeneProtector { - public boolean invalidGene(final SpeciesGene gene) + public boolean invalidEntry(final PokedexEntry entry) { - final SpeciesInfo info = gene.getValue(); - final PokedexEntry entry = info.entry; // No cloning legends. if (entry.isLegendary()) return true; // No cloning things with requirements @@ -26,6 +27,13 @@ public boolean invalidGene(final SpeciesGene gene) return false; } + public boolean invalidGene(final SpeciesGene gene) + { + final SpeciesInfo info = gene.getValue(); + final PokedexEntry entry = info.entry; + return this.invalidEntry(entry); + } + @SubscribeEvent public void GeneEditEvent(final GeneEditEvent evt) { @@ -36,4 +44,13 @@ public void GeneEditEvent(final GeneEditEvent evt) if (this.invalidGene(gene)) evt.resultGenes.getAlleles().remove(GeneticsManager.SPECIESGENE); } } + + @SubscribeEvent + public void CanBreedEvent(final CanBreed evt) + { + final IPokemob mobA = CapabilityPokemob.getPokemobFor(evt.getEntity()); + final IPokemob mobB = CapabilityPokemob.getPokemobFor(evt.getOther()); + if (mobA != null && this.invalidEntry(mobA.getPokedexEntry())) evt.setCanceled(true); + if (mobB != null && this.invalidEntry(mobB.getPokedexEntry())) evt.setCanceled(true); + } } \ No newline at end of file From 6f7d0277e3baccbae57894bdff90a033712e1b75 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 00:31:50 -0400 Subject: [PATCH 08/27] fixes some issues in hunger AI this should partially address #388 --- .../java/pokecube/core/ai/tasks/TaskBase.java | 13 +++++++++---- .../pokecube/core/ai/tasks/idle/AIHungry.java | 15 +++++++-------- .../core/ai/tasks/idle/hunger/EatWater.java | 6 +++--- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/main/java/pokecube/core/ai/tasks/TaskBase.java b/src/main/java/pokecube/core/ai/tasks/TaskBase.java index c5a76dd3cd..82542713d9 100644 --- a/src/main/java/pokecube/core/ai/tasks/TaskBase.java +++ b/src/main/java/pokecube/core/ai/tasks/TaskBase.java @@ -155,18 +155,23 @@ protected void setWalkTo(final Vector3 pos, final double speed, final int dist) protected void setWalkTo(final Vec3d pos, final double speed, final int dist) { - this.entity.getBrain().setMemory(MemoryModules.WALK_TARGET, new WalkTarget(pos, (float) speed, dist)); + this.setWalkTo(new WalkTarget(pos, (float) speed, dist)); } protected void setWalkTo(final BlockPos pos, final double speed, final int dist) { - this.entity.getBrain().setMemory(MemoryModules.WALK_TARGET, new WalkTarget(pos, (float) speed, dist)); + this.setWalkTo(new WalkTarget(pos, (float) speed, dist)); } protected void setWalkTo(final Entity mobIn, final double speed, final int dist) { - this.entity.getBrain().setMemory(MemoryModules.WALK_TARGET, new WalkTarget(new EntityPosWrapper(mobIn), - (float) speed, dist)); + this.setWalkTo(new WalkTarget(new EntityPosWrapper(mobIn), (float) speed, dist)); + } + + protected void setWalkTo(final WalkTarget target) + { + this.pokemob.setLogicState(LogicStates.SITTING, false); + this.entity.getBrain().setMemory(MemoryModules.WALK_TARGET, target); } @Override diff --git a/src/main/java/pokecube/core/ai/tasks/idle/AIHungry.java b/src/main/java/pokecube/core/ai/tasks/idle/AIHungry.java index 0651e56fc0..9a2ed3641a 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/AIHungry.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/AIHungry.java @@ -347,7 +347,8 @@ public boolean shouldRun() // Apply cooldowns and increment hunger. this.pokemob.setHungerCooldown(this.pokemob.getHungerCooldown() - hungerTicks); - this.pokemob.setHungerTime(this.pokemob.getHungerTime() + hungerTicks); + if (!this.hitThreshold(AIHungry.HUNTTHRESHOLD)) this.pokemob.setHungerTime(this.pokemob.getHungerTime() + + hungerTicks); this.calculateHunger(); @@ -412,14 +413,12 @@ public void tick() if (diff < PokecubeCore.getConfig().pokemobLifeSpan) tameCheck = false; } // If they are allowed to, find the berries. - if (tameCheck) - { - // Only run this if we are getting close to hurt damage, mostly - // to allow trying other food sources first. - if (this.hitThreshold(AIHungry.BERRYGEN)) new GenBerries(this.pokemob).run(this.world); - } + // Only run this if we are getting close to hurt damage, mostly + // to allow trying other food sources first. + if (tameCheck && this.hitThreshold(AIHungry.BERRYGEN)) new GenBerries(this.pokemob).run(this.world); + // Otherwise take damage. - else if (this.hitThreshold(AIHungry.DAMAGE)) + if (this.hitThreshold(AIHungry.DAMAGE)) { final float ratio = (AIHungry.DAMAGE - this.hungerValue) / AIHungry.DAMAGE; final boolean dead = this.pokemob.getMaxHealth() * ratio > this.pokemob.getHealth() || this diff --git a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatWater.java b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatWater.java index f57aff2495..15916b687e 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatWater.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatWater.java @@ -10,13 +10,12 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.sensors.NearBlocks.NearBlock; import pokecube.core.interfaces.IPokemob; -import thut.api.item.ItemList; public class EatWater extends EatBlockBase { public static final ResourceLocation FOODTAG = new ResourceLocation(PokecubeCore.MODID, "pokemob_redstone_food"); - private static final Predicate checker = (b2) -> ItemList.is(EatWater.FOODTAG, b2); + private static final Predicate checker = (b2) -> b2.getFluidState().getFluid() instanceof WaterFluid; @Override public EatResult eat(final IPokemob pokemob, final NearBlock block) @@ -32,6 +31,7 @@ public EatResult eat(final IPokemob pokemob, final NearBlock block) final ServerWorld world = (ServerWorld) entity.getEntityWorld(); final BlockState current = world.getBlockState(block.getPos()); + if (!EatWater.checker.test(current)) return EatResult.NOEAT; pokemob.setHungerTime(pokemob.getHungerTime() - PokecubeCore.getConfig().pokemobLifeSpan / 4); @@ -42,7 +42,7 @@ public EatResult eat(final IPokemob pokemob, final NearBlock block) @Override public boolean isValid(final NearBlock block) { - return block.getState().getFluidState().getFluid() instanceof WaterFluid; + return EatWater.checker.test(block.getState()); } } \ No newline at end of file From 784fd5680766d1110d103350989bb317746f6a2a Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 00:46:59 -0400 Subject: [PATCH 09/27] Update PokemobSexed.java some more re-organizations of valid mating checks --- .../capabilities/impl/PokemobSexed.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java index 6d77711c1e..e21b32f30b 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java @@ -13,6 +13,7 @@ import net.minecraftforge.fml.LogicalSidedProvider; import pokecube.core.PokecubeCore; import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.idle.AIHungry; import pokecube.core.database.PokedexEntry; import pokecube.core.events.EggEvent; import pokecube.core.handlers.playerdata.advancements.triggers.Triggers; @@ -37,23 +38,20 @@ public boolean canMate(final AgeableEntity otherAnimal) if (otherAnimal == null || !otherAnimal.isAlive()) return false; if (otherAnimal == this.getEntity()) return false; // Not allowed to mate! - if (!this.isRoutineEnabled(AIRoutine.MATE)) return false; + if (!this.canBreed()) return false; // Too injured, no mate! if (otherAnimal.getHealth() < otherAnimal.getMaxHealth() / 2) return false; final IPokemob otherMob = CapabilityPokemob.getPokemobFor(otherAnimal); if (otherMob != null) { - // Not allowed to mate! - if (!otherMob.isRoutineEnabled(AIRoutine.MATE)) return false; - // Don't let tame and wild breed, prevents exploits with dittos if (otherMob.getOwnerId() != null && this.getOwnerId() == null) return false; if (this.getOwnerId() != null && otherMob.getOwnerId() == null) return false; - if (PokecubeCore.POKEMOB_BUS.post(new EggEvent.CanBreed(this.getEntity(), otherAnimal))) return false; + if (!otherMob.canBreed()) return false; - if (!otherMob.getPokedexEntry().breeds || !this.getPokedexEntry().breeds) return false; + if (PokecubeCore.POKEMOB_BUS.post(new EggEvent.CanBreed(this.getEntity(), otherAnimal))) return false; PokedexEntry thisEntry = this.getPokedexEntry(); PokedexEntry thatEntry = otherMob.getPokedexEntry(); @@ -207,6 +205,12 @@ public ServerPlayerEntity getCause() @Override public boolean canBreed() { + if (!this.isRoutineEnabled(AIRoutine.MATE)) return false; + PokedexEntry thisEntry = this.getPokedexEntry(); + if (thisEntry.isMega) thisEntry = this.getMegaBase(); + if (!thisEntry.breeds) return false; + final float hunger = AIHungry.calculateHunger(this); + if (AIHungry.hitThreshold(hunger, AIHungry.MATERESET)) return false; return this.loveTimer >= 0; } From a3cfd03813550f0df368ebdb5510f83ecf9599d0 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 05:31:44 -0400 Subject: [PATCH 10/27] another pass at re-organizing AI stuff renames the tasks to a bit more appropriate names (the majoirty of file changes are from that) Fixes some issues with target selction, should address #392 Fixes some issues in breeding, might address #394 but needs testing fixes some hunger AI issues, should address #388 Also made some adjustments to spawn location determination, might help with #393 bit meeds testing Fixes issue with arenatrap/swarm/illuminate while fixing the AFA AFA now functions again Pokemob Commad block now uses same coordinate system as the other things that use locations, so can be more easily set via location linker --- src/main/java/pokecube/adventures/Config.java | 3 + .../java/pokecube/adventures/PokecubeAdv.java | 2 + .../adventures/ai/tasks/AIBattle.java | 6 +- .../adventures/ai/tasks/AITrainerAgro.java | 6 +- .../adventures/blocks/afa/AfaContainer.java | 61 ++++-- .../adventures/blocks/afa/AfaTile.java | 184 ++++++++++++---- .../blocks/commander/CommanderTile.java | 6 +- .../adventures/client/gui/blocks/AFA.java | 93 ++++++++ .../client/gui/blocks/Commander.java | 7 + .../adventures/network/PacketAFA.java | 54 +++++ .../adventures/proxy/ClientProxy.java | 3 + .../adventures/proxy/CommonProxy.java | 8 + .../pokecube/core/ai/brain/MemoryModules.java | 2 + .../java/pokecube/core/ai/brain/Sensors.java | 10 +- ...ossibleMates.java => InterestingMobs.java} | 4 +- .../core/ai/brain/sensors/NearBlocks.java | 1 + .../core/ai/logic/LogicMiscUpdate.java | 4 + .../java/pokecube/core/ai/tasks/Tasks.java | 113 +++++----- .../{AICombatMovement.java => CicleTask.java} | 4 +- .../{FightTask.java => CombatTask.java} | 12 +- .../combat/{AIDodge.java => DodgeTask.java} | 4 +- ...AIFindTarget.java => FindTargetsTask.java} | 150 +++---------- .../combat/{AILeap.java => LeapTask.java} | 8 +- .../ai/tasks/combat/ManageTargetTask.java | 188 ++++++++++++++++ ...{AISelectMove.java => SelectMoveTask.java} | 7 +- .../{AIAttack.java => UseAttacksTask.java} | 65 +----- .../idle/{IdleTask.java => BaseIdleTask.java} | 12 +- .../ai/tasks/idle/ForgetHuntedByTask.java | 39 ++++ .../{AIGuardEgg.java => GuardEggTask.java} | 14 +- .../pokecube/core/ai/tasks/idle/HerdTask.java | 44 ++++ .../idle/{AIHungry.java => HungerTask.java} | 63 +++--- .../idle/{AIIdle.java => IdleWalkTask.java} | 18 +- .../tasks/idle/{AIMate.java => MateTask.java} | 50 ++++- .../ai/tasks/idle/hunger/EatFromChest.java | 4 +- .../core/ai/tasks/idle/hunger/EatPlant.java | 2 +- .../ai/tasks/idle/hunger/EatRedstone.java | 2 +- .../core/ai/tasks/idle/hunger/EatRock.java | 2 +- .../{AIGatherStuff.java => GatherTask.java} | 20 +- .../{AIStoreStuff.java => StoreTask.java} | 22 +- .../{AIUseMove.java => UseMoveTask.java} | 8 +- .../client/gui/pokemob/GuiPokemobStorage.java | 6 +- .../pokecube/core/database/PokedexEntry.java | 4 +- .../java/pokecube/core/handlers/Config.java | 8 +- .../handlers/events/PokemobEventsHandler.java | 6 +- .../core/handlers/events/SpawnHandler.java | 205 ++++++++++-------- .../pokecube/core/interfaces/IPokemob.java | 1 + .../capabilities/impl/PokemobAI.java | 1 + .../capabilities/impl/PokemobMoves.java | 4 +- .../capabilities/impl/PokemobOwned.java | 4 +- .../capabilities/impl/PokemobSexed.java | 12 +- .../commandhandlers/AttackEntityHandler.java | 4 +- .../AttackLocationHandler.java | 6 +- .../commandhandlers/MoveToHandler.java | 10 +- .../items/pokecubes/EntityPokecubeBase.java | 4 +- .../pokecubes/helper/CaptureManager.java | 4 +- .../items/pokemobeggs/EntityPokemobEgg.java | 4 +- .../java/pokecube/core/moves/MovesUtils.java | 4 +- .../core/moves/templates/Move_Basic.java | 4 +- .../network/pokemobs/PacketPokemobGui.java | 8 +- .../pokecube/mobs/abilities/a/ArenaTrap.java | 27 ++- .../mobs/abilities/eventwatchers/Damp.java | 17 +- .../mobs/abilities/h/HoneyGather.java | 7 +- .../pokecube/mobs/abilities/i/Illuminate.java | 27 ++- .../java/pokecube/mobs/abilities/s/Swarm.java | 37 +++- .../mobs/moves/attacks/special/Teleport.java | 4 +- .../mobs/moves/attacks/special/Transform.java | 4 +- .../mobs/moves/attacks/special/Whirlwind.java | 4 +- .../mobs/moves/world/ActionTeleport.java | 4 +- src/main/java/thut/api/OwnableCaps.java | 19 +- .../thut/core/common/network/TileUpdate.java | 2 +- .../pokecube_adventures/lang/en_us.json | 8 +- 71 files changed, 1160 insertions(+), 604 deletions(-) create mode 100644 src/main/java/pokecube/adventures/client/gui/blocks/AFA.java create mode 100644 src/main/java/pokecube/adventures/network/PacketAFA.java rename src/main/java/pokecube/core/ai/brain/sensors/{PossibleMates.java => InterestingMobs.java} (92%) rename src/main/java/pokecube/core/ai/tasks/combat/{AICombatMovement.java => CicleTask.java} (96%) rename src/main/java/pokecube/core/ai/tasks/combat/{FightTask.java => CombatTask.java} (57%) rename src/main/java/pokecube/core/ai/tasks/combat/{AIDodge.java => DodgeTask.java} (97%) rename src/main/java/pokecube/core/ai/tasks/combat/{AIFindTarget.java => FindTargetsTask.java} (79%) rename src/main/java/pokecube/core/ai/tasks/combat/{AILeap.java => LeapTask.java} (94%) create mode 100644 src/main/java/pokecube/core/ai/tasks/combat/ManageTargetTask.java rename src/main/java/pokecube/core/ai/tasks/combat/{AISelectMove.java => SelectMoveTask.java} (95%) rename src/main/java/pokecube/core/ai/tasks/combat/{AIAttack.java => UseAttacksTask.java} (84%) rename src/main/java/pokecube/core/ai/tasks/idle/{IdleTask.java => BaseIdleTask.java} (56%) create mode 100644 src/main/java/pokecube/core/ai/tasks/idle/ForgetHuntedByTask.java rename src/main/java/pokecube/core/ai/tasks/idle/{AIGuardEgg.java => GuardEggTask.java} (89%) create mode 100644 src/main/java/pokecube/core/ai/tasks/idle/HerdTask.java rename src/main/java/pokecube/core/ai/tasks/idle/{AIHungry.java => HungerTask.java} (88%) rename src/main/java/pokecube/core/ai/tasks/idle/{AIIdle.java => IdleWalkTask.java} (92%) rename src/main/java/pokecube/core/ai/tasks/idle/{AIMate.java => MateTask.java} (71%) rename src/main/java/pokecube/core/ai/tasks/utility/{AIGatherStuff.java => GatherTask.java} (94%) rename src/main/java/pokecube/core/ai/tasks/utility/{AIStoreStuff.java => StoreTask.java} (95%) rename src/main/java/pokecube/core/ai/tasks/utility/{AIUseMove.java => UseMoveTask.java} (96%) diff --git a/src/main/java/pokecube/adventures/Config.java b/src/main/java/pokecube/adventures/Config.java index cd96ef689c..fb1f1bb04c 100644 --- a/src/main/java/pokecube/adventures/Config.java +++ b/src/main/java/pokecube/adventures/Config.java @@ -128,6 +128,8 @@ public class Config extends ConfigData public String afaCostFunctionShiny = "(d^3)/10"; @Configure(category = Config.MACHINE) public int afaMaxEnergy = 3200; + @Configure(category = Config.MACHINE) + public int afaTickRate = 5; @Configure(category = Config.BAG, type = Type.SERVER) public boolean bagsHoldEverything = false; @@ -154,6 +156,7 @@ public void onUpdated() DaycareTile.initParser(this.dayCarePowerPerExp, this.dayCareExpFunction); AfaTile.initParser(this.afaCostFunction, this.afaCostFunctionShiny); this.dayCareTickRate = Math.max(1, this.dayCareTickRate); + this.afaTickRate = Math.max(1, this.afaTickRate); if (this.autoAddFossilDNA) for (final Entry fossil : ItemGenerator.fossils.entrySet()) { diff --git a/src/main/java/pokecube/adventures/PokecubeAdv.java b/src/main/java/pokecube/adventures/PokecubeAdv.java index 014f20a63c..ccd206bee1 100644 --- a/src/main/java/pokecube/adventures/PokecubeAdv.java +++ b/src/main/java/pokecube/adventures/PokecubeAdv.java @@ -27,6 +27,7 @@ import pokecube.adventures.advancements.Triggers; import pokecube.adventures.blocks.BlockEventHandler; import pokecube.adventures.blocks.afa.AfaBlock; +import pokecube.adventures.blocks.afa.AfaContainer; import pokecube.adventures.blocks.afa.AfaTile; import pokecube.adventures.blocks.commander.CommanderBlock; import pokecube.adventures.blocks.commander.CommanderTile; @@ -99,6 +100,7 @@ public static void registerContainers(final RegistryEvent.Register TYPE = new ContainerType<>(AfaContainer::new); - private static class InvWrapper implements IInventory + public static class InvWrapper implements IInventory { final IItemHandlerModifiable wrapped; final IOwnableTE ownable; + private List listeners; + public InvWrapper(final IItemHandlerModifiable wrapped, final IOwnableTE ownable) { this.wrapped = wrapped; this.ownable = ownable; } + /** + * Add a listener that will be notified when any item in this inventory + * is modified. + */ + public void addListener(final IInventoryChangedListener listener) + { + if (this.listeners == null) this.listeners = Lists.newArrayList(); + this.listeners.add(listener); + } + + /** + * removes the specified IInvBasic from receiving further change notices + */ + public void removeListener(final IInventoryChangedListener listener) + { + this.listeners.remove(listener); + } + @Override public void clear() { @@ -57,24 +82,29 @@ public ItemStack getStackInSlot(final int index) @Override public ItemStack decrStackSize(final int index, final int count) { + this.markDirty(); return this.wrapped.extractItem(index, count, false); } @Override public ItemStack removeStackFromSlot(final int index) { + this.markDirty(); return this.wrapped.extractItem(index, this.wrapped.getStackInSlot(index).getCount(), false); } @Override public void setInventorySlotContents(final int index, final ItemStack stack) { + this.markDirty(); this.wrapped.setStackInSlot(index, stack); } @Override public void markDirty() { + if (this.listeners != null) for (final IInventoryChangedListener iinventorychangedlistener : this.listeners) + iinventorychangedlistener.onInventoryChanged(this); } @Override @@ -85,8 +115,9 @@ public boolean isUsableByPlayer(final PlayerEntity player) } - IInventory inv; - IOwnableTE ownable; + IInventory inv; + IOwnableTE ownable; + public AfaTile tile; public AfaContainer(final int id, final PlayerInventory invIn) { @@ -102,28 +133,28 @@ public AfaContainer(final int id, final PlayerInventory invIn, final IWorldPosCa // Server side if (tile instanceof AfaTile) { - this.ownable = (IOwnableTE) tile.getCapability(ThutCaps.OWNABLE_CAP); - final IItemHandlerModifiable handler = (IItemHandlerModifiable) tile.getCapability( - CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - this.inv = new InvWrapper(handler, this.ownable); + this.ownable = (IOwnableTE) tile.getCapability(ThutCaps.OWNABLE_CAP).orElse(null); + this.tile = (AfaTile) tile; + this.inv = ((AfaTile) tile).inventory; } }); // Client side if (this.ownable == null) { - final AfaTile tile = new AfaTile(); - this.ownable = (IOwnableTE) tile.getCapability(ThutCaps.OWNABLE_CAP); - final IItemHandlerModifiable handler = (IItemHandlerModifiable) tile.getCapability( - CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - this.inv = new InvWrapper(handler, this.ownable); + this.tile = new AfaTile(); + this.ownable = (IOwnableTE) this.tile.getCapability(ThutCaps.OWNABLE_CAP).orElse(null); + this.inv = this.tile.inventory; + this.tile.setWorld(PokecubeCore.proxy.getWorld()); } - final int di = 17; - final int dj = 32; + final int di = 12; + final int dj = 36; final int i = 0; final int j = 0; this.addSlot(new TexturedSlot(this.inv, 0, dj - 21 + j * 18, di + i * 18, "pokecube:items/slot_cube")); this.bindPlayerInventory(invIn, -19); + + this.trackIntArray(this.tile.syncValues); } @Override diff --git a/src/main/java/pokecube/adventures/blocks/afa/AfaTile.java b/src/main/java/pokecube/adventures/blocks/afa/AfaTile.java index 0e5dbffbbc..6e0e8010cd 100644 --- a/src/main/java/pokecube/adventures/blocks/afa/AfaTile.java +++ b/src/main/java/pokecube/adventures/blocks/afa/AfaTile.java @@ -4,29 +4,42 @@ import org.nfunk.jep.JEP; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.IInventoryChangedListener; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Hand; +import net.minecraft.util.IIntArray; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.network.PacketAFA; import pokecube.core.PokecubeCore; import pokecube.core.blocks.InteractableTile; import pokecube.core.database.abilities.Ability; import pokecube.core.events.pokemob.SpawnEvent; import pokecube.core.interfaces.IPokemob; import pokecube.core.items.pokecubes.PokecubeManager; +import thut.api.ThutCaps; +import thut.api.block.IOwnableTE; import thut.api.item.ItemList; import thut.api.maths.Vector3; +import thut.core.common.network.TileUpdate; -public class AfaTile extends InteractableTile implements ITickableTileEntity, IEnergyStorage +public class AfaTile extends InteractableTile implements ITickableTileEntity, IEnergyStorage, IInventoryChangedListener { public static TileEntityType TYPE; public static final ResourceLocation SHINYTAG = new ResourceLocation(PokecubeAdv.MODID, @@ -60,32 +73,86 @@ public static void initParser(final String function, final String functionS) AfaTile.parserS.parseExpression(functionS); } + public final IIntArray syncValues = new IIntArray() + { + + @Override + public int get(final int index) + { + switch (index) + { + case 0: + return AfaTile.this.orig; + case 1: + return AfaTile.this.distance; + case 2: + return AfaTile.this.cost; + } + return 0; + } + + @Override + public void set(final int index, final int value) + { + switch (index) + { + case 0: + AfaTile.this.orig = value; + break; + case 1: + AfaTile.this.distance = value; + break; + case 2: + AfaTile.this.cost = value; + break; + } + } + + @Override + public int size() + { + // TODO Auto-generated method stub + return 3; + } + + }; + private final IItemHandlerModifiable itemstore; - public IPokemob pokemob = null; - boolean shiny = false; - public int[] shift = { 0, 0, 0 }; - public int scale = 1000; - public String animation = "idle"; - public Ability ability = null; - public int distance = 4; - public int transparency = 128; - public boolean rotates = true; - public float angle = 0; - public boolean noEnergy = false; - public boolean frozen = true; - public float animationTime = 0; - - public int energy = 0; - boolean noEnergyNeed = false; + public final IInventory inventory; + + public IPokemob pokemob = null; + boolean shiny = false; + public int[] shift = { 0, 0, 0 }; + public int scale = 1000; + public String animation = "idle"; + public Ability ability = null; + public int distance = 4; + public int transparency = 128; + public boolean rotates = true; + public float angle = 0; + public boolean noEnergy = false; + public boolean frozen = true; + public float animationTime = 0; + + public int orig = 0; + public int energy = 0; + public int cost = 0; + + int tick = 0; + + boolean noEnergyNeed = false; public AfaTile() { super(AfaTile.TYPE); this.itemstore = (IItemHandlerModifiable) this.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) .orElse(null); + this.inventory = new AfaContainer.InvWrapper(this.itemstore, (IOwnableTE) this.getCapability( + ThutCaps.OWNABLE_CAP).orElse(null)); + ((AfaContainer.InvWrapper) this.inventory).addListener(this); } - public void refreshAbility() + public void refreshAbility(final boolean update) { if (this.pokemob != null) { @@ -109,52 +176,59 @@ public void refreshAbility() this.pokemob.getEntity().setPosition(this.getPos().getX() + 0.5, this.getPos().getY() + 0.5, this.getPos() .getZ() + 0.5); this.ability.init(this.pokemob, this.distance); + if (this.getWorld() instanceof ServerWorld && update) TileUpdate.sendUpdate(this); } } + @Override + public void onLoad() + { + super.onLoad(); + this.refreshAbility(false); + } + @Override public void tick() { - final ItemStack stack = this.itemstore.getStackInSlot(0); - if (!stack.isEmpty() && this.pokemob == null) this.refreshAbility(); - else if (stack.isEmpty()) this.refreshAbility(); + if (!(this.getWorld() instanceof ServerWorld)) return; + if (this.tick++ % PokecubeAdv.config.afaTickRate != 0) return; - boolean shouldUseEnergy = this.pokemob != null && this.ability != null; int levelFactor = 0; + if (this.pokemob != null) levelFactor = this.pokemob.getLevel(); + double value = 0; + if (this.shiny) + { + AfaTile.parserS.setVarValue("d", this.distance); + value = AfaTile.parserS.getValue(); + } + else if (this.pokemob != null) + { + AfaTile.parser.setVarValue("l", levelFactor); + AfaTile.parser.setVarValue("d", this.distance); + value = AfaTile.parser.getValue(); + } + this.cost = (int) Math.ceil(value); + + boolean shouldUseEnergy = this.pokemob != null && this.ability != null && !this.noEnergy; if (this.pokemob != null && this.ability != null) this.shiny = false; - if (shouldUseEnergy) if (!this.noEnergy && !this.world.isRemote) + if (shouldUseEnergy && this.energy < this.cost) { - double value; - if (this.shiny) - { - AfaTile.parserS.setVarValue("d", this.distance); - value = AfaTile.parserS.getValue(); - } - else - { - AfaTile.parser.setVarValue("l", levelFactor); - AfaTile.parser.setVarValue("d", this.distance); - value = AfaTile.parser.getValue(); - } - final int needed = (int) Math.ceil(value); - if (this.energy < needed) - { - this.energy = 0; - return; - } - else this.energy -= needed; + this.energy = 0; + return; } + else this.energy -= this.cost; + + final boolean hasEnergy = !shouldUseEnergy || this.energy >= 0; - if (this.pokemob != null && this.ability != null) + if (this.pokemob != null && this.ability != null && hasEnergy) { this.shiny = false; // Tick increase incase ability tracks this for update. // Renderer can also then render it animated. this.pokemob.getEntity().ticksExisted++; - levelFactor = this.pokemob.getLevel(); // Do not call ability update on client. - if (!this.world.isRemote) this.ability.onUpdate(this.pokemob); + this.ability.onUpdate(this.pokemob); } shouldUseEnergy = shouldUseEnergy || this.shiny; } @@ -191,6 +265,7 @@ public void read(final CompoundNBT nbt) this.animationTime = nbt.getFloat("animTime"); this.animation = nbt.getString("animation"); this.shiny = ItemList.is(AfaTile.SHINYTAG, this.itemstore.getStackInSlot(0)); + this.orig = this.energy; } @Override @@ -216,10 +291,11 @@ public CompoundNBT write(final CompoundNBT nbt) public int receiveEnergy(final int maxReceive, final boolean simulate) { int var = maxReceive; - if (maxReceive + this.energy < this.getMaxEnergyStored()) var = this.getMaxEnergyStored() - this.energy; + if (maxReceive + this.energy > this.getMaxEnergyStored()) var = this.getMaxEnergyStored() - this.energy; if (!simulate) this.energy += var; this.energy = Math.max(0, this.energy); this.energy = Math.min(this.getMaxEnergyStored(), this.energy); + this.orig = this.energy; return var; } @@ -266,6 +342,14 @@ public void spawnEvent(final SpawnEvent.Post evt) } } + @Override + public boolean onInteract(final BlockPos pos, final PlayerEntity player, final Hand hand, + final BlockRayTraceResult hit) + { + if (player instanceof ServerPlayerEntity) PacketAFA.openGui((ServerPlayerEntity) player, this); + return true; + } + @Override public int getEnergyStored() { @@ -275,7 +359,7 @@ public int getEnergyStored() @Override public int getMaxEnergyStored() { - return PokecubeAdv.config.warpPadMaxEnergy; + return PokecubeAdv.config.afaMaxEnergy; } @Override @@ -289,4 +373,10 @@ public boolean canReceive() { return true; } + + @Override + public void onInventoryChanged(final IInventory invBasic) + { + this.refreshAbility(true); + } } diff --git a/src/main/java/pokecube/adventures/blocks/commander/CommanderTile.java b/src/main/java/pokecube/adventures/blocks/commander/CommanderTile.java index b7ceb73610..04ed6c76dd 100644 --- a/src/main/java/pokecube/adventures/blocks/commander/CommanderTile.java +++ b/src/main/java/pokecube/adventures/blocks/commander/CommanderTile.java @@ -119,7 +119,7 @@ private Object[] getArgs() throws Exception private Object[] getArgs(final Constructor constructor) { - final String[] args = this.args.split(","); + final String[] args = this.args.split(" "); final Class[] argTypes = constructor.getParameterTypes(); int index = 0; final Object[] ret = new Object[argTypes.length]; @@ -129,8 +129,8 @@ private Object[] getArgs(final Constructor constructor) if (type == Vector3.class) { final Vector3 arg = Vector3.getNewVector(); - arg.set(Double.parseDouble(args[index]) + this.getPos().getX(), Double.parseDouble(args[index + 1]) - + this.getPos().getY(), Double.parseDouble(args[index + 2]) + this.getPos().getZ()); + arg.set(Double.parseDouble(args[index]), Double.parseDouble(args[index + 1]), Double.parseDouble( + args[index + 2])); index += 3; ret[i] = arg; } diff --git a/src/main/java/pokecube/adventures/client/gui/blocks/AFA.java b/src/main/java/pokecube/adventures/client/gui/blocks/AFA.java new file mode 100644 index 0000000000..69593bb583 --- /dev/null +++ b/src/main/java/pokecube/adventures/client/gui/blocks/AFA.java @@ -0,0 +1,93 @@ +package pokecube.adventures.client.gui.blocks; + +import org.lwjgl.opengl.GL11; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.inventory.ContainerScreen; +import net.minecraft.client.gui.widget.button.Button; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.blocks.afa.AfaContainer; +import pokecube.adventures.network.PacketAFA; + +public class AFA extends ContainerScreen +{ + + public AFA(final AfaContainer screenContainer, final PlayerInventory inv, final ITextComponent titleIn) + { + super(screenContainer, inv, titleIn); + } + + @Override + protected void drawGuiContainerBackgroundLayer(final float partialTicks, final int mouseX, final int mouseY) + { + GL11.glPushMatrix(); + GL11.glColor4f(1f, 1f, 1f, 1f); + this.minecraft.getTextureManager().bindTexture(new ResourceLocation(PokecubeAdv.MODID, "textures/gui/afa.png")); + final int x = (this.width - this.xSize) / 2; + final int y = (this.height - this.ySize) / 2; + this.blit(x, y, 0, 0, this.xSize, this.ySize); + + GL11.glPopMatrix(); + } + + @Override + protected void drawGuiContainerForegroundLayer(final int mouseX, final int mouseY) + { + String text = this.getTitle().getFormattedText(); + this.font.drawString(text, 172 - this.font.getStringWidth(text), 6, 4210752); + this.font.drawString(this.playerInventory.getName().getFormattedText(), 8, this.ySize - 96 + 2, 4210752); + + text = this.container.tile.ability != null ? I18n.format("block.afa.ability.info", I18n.format( + this.container.tile.ability.getName())) : I18n.format("block.afa.ability.none"); + + this.font.drawString(text, 172 - this.font.getStringWidth(text), 22, 4210752); + + text = I18n.format("block.afa.range.info", this.container.tile.distance); + + this.font.drawString(text, 172 - this.font.getStringWidth(text), 42, 4210752); + + text = I18n.format("block.afa.power.info", this.container.tile.cost, this.container.tile.orig); + + this.font.drawString(text, 172 - this.font.getStringWidth(text), 62, 4210752); + } + + @Override + /** Draws the screen and all the components in it. */ + public void render(final int mouseX, final int mouseY, final float partialTicks) + { + this.renderBackground(); + super.render(mouseX, mouseY, partialTicks); + this.renderHoveredToolTip(mouseX, mouseY); + } + + @Override + protected void init() + { + super.init(); + + final int xOffset = -119; + final int yOffset = -88; + final String next = I18n.format("block.pc.next"); + this.addButton(new Button(this.width / 2 - xOffset - 44, this.height / 2 - yOffset - 121, 10, 10, next, b -> + { + final PacketAFA message = new PacketAFA(); + message.data.putBoolean("U", true); + message.data.putBoolean("S", Screen.hasShiftDown()); + PokecubeAdv.packets.sendToServer(message); + })); + final String prev = I18n.format("block.pc.previous"); + this.addButton(new Button(this.width / 2 - xOffset - 54, this.height / 2 - yOffset - 121, 10, 10, prev, b -> + { + final PacketAFA message = new PacketAFA(); + message.data.putBoolean("U", false); + message.data.putBoolean("S", Screen.hasShiftDown()); + PokecubeAdv.packets.sendToServer(message); + })); + + } + +} diff --git a/src/main/java/pokecube/adventures/client/gui/blocks/Commander.java b/src/main/java/pokecube/adventures/client/gui/blocks/Commander.java index 8088be00f1..74cdbfdce8 100644 --- a/src/main/java/pokecube/adventures/client/gui/blocks/Commander.java +++ b/src/main/java/pokecube/adventures/client/gui/blocks/Commander.java @@ -40,6 +40,13 @@ public boolean keyPressed(final int key, final int unk1, final int unk2) return super.keyPressed(key, unk1, unk2); } + @Override + public void render(final int a, final int b, final float c) + { + this.renderBackground(); + super.render(a, b, c); + } + @Override protected void init() { diff --git a/src/main/java/pokecube/adventures/network/PacketAFA.java b/src/main/java/pokecube/adventures/network/PacketAFA.java new file mode 100644 index 0000000000..f5b47973ac --- /dev/null +++ b/src/main/java/pokecube/adventures/network/PacketAFA.java @@ -0,0 +1,54 @@ +package pokecube.adventures.network; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.SimpleNamedContainerProvider; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IWorldPosCallable; +import net.minecraft.util.text.TranslationTextComponent; +import pokecube.adventures.blocks.afa.AfaContainer; +import pokecube.adventures.blocks.afa.AfaTile; +import thut.core.common.network.Packet; + +public class PacketAFA extends Packet +{ + public static void openGui(final ServerPlayerEntity player, final AfaTile tile) + { + final TranslationTextComponent name = new TranslationTextComponent("block.pokecube_adventures.afa"); + final SimpleNamedContainerProvider provider = new SimpleNamedContainerProvider((i, p, e) -> new AfaContainer(i, + p, IWorldPosCallable.of(tile.getWorld(), tile.getPos())), name); + player.openContainer(provider); + } + + public CompoundNBT data = new CompoundNBT(); + + public PacketAFA() + { + } + + public PacketAFA(final PacketBuffer buf) + { + this.data = buf.readCompoundTag(); + } + + @Override + public void write(final PacketBuffer buffer) + { + buffer.writeCompoundTag(this.data); + } + + @Override + public void handleServer(final ServerPlayerEntity player) + { + final Container cont = player.openContainer; + if (cont instanceof AfaContainer) + { + final AfaTile tile = ((AfaContainer) cont).tile; + final int scale = this.data.getBoolean("S") ? 10 : 1; + tile.distance += this.data.getBoolean("U") ? 1 * scale : -1 * scale; + tile.distance = Math.max(0, tile.distance); + tile.refreshAbility(true); + } + } +} diff --git a/src/main/java/pokecube/adventures/proxy/ClientProxy.java b/src/main/java/pokecube/adventures/proxy/ClientProxy.java index 39908f0aba..92c80e5ba8 100644 --- a/src/main/java/pokecube/adventures/proxy/ClientProxy.java +++ b/src/main/java/pokecube/adventures/proxy/ClientProxy.java @@ -24,6 +24,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import pokecube.adventures.Config; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.blocks.afa.AfaContainer; import pokecube.adventures.blocks.genetics.cloner.ClonerContainer; import pokecube.adventures.blocks.genetics.extractor.ExtractorContainer; import pokecube.adventures.blocks.genetics.helper.ClonerHelper; @@ -32,6 +33,7 @@ import pokecube.adventures.blocks.genetics.helper.recipe.RecipeSelector.SelectorValue; import pokecube.adventures.blocks.genetics.splicer.SplicerContainer; import pokecube.adventures.capabilities.utils.TypeTrainer; +import pokecube.adventures.client.gui.blocks.AFA; import pokecube.adventures.client.gui.blocks.Cloner; import pokecube.adventures.client.gui.blocks.Extractor; import pokecube.adventures.client.gui.blocks.Splicer; @@ -165,6 +167,7 @@ public void setupClient(final FMLClientSetupEvent event) ScreenManager.registerFactory(ClonerContainer.TYPE, Cloner::new); ScreenManager.registerFactory(SplicerContainer.TYPE, Splicer::new); ScreenManager.registerFactory(ExtractorContainer.TYPE, Extractor::new); + ScreenManager.registerFactory(AfaContainer.TYPE, AFA::new); ScreenManager.registerFactory(BagContainer.TYPE, Bag::new); // Register config gui diff --git a/src/main/java/pokecube/adventures/proxy/CommonProxy.java b/src/main/java/pokecube/adventures/proxy/CommonProxy.java index 516a026004..ed14ebc995 100644 --- a/src/main/java/pokecube/adventures/proxy/CommonProxy.java +++ b/src/main/java/pokecube/adventures/proxy/CommonProxy.java @@ -11,6 +11,8 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.blocks.afa.AfaTile; +import pokecube.adventures.blocks.warppad.WarppadTile; import pokecube.adventures.capabilities.CapabilityHasPokemobs; import pokecube.adventures.capabilities.CapabilityHasPokemobs.DefaultPokemobs; import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; @@ -28,10 +30,12 @@ import pokecube.adventures.capabilities.CapabilityNPCMessages.IHasMessages; import pokecube.adventures.capabilities.utils.TypeTrainer; import pokecube.adventures.events.CompatEvent; +import pokecube.adventures.network.PacketAFA; import pokecube.adventures.network.PacketBag; import pokecube.adventures.network.PacketCommander; import pokecube.adventures.network.PacketTrainer; import pokecube.compat.Compat; +import thut.api.OwnableCaps; import thut.core.common.Proxy; import thut.wearables.EnumWearable; import thut.wearables.IActiveWearable; @@ -87,6 +91,10 @@ public void setup(final FMLCommonSetupEvent event) PokecubeAdv.packets.registerMessage(PacketBag.class, PacketBag::new); PokecubeAdv.packets.registerMessage(PacketTrainer.class, PacketTrainer::new); PokecubeAdv.packets.registerMessage(PacketCommander.class, PacketCommander::new); + PokecubeAdv.packets.registerMessage(PacketAFA.class, PacketAFA::new); + + OwnableCaps.TILES.add(AfaTile.class); + OwnableCaps.TILES.add(WarppadTile.class); PacketTrainer.register(); } diff --git a/src/main/java/pokecube/core/ai/brain/MemoryModules.java b/src/main/java/pokecube/core/ai/brain/MemoryModules.java index 7af433dfd8..5984112601 100644 --- a/src/main/java/pokecube/core/ai/brain/MemoryModules.java +++ b/src/main/java/pokecube/core/ai/brain/MemoryModules.java @@ -36,6 +36,8 @@ public class MemoryModules public static final MemoryModuleType> POSSIBLE_MATES = new MemoryModuleType<>(Optional.empty()); public static final MemoryModuleType MATE_TARGET = new MemoryModuleType<>(Optional.empty()); + public static final MemoryModuleType> HERD_MEMBERS = new MemoryModuleType<>(Optional.empty()); + public static void register(final Register> event) { event.getRegistry().register(MemoryModules.ATTACKTARGET.setRegistryName(PokecubeCore.MODID, "attack_target")); diff --git a/src/main/java/pokecube/core/ai/brain/Sensors.java b/src/main/java/pokecube/core/ai/brain/Sensors.java index b95d004cec..7f0cc0a14b 100644 --- a/src/main/java/pokecube/core/ai/brain/Sensors.java +++ b/src/main/java/pokecube/core/ai/brain/Sensors.java @@ -3,21 +3,21 @@ import net.minecraft.entity.ai.brain.sensor.SensorType; import net.minecraftforge.event.RegistryEvent.Register; import pokecube.core.PokecubeCore; +import pokecube.core.ai.brain.sensors.InterestingMobs; import pokecube.core.ai.brain.sensors.NearBlocks; import pokecube.core.ai.brain.sensors.NearItems; -import pokecube.core.ai.brain.sensors.PossibleMates; public class Sensors { - public static final SensorType VISIBLE_BLOCKS = new SensorType<>(NearBlocks::new); - public static final SensorType VISIBLE_ITEMS = new SensorType<>(NearItems::new); - public static final SensorType VALID_MATES = new SensorType<>(PossibleMates::new); + public static final SensorType VISIBLE_BLOCKS = new SensorType<>(NearBlocks::new); + public static final SensorType VISIBLE_ITEMS = new SensorType<>(NearItems::new); + public static final SensorType INTERESTING_MOBS = new SensorType<>(InterestingMobs::new); public static void register(final Register> event) { event.getRegistry().register(Sensors.VISIBLE_BLOCKS.setRegistryName(PokecubeCore.MODID, "visible_blocks")); event.getRegistry().register(Sensors.VISIBLE_ITEMS.setRegistryName(PokecubeCore.MODID, "visible_items")); - event.getRegistry().register(Sensors.VALID_MATES.setRegistryName(PokecubeCore.MODID, "valid_mates")); + event.getRegistry().register(Sensors.INTERESTING_MOBS.setRegistryName(PokecubeCore.MODID, "interesting_mobs")); } } diff --git a/src/main/java/pokecube/core/ai/brain/sensors/PossibleMates.java b/src/main/java/pokecube/core/ai/brain/sensors/InterestingMobs.java similarity index 92% rename from src/main/java/pokecube/core/ai/brain/sensors/PossibleMates.java rename to src/main/java/pokecube/core/ai/brain/sensors/InterestingMobs.java index 7591b277e8..9de96951d6 100644 --- a/src/main/java/pokecube/core/ai/brain/sensors/PossibleMates.java +++ b/src/main/java/pokecube/core/ai/brain/sensors/InterestingMobs.java @@ -15,7 +15,7 @@ import thut.api.entity.BreedableCaps; import thut.api.entity.IBreedingMob; -public class PossibleMates extends Sensor +public class InterestingMobs extends Sensor { long lastUpdate = 0; @@ -47,7 +47,7 @@ protected void update(final ServerWorld worldIn, final AgeableEntity entityIn) @Override public Set> getUsedMemories() { - return ImmutableSet.of(MemoryModules.POSSIBLE_MATES); + return ImmutableSet.of(MemoryModules.POSSIBLE_MATES, MemoryModules.HERD_MEMBERS); } } diff --git a/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java b/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java index a09e2320ba..1c13388787 100644 --- a/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java +++ b/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java @@ -83,6 +83,7 @@ protected void update(final ServerWorld worldIn, final LivingEntity entityIn) final int size = 8; final Vec3d start = entityIn.getEyePosition(1); + final Predicate visible = input -> { final Vec3d end = new Vec3d(input); diff --git a/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java b/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java index fab3914e14..a37817da5a 100644 --- a/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java +++ b/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java @@ -3,6 +3,7 @@ import java.util.Calendar; import java.util.Random; +import net.minecraft.entity.AgeableEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; import net.minecraft.particles.ParticleTypes; @@ -94,6 +95,9 @@ private void checkAIStates() this.de_dyna = false; } + if (this.pokemob.getGeneralState(GeneralStates.MATING) && !BrainUtils.hasMateTarget( + (AgeableEntity) this.entity)) this.pokemob.setGeneralState(GeneralStates.MATING, false); + // Check if we are sheared every second or so if (this.entity.ticksExisted % 20 == 0) this.pokemob.isSheared(); diff --git a/src/main/java/pokecube/core/ai/tasks/Tasks.java b/src/main/java/pokecube/core/ai/tasks/Tasks.java index 8f492c8ff4..d4186fcc70 100644 --- a/src/main/java/pokecube/core/ai/tasks/Tasks.java +++ b/src/main/java/pokecube/core/ai/tasks/Tasks.java @@ -19,7 +19,6 @@ import net.minecraft.entity.ai.brain.task.LookAtEntityTask; import net.minecraft.entity.ai.brain.task.LookTask; import net.minecraft.entity.ai.brain.task.Task; -import net.minecraft.entity.item.ItemEntity; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.brain.MemoryModules; import pokecube.core.ai.brain.Sensors; @@ -28,19 +27,21 @@ import pokecube.core.ai.routes.GuardTask; import pokecube.core.ai.routes.IGuardAICapability; import pokecube.core.ai.routes.WalkToTask; -import pokecube.core.ai.tasks.combat.AIAttack; -import pokecube.core.ai.tasks.combat.AICombatMovement; -import pokecube.core.ai.tasks.combat.AIDodge; -import pokecube.core.ai.tasks.combat.AIFindTarget; -import pokecube.core.ai.tasks.combat.AILeap; -import pokecube.core.ai.tasks.combat.AISelectMove; -import pokecube.core.ai.tasks.idle.AIGuardEgg; -import pokecube.core.ai.tasks.idle.AIHungry; -import pokecube.core.ai.tasks.idle.AIIdle; -import pokecube.core.ai.tasks.idle.AIMate; -import pokecube.core.ai.tasks.utility.AIGatherStuff; -import pokecube.core.ai.tasks.utility.AIStoreStuff; -import pokecube.core.ai.tasks.utility.AIUseMove; +import pokecube.core.ai.tasks.combat.CicleTask; +import pokecube.core.ai.tasks.combat.DodgeTask; +import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.tasks.combat.LeapTask; +import pokecube.core.ai.tasks.combat.ManageTargetTask; +import pokecube.core.ai.tasks.combat.SelectMoveTask; +import pokecube.core.ai.tasks.combat.UseAttacksTask; +import pokecube.core.ai.tasks.idle.ForgetHuntedByTask; +import pokecube.core.ai.tasks.idle.GuardEggTask; +import pokecube.core.ai.tasks.idle.HungerTask; +import pokecube.core.ai.tasks.idle.IdleWalkTask; +import pokecube.core.ai.tasks.idle.MateTask; +import pokecube.core.ai.tasks.utility.GatherTask; +import pokecube.core.ai.tasks.utility.StoreTask; +import pokecube.core.ai.tasks.utility.UseMoveTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.pokemob.ai.GeneralStates; import pokecube.core.utils.CapHolders; @@ -57,17 +58,16 @@ public class Tasks public static final List> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.INTERACTABLE_DOORS, SensorType.HURT_BY, Sensors.VISIBLE_BLOCKS, - Sensors.VISIBLE_ITEMS, Sensors.VALID_MATES); + Sensors.VISIBLE_ITEMS, Sensors.INTERESTING_MOBS); public static void initBrain(final Brain brain) { BrainUtils.addToBrain(brain, Tasks.MEMORY_TYPES, Tasks.SENSOR_TYPES); } - //@formatter:off @SuppressWarnings("unchecked") - public static ImmutableList>> idle( - final IPokemob pokemob, final float speed) + public static ImmutableList>> idle(final IPokemob pokemob, + final float speed) { // Tasks for idle final List aiList = Lists.newArrayList(); @@ -76,22 +76,22 @@ public static void initBrain(final Brain brain) final IGuardAICapability guardCap = entity.getCapability(CapHolders.GUARDAI_CAP).orElse(null); // Idle tasks // Guard your egg - aiList.add(new AIGuardEgg(pokemob).setPriority(250)); + aiList.add(new GuardEggTask(pokemob)); // Mate with things - aiList.add(new AIMate(pokemob).setPriority(300)); + aiList.add(new MateTask(pokemob)); // Eat things - aiList.add(new AIHungry(pokemob, new ItemEntity(entity.getEntityWorld(), 0, 0, 0), 16).setPriority(300)); + aiList.add(new HungerTask(pokemob)); // Wander around - aiList.add(new AIIdle(pokemob).setPriority(500)); + aiList.add(new IdleWalkTask(pokemob)); // Owner related tasks if (!pokemob.getPokedexEntry().isStationary) // Follow owner around - aiList.add(new AIFollowOwner(pokemob, 3 + entity.getWidth() + pokemob.getPokedexEntry().length, 8 + entity.getWidth() - + pokemob.getPokedexEntry().length).setPriority(400)); + aiList.add(new AIFollowOwner(pokemob, 3 + entity.getWidth() + pokemob.getPokedexEntry().length, 8 + entity + .getWidth() + pokemob.getPokedexEntry().length)); final List>> list = Lists.newArrayList(); - final GuardAI guardai = new GuardAI(pokemob.getEntity(),guardCap); + final GuardAI guardai = new GuardAI(pokemob.getEntity(), guardCap); guardai.shouldRun = new ShouldRun() { @Override @@ -105,14 +105,14 @@ public boolean shouldRun() final Pair> pair = Pair.of(0, new GuardTask<>(guardai)); list.add(pair); - Task task = new LookTask(45, 90); - list.add(Pair.of(1, (Task)task)); + Task task = new LookTask(45, 90); + list.add(Pair.of(1, (Task) task)); task = new WalkToTask(200); - list.add(Pair.of(1, (Task)task)); + list.add(Pair.of(1, (Task) task)); - task = new FleeTask(MemoryModules.HUNTED_BY, (float) (pokemob.getMovementSpeed()*1.5f)); - list.add(Pair.of(1, (Task)task)); + task = new FleeTask(MemoryModules.HUNTED_BY, (float) (pokemob.getMovementSpeed() * 1.5f)); + list.add(Pair.of(1, (Task) task)); list.add(Tasks.lookAtMany()); list.add(Tasks.lookAtPlayerOrVillager()); @@ -129,34 +129,36 @@ public boolean shouldRun() } @SuppressWarnings("unchecked") - public static ImmutableList>> combat( - final IPokemob pokemob, final float speed) + public static ImmutableList>> combat(final IPokemob pokemob, + final float speed) { // Tasks for combat final List aiList = Lists.newArrayList(); // combat tasks - aiList.add(new AISelectMove(pokemob).setPriority(190)); + aiList.add(new SelectMoveTask(pokemob)); + // Attack stuff + aiList.add(new UseAttacksTask(pokemob)); // Attack stuff - aiList.add(new AIAttack(pokemob).setPriority(200)); + aiList.add(new ManageTargetTask(pokemob)); // Dodge attacks - aiList.add(new AIDodge(pokemob).setPriority(225)); + aiList.add(new DodgeTask(pokemob)); // Leap at things - aiList.add(new AILeap(pokemob).setPriority(225)); + aiList.add(new LeapTask(pokemob)); // Move around in combat - aiList.add(new AICombatMovement(pokemob).setPriority(250)); + aiList.add(new CicleTask(pokemob)); // Look for targets to kill - final AIFindTarget targetFind = new AIFindTarget(pokemob); - aiList.add(targetFind.setPriority(400)); + final FindTargetsTask targetFind = new FindTargetsTask(pokemob); + aiList.add(targetFind); pokemob.setTargetFinder(targetFind); final List>> list = Lists.newArrayList(); - Task task = new LookTask(45, 90); - list.add(Pair.of(1, (Task)task)); + Task task = new LookTask(45, 90); + list.add(Pair.of(1, (Task) task)); - task = new FleeTask(MemoryModules.HUNTED_BY, (float) (pokemob.getMovementSpeed()*1.5f)); - list.add(Pair.of(1, (Task)task)); + task = new FleeTask(MemoryModules.HUNTED_BY, (float) (pokemob.getMovementSpeed() * 1.5f)); + list.add(Pair.of(1, (Task) task)); pokemob.getTasks().addAll(aiList); for (final IAIRunnable run : aiList) @@ -170,25 +172,27 @@ public boolean shouldRun() } @SuppressWarnings("unchecked") - public static ImmutableList>> utility( - final IPokemob pokemob, final float speed) + public static ImmutableList>> utility(final IPokemob pokemob, + final float speed) { // Tasks for utilitiy final List aiList = Lists.newArrayList(); // combat tasks - final AIStoreStuff ai = new AIStoreStuff(pokemob); + final StoreTask ai = new StoreTask(pokemob); // Store things in chests - aiList.add(ai.setPriority(350)); + aiList.add(ai); // Gather things from ground - aiList.add(new AIGatherStuff(pokemob, 32, ai).setPriority(400)); + aiList.add(new GatherTask(pokemob, 32, ai)); // Execute moves when told to - aiList.add(new AIUseMove(pokemob).setPriority(250)); + aiList.add(new UseMoveTask(pokemob)); + // forget we were being hunted + aiList.add(new ForgetHuntedByTask(pokemob, 100)); final List>> list = Lists.newArrayList(); final IGuardAICapability guardCap = pokemob.getEntity().getCapability(CapHolders.GUARDAI_CAP).orElse(null); - final GuardAI guardai = new GuardAI(pokemob.getEntity(),guardCap); + final GuardAI guardai = new GuardAI(pokemob.getEntity(), guardCap); guardai.shouldRun = new ShouldRun() { @Override @@ -202,13 +206,13 @@ public boolean shouldRun() list.add(pair); Task task = new LookTask(45, 90); - list.add(Pair.of(1, (Task)task)); + list.add(Pair.of(1, (Task) task)); task = new WalkToTask(200); - list.add(Pair.of(1, (Task)task)); + list.add(Pair.of(1, (Task) task)); - task = new FleeTask(MemoryModules.HUNTED_BY, (float) (pokemob.getMovementSpeed()*1.5f)); - list.add(Pair.of(1, (Task)task)); + task = new FleeTask(MemoryModules.HUNTED_BY, (float) (pokemob.getMovementSpeed() * 1.5f)); + list.add(Pair.of(1, (Task) task)); pokemob.getTasks().addAll(aiList); for (final IAIRunnable run : aiList) @@ -221,6 +225,7 @@ public boolean shouldRun() return ImmutableList.copyOf(list); } + //@formatter:off private static Pair> lookAtMany() { return Pair.of(5, new FirstShuffledTask<>( diff --git a/src/main/java/pokecube/core/ai/tasks/combat/AICombatMovement.java b/src/main/java/pokecube/core/ai/tasks/combat/CicleTask.java similarity index 96% rename from src/main/java/pokecube/core/ai/tasks/combat/AICombatMovement.java rename to src/main/java/pokecube/core/ai/tasks/combat/CicleTask.java index c03db5447c..e924b3ae85 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/AICombatMovement.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/CicleTask.java @@ -14,13 +14,13 @@ * on cooldown between attacks. It also manages the leaping at targets, and the * dodging of attacks. */ -public class AICombatMovement extends FightTask implements IAICombat +public class CicleTask extends CombatTask implements IAICombat { Entity target; Vector3 centre; double movementSpeed; - public AICombatMovement(final IPokemob mob) + public CicleTask(final IPokemob mob) { super(mob); this.movementSpeed = this.entity.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue() * 1.8; diff --git a/src/main/java/pokecube/core/ai/tasks/combat/FightTask.java b/src/main/java/pokecube/core/ai/tasks/combat/CombatTask.java similarity index 57% rename from src/main/java/pokecube/core/ai/tasks/combat/FightTask.java rename to src/main/java/pokecube/core/ai/tasks/combat/CombatTask.java index ccfa76c826..5b88978dab 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/FightTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/CombatTask.java @@ -12,24 +12,24 @@ import pokecube.core.interfaces.IPokemob; import thut.api.entity.ai.IAICombat; -public abstract class FightTask extends TaskBase implements IAICombat +public abstract class CombatTask extends TaskBase implements IAICombat { private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); static { - FightTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_PRESENT); + CombatTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_PRESENT); } - public FightTask(final IPokemob pokemob) + public CombatTask(final IPokemob pokemob) { - super(pokemob, FightTask.MEMS); + super(pokemob, CombatTask.MEMS); } - public FightTask(final IPokemob pokemob, final Map, MemoryModuleStatus> mems) + public CombatTask(final IPokemob pokemob, final Map, MemoryModuleStatus> mems) { - super(pokemob, TaskBase.merge(FightTask.MEMS, mems)); + super(pokemob, TaskBase.merge(CombatTask.MEMS, mems)); } } diff --git a/src/main/java/pokecube/core/ai/tasks/combat/AIDodge.java b/src/main/java/pokecube/core/ai/tasks/combat/DodgeTask.java similarity index 97% rename from src/main/java/pokecube/core/ai/tasks/combat/AIDodge.java rename to src/main/java/pokecube/core/ai/tasks/combat/DodgeTask.java index 4a3875d0b3..783cd7d3f4 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/AIDodge.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/DodgeTask.java @@ -18,7 +18,7 @@ import thut.api.entity.ai.IAICombat; import thut.api.maths.Vector3; -public class AIDodge extends FightTask implements IAICombat +public class DodgeTask extends CombatTask implements IAICombat { // Location of the targetted attack @@ -29,7 +29,7 @@ public class AIDodge extends FightTask implements IAICombat int dodgeCooldown = -1; - public AIDodge(final IPokemob mob) + public DodgeTask(final IPokemob mob) { super(mob); this.movementSpeed = this.entity.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue() * 1.8; diff --git a/src/main/java/pokecube/core/ai/tasks/combat/AIFindTarget.java b/src/main/java/pokecube/core/ai/tasks/combat/FindTargetsTask.java similarity index 79% rename from src/main/java/pokecube/core/ai/tasks/combat/AIFindTarget.java rename to src/main/java/pokecube/core/ai/tasks/combat/FindTargetsTask.java index 051b3ed218..8c16336750 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/AIFindTarget.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/FindTargetsTask.java @@ -44,13 +44,13 @@ import thut.api.terrain.TerrainManager; /** This IAIRunnable is to find targets for the pokemob to try to kill. */ -public class AIFindTarget extends TaskBase implements IAICombat, ITargetFinder +public class FindTargetsTask extends TaskBase implements IAICombat, ITargetFinder { public static boolean handleDamagedTargets = true; static { - MinecraftForge.EVENT_BUS.register(AIFindTarget.class); + MinecraftForge.EVENT_BUS.register(FindTargetsTask.class); } public static int DEAGROTIMER = 50; @@ -80,25 +80,26 @@ public static void deagro(final LivingEntity mob) if (mob == null) return; final IPokemob aggressor = CapabilityPokemob.getPokemobFor(mob); - if (mob instanceof MobEntity) - { - final LivingEntity oldTarget = BrainUtils.getAttackTarget(mob); - BrainUtils.setAttackTarget(mob, null); - AIFindTarget.deagro(oldTarget); - } - mob.getBrain().removeMemory(MemoryModules.ATTACKTARGET); if (aggressor != null) { aggressor.getTargetFinder().clear(); aggressor.setCombatState(CombatStates.ANGRY, false); aggressor.setCombatState(CombatStates.MATEFIGHT, false); } + if (mob instanceof MobEntity) + { + final LivingEntity oldTarget = BrainUtils.getAttackTarget(mob); + BrainUtils.setAttackTarget(mob, null); + FindTargetsTask.deagro(oldTarget); + } + mob.getBrain().removeMemory(MemoryModules.ATTACKTARGET); + mob.getBrain().removeMemory(MemoryModules.MATE_TARGET); } @SubscribeEvent public static void livingSetTargetEvent(final LivingSetAttackTargetEvent evt) { - if (!AIFindTarget.handleDamagedTargets || evt.getEntity().getEntityWorld().isRemote) return; + if (!FindTargetsTask.handleDamagedTargets || evt.getEntity().getEntityWorld().isRemote) return; // Only handle attack target set, not revenge target set. if (evt.getTarget() == ((LivingEntity) evt.getEntity()).getRevengeTarget()) return; // Prevent mob from targetting self. @@ -124,7 +125,7 @@ public static void livingSetTargetEvent(final LivingSetAttackTargetEvent evt) if (nearest.getDistanceSq(evt.getEntityLiving()) < 256 && nearest instanceof LivingEntity) { if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Diverting agro to owner!"); - AIFindTarget.initiateCombat((MobEntity) evt.getEntityLiving(), (LivingEntity) nearest); + FindTargetsTask.initiateCombat((MobEntity) evt.getEntityLiving(), (LivingEntity) nearest); return; } } @@ -155,7 +156,7 @@ public static void livingSetTargetEvent(final LivingSetAttackTargetEvent evt) @SubscribeEvent public static void onAttacked(final LivingAttackEvent event) { - if (!AIFindTarget.handleDamagedTargets || event.getEntity().getEntityWorld().isRemote) return; + if (!FindTargetsTask.handleDamagedTargets || event.getEntity().getEntityWorld().isRemote) return; final DamageSource source = event.getSource(); final LivingEntity attacked = (LivingEntity) event.getEntity(); @@ -181,7 +182,7 @@ public static void onAttacked(final LivingAttackEvent event) @SubscribeEvent public static void onDamaged(final LivingDamageEvent event) { - if (!AIFindTarget.handleDamagedTargets || event.getEntity().getEntityWorld().isRemote) return; + if (!FindTargetsTask.handleDamagedTargets || event.getEntity().getEntityWorld().isRemote) return; final DamageSource source = event.getSource(); final LivingEntity attacked = (LivingEntity) event.getEntity(); @@ -214,7 +215,7 @@ public static void onDamaged(final LivingDamageEvent event) if (oldTarget != null && BrainUtils.getAttackTarget(attacked) != oldTarget) newTarget = oldTarget; else if (attacker instanceof LivingEntity) newTarget = (LivingEntity) attacker; final MobEntity living = (MobEntity) attacked; - AIFindTarget.initiateCombat(living, newTarget); + FindTargetsTask.initiateCombat(living, newTarget); } } @@ -228,8 +229,8 @@ public static void onDamaged(final LivingDamageEvent event) */ final Predicate validGuardTarget = input -> { - if (input == AIFindTarget.this.entity) return false; - if (TeamManager.sameTeam(AIFindTarget.this.entity, input)) return false; + if (input == FindTargetsTask.this.entity) return false; + if (TeamManager.sameTeam(FindTargetsTask.this.entity, input)) return false; if (!AITools.validTargets.test(input)) return false; return input instanceof LivingEntity; }; @@ -238,7 +239,7 @@ public static void onDamaged(final LivingDamageEvent event) private LivingEntity entityTarget = null; - public AIFindTarget(final IPokemob mob) + public FindTargetsTask(final IPokemob mob) { super(mob, ImmutableMap.of(MemoryModuleType.VISIBLE_MOBS, MemoryModuleStatus.VALUE_PRESENT)); } @@ -246,14 +247,14 @@ public AIFindTarget(final IPokemob mob) @Override public void clear() { - this.agroTimer = AIFindTarget.DEAGROTIMER; + this.agroTimer = FindTargetsTask.DEAGROTIMER; this.entityTarget = null; } /** * Check if there are any mobs nearby that will help us.
*
- * This is called from {@link AIFindTarget#shouldRun()} + * This is called from {@link FindTargetsTask#shouldRun()} * * @return someone needed help. */ @@ -286,25 +287,25 @@ protected boolean checkForHelp(final LivingEntity from) // We check for whether it is the same species and, has the same owner // (including null) or is on the team. - final Predicate relationCheck = input -> + final Predicate relationCheck = input -> { final IPokemob other = CapabilityPokemob.getPokemobFor(input); // No pokemob, no helps. if (other == null) return false; // Not related, no helps. - if (!other.getPokedexEntry().areRelated(AIFindTarget.this.pokemob.getPokedexEntry())) return false; + if (!other.getPokedexEntry().areRelated(FindTargetsTask.this.pokemob.getPokedexEntry())) return false; // Same owner (owned or null), helps. - if (other.getOwnerId() == null && AIFindTarget.this.pokemob.getOwnerId() == null || other - .getOwnerId() != null && other.getOwnerId().equals(AIFindTarget.this.pokemob.getOwnerId())) + if (other.getOwnerId() == null && FindTargetsTask.this.pokemob.getOwnerId() == null || other + .getOwnerId() != null && other.getOwnerId().equals(FindTargetsTask.this.pokemob.getOwnerId())) return true; // Same team, helps. - if (TeamManager.sameTeam(input, AIFindTarget.this.entity)) return true; + if (TeamManager.sameTeam(input, FindTargetsTask.this.entity)) return true; return false; }; // Only allow valid guard targets. - for (final Object o : pokemobs) - if (relationCheck.test((MobEntity) o)) ret.add((MobEntity) o); + for (final LivingEntity o : pokemobs) + if (relationCheck.test(o)) ret.add(o); for (final LivingEntity mob : ret) { @@ -323,7 +324,7 @@ protected boolean checkForHelp(final LivingEntity from) /** * Check for and agress any guard targets.
*
- * This is called from {@link AIFindTarget#run()} + * This is called from {@link FindTargetsTask#run()} * * @return a guard target was found */ @@ -350,8 +351,8 @@ protected boolean checkGuard() final List ret = new ArrayList<>(); final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); // Only allow valid guard targets. - for (final Object o : pokemobs) - if (this.validGuardTarget.test((Entity) o)) ret.add((LivingEntity) o); + for (final LivingEntity o : pokemobs) + if (this.validGuardTarget.test(o)) ret.add(o); ret.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); if (ret.isEmpty()) return false; @@ -384,12 +385,12 @@ protected void setAttackTarget(final MobEntity attacker, final LivingEntity targ { if (target == null) { - AIFindTarget.deagro(attacker); + FindTargetsTask.deagro(attacker); this.clear(); } else { - AIFindTarget.initiateCombat(attacker, target); + FindTargetsTask.initiateCombat(attacker, target); this.entityTarget = target; } } @@ -397,7 +398,7 @@ protected void setAttackTarget(final MobEntity attacker, final LivingEntity targ /** * Check if there is a target to hunt, if so, sets it as target.
*
- * This is called from {@link AIFindTarget#run()} + * This is called from {@link FindTargetsTask#run()} * * @return if a hunt target was found. */ @@ -432,7 +433,7 @@ protected boolean checkHunt() /** * Check if owner is under attack, if so, agress the attacker.
*
- * This is called from {@link AIFindTarget#run()} + * This is called from {@link FindTargetsTask#run()} * * @return if target was found. */ @@ -515,7 +516,6 @@ public boolean shouldRun() // Don't look for targets if you are sitting. final boolean ret = target == null && !this.pokemob.getLogicState(LogicStates.SITTING); - final boolean tame = this.pokemob.getGeneralState(GeneralStates.TAMED); // Target is too far away, lets forget it. if (target != null && this.entity.getDistance(target) > PokecubeCore.getConfig().chaseDistance) @@ -526,86 +526,6 @@ public boolean shouldRun() return false; } - // If we have a target, we don't need to look for another. - if (target != null) - { - final IOwnable targetOwnable = OwnableCaps.getOwnable(this.entityTarget); - - // Prevents swapping to owner as target if we are owned and we just - // defeated someone, only applies to tame mobs, wild mobs will still - // try to kill the owner if they run away. - if (this.entityTarget != null && this.entityTarget != target && targetOwnable != null && targetOwnable - .getOwner(this.world) == target && this.pokemob.getGeneralState(GeneralStates.TAMED) - && this.entityTarget.getHealth() <= 0) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Battle is over."); - this.setAttackTarget(this.entity, null); - return false; - } - - this.entityTarget = target; - // If our target is dead, we can forget it, so long as it isn't - // owned - if (!target.isAlive() || target.getHealth() <= 0) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Target is dead!"); - this.setAttackTarget(this.entity, null); - return false; - } - - // If our target is us, we should forget it. - if (target == this.entity) - { - this.setAttackTarget(this.entity, null); - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Cannot target self."); - return false; - } - - // If we are not angry, we should forget target. - if (!this.pokemob.getCombatState(CombatStates.ANGRY)) - { - this.setAttackTarget(this.entity, null); - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Not Angry. losing target now."); - return false; - } - - // If our target is owner, we should forget it. - if (target.getUniqueID().equals(this.pokemob.getOwnerId())) - { - this.setAttackTarget(this.entity, null); - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Cannot target owner."); - return false; - } - - // If your owner is too far away, shouldn't have a target, should be - // going back to the owner. - if (tame) - { - final Entity owner = this.pokemob.getOwner(); - final boolean stayOrGuard = this.pokemob.getCombatState(CombatStates.GUARDING) || this.pokemob - .getGeneralState(GeneralStates.STAYING); - if (owner != null && !stayOrGuard && owner.getDistance(this.entity) > PokecubeCore - .getConfig().chaseDistance) - { - this.setAttackTarget(this.entity, null); - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug( - "Cannot target mob that far while guarding."); - return false; - } - - // If the target is a pokemob, on same team, we shouldn't target - // it either, unless it is fighting over a mate - if (TeamManager.sameTeam(target, this.entity) && !this.pokemob.getCombatState(CombatStates.MATEFIGHT)) - { - this.setAttackTarget(this.entity, null); - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Cannot target team mates."); - return false; - } - - } - return false; - } - // Check if the pokemob is set to follow, and if so, look for mobs // nearby trying to attack the owner of the pokemob, if any such are // found, try to aggress them immediately. @@ -620,7 +540,7 @@ public boolean shouldRun() if (target == null && this.entityTarget != null) { target = this.entityTarget; - if (this.agroTimer == -1) this.agroTimer = AIFindTarget.DEAGROTIMER; + if (this.agroTimer == -1) this.agroTimer = FindTargetsTask.DEAGROTIMER; else { this.agroTimer--; diff --git a/src/main/java/pokecube/core/ai/tasks/combat/AILeap.java b/src/main/java/pokecube/core/ai/tasks/combat/LeapTask.java similarity index 94% rename from src/main/java/pokecube/core/ai/tasks/combat/AILeap.java rename to src/main/java/pokecube/core/ai/tasks/combat/LeapTask.java index b8a9a1b62a..d3a90933d5 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/AILeap.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/LeapTask.java @@ -27,13 +27,13 @@ * move target, ie attacking blocks, so it doesn't need to actually have a * living target to apply. */ -public class AILeap extends TaskBase implements IAICombat +public class LeapTask extends TaskBase implements IAICombat { private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); static { - AILeap.MEMS.put(MemoryModules.MOVE_TARGET, MemoryModuleStatus.VALUE_PRESENT); + LeapTask.MEMS.put(MemoryModules.MOVE_TARGET, MemoryModuleStatus.VALUE_PRESENT); } int leapTick = -1; @@ -46,9 +46,9 @@ public class AILeap extends TaskBase implements IAICombat Vector3 leapTarget = Vector3.getNewVector(); Vector3 leapOrigin = Vector3.getNewVector(); - public AILeap(final IPokemob mob) + public LeapTask(final IPokemob mob) { - super(mob, AILeap.MEMS); + super(mob, LeapTask.MEMS); this.movementSpeed = this.entity.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue() * 1.8; } diff --git a/src/main/java/pokecube/core/ai/tasks/combat/ManageTargetTask.java b/src/main/java/pokecube/core/ai/tasks/combat/ManageTargetTask.java new file mode 100644 index 0000000000..2c12377554 --- /dev/null +++ b/src/main/java/pokecube/core/ai/tasks/combat/ManageTargetTask.java @@ -0,0 +1,188 @@ +package pokecube.core.ai.tasks.combat; + +import net.minecraft.entity.AgeableEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import pokecube.core.PokecubeCore; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.brain.MemoryModules; +import pokecube.core.handlers.TeamManager; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.interfaces.pokemob.ai.CombatStates; +import pokecube.core.interfaces.pokemob.ai.GeneralStates; + +public class ManageTargetTask extends CombatTask +{ + /** The target being attacked. */ + LivingEntity entityTarget; + + /** IPokemob version of entityTarget. */ + IPokemob pokemobTarget; + + int battleTime = 0; + + public ManageTargetTask(final IPokemob pokemob) + { + super(pokemob); + } + + @Override + public void reset() + { + this.entityTarget = null; + this.pokemobTarget = null; + FindTargetsTask.deagro(this.entity); + } + + @Override + public void run() + { + this.battleTime++; + + // Check if we should be cancelling due to wild mobs + + final IPokemob mobA = this.pokemob; + final IPokemob mobB = this.pokemobTarget; + + LivingEntity mate = BrainUtils.getMateTarget((AgeableEntity) this.entity); + + if (mate != null && !mate.isAlive()) + { + BrainUtils.setMateTarget((AgeableEntity) this.entity, null); + mate = null; + } + + boolean deAgro = mate == this.entityTarget; + + agroCheck: + if (mobB != null && !deAgro) + { + if (mobB.getCombatState(CombatStates.FAINTED)) + { + deAgro = true; + break agroCheck; + } + + final boolean weTame = mobA.getOwnerId() != null && !mobA.getCombatState(CombatStates.MATEFIGHT); + final boolean theyTame = mobB.getOwnerId() != null && !mobB.getCombatState(CombatStates.MATEFIGHT); + final boolean weHunt = mobA.getCombatState(CombatStates.HUNTING); + final boolean theyHunt = mobB.getCombatState(CombatStates.HUNTING); + + final boolean bothWild = !weTame && !theyTame; + final boolean oneHunting = weHunt || theyHunt; + + // Give up if we took too long to fight. + if (bothWild && this.battleTime > UseAttacksTask.maxWildBattleDur) + { + deAgro = true; + break agroCheck; + } + + if (bothWild && !oneHunting) + { + final float weHealth = mobA.getEntity().getHealth() / mobA.getEntity().getMaxHealth(); + final float theyHealth = mobB.getEntity().getHealth() / mobB.getEntity().getMaxHealth(); + // Wild mobs shouldn't fight to the death unless hunting. + if (weHealth < 0.5 || theyHealth < 0.5) + { + mobA.setCombatState(CombatStates.MATEFIGHT, false); + mobB.setCombatState(CombatStates.MATEFIGHT, false); + + if (weHealth < 0.5) if (mobA.getEntity().getBrain().hasMemory(MemoryModules.HUNTED_BY, + MemoryModuleStatus.REGISTERED)) mobA.getEntity().getBrain().setMemory( + MemoryModules.HUNTED_BY, mobB.getEntity()); + if (theyHealth < 0.5) if (mobB.getEntity().getBrain().hasMemory(MemoryModules.HUNTED_BY, + MemoryModuleStatus.REGISTERED)) mobB.getEntity().getBrain().setMemory( + MemoryModules.HUNTED_BY, mobA.getEntity()); + + PokecubeCore.LOGGER.debug("No want to fight, too weak!"); + deAgro = true; + } + } + } + if (mobA.getCombatState(CombatStates.FAINTED)) deAgro = true; + + agroCheck: + if (!deAgro) + { + if (!this.entityTarget.isAlive() || this.entityTarget.getHealth() <= 0) + { + PokecubeCore.LOGGER.debug("They are Dead!"); + deAgro = true; + break agroCheck; + } + if (!this.entity.isAlive() || this.entity.getHealth() <= 0) + { + PokecubeCore.LOGGER.debug("We are Dead!"); + deAgro = true; + break agroCheck; + } + + // If our target is us, we should forget it. + if (this.entityTarget == this.entity) + { + PokecubeCore.LOGGER.debug("Cannot target self."); + deAgro = true; + break agroCheck; + } + + // If we are not angry, we should forget target. + if (!this.pokemob.getCombatState(CombatStates.ANGRY)) + { + PokecubeCore.LOGGER.debug("Not Angry. losing target now."); + deAgro = true; + break agroCheck; + } + + // If our target is owner, we should forget it. + if (this.entityTarget.getUniqueID().equals(this.pokemob.getOwnerId())) + { + PokecubeCore.LOGGER.debug("Cannot target owner."); + deAgro = true; + break agroCheck; + } + + final boolean tame = this.pokemob.getGeneralState(GeneralStates.TAMED); + // If your owner is too far away, shouldn't have a target, should be + // going back to the owner. + if (tame) + { + final Entity owner = this.pokemob.getOwner(); + final boolean stayOrGuard = this.pokemob.getCombatState(CombatStates.GUARDING) || this.pokemob + .getGeneralState(GeneralStates.STAYING); + if (owner != null && !stayOrGuard && owner.getDistance(this.entity) > PokecubeCore + .getConfig().chaseDistance) + { + PokecubeCore.LOGGER.debug("Cannot target mob that far while guarding."); + deAgro = true; + break agroCheck; + } + + // If the target is a pokemob, on same team, we shouldn't target + // it either, unless it is fighting over a mate + if (TeamManager.sameTeam(this.entityTarget, this.entity) && !this.pokemob.getCombatState( + CombatStates.MATEFIGHT)) + { + PokecubeCore.LOGGER.debug("Cannot target team mates."); + deAgro = true; + break agroCheck; + } + + } + } + // All we do is deagro if needed. + if (deAgro) FindTargetsTask.deagro(this.entity); + } + + @Override + public boolean shouldRun() + { + this.entityTarget = BrainUtils.getAttackTarget(this.entity); + this.pokemobTarget = CapabilityPokemob.getPokemobFor(this.entityTarget); + // Only run if we have a combat target + return this.entityTarget != null; + } + +} diff --git a/src/main/java/pokecube/core/ai/tasks/combat/AISelectMove.java b/src/main/java/pokecube/core/ai/tasks/combat/SelectMoveTask.java similarity index 95% rename from src/main/java/pokecube/core/ai/tasks/combat/AISelectMove.java rename to src/main/java/pokecube/core/ai/tasks/combat/SelectMoveTask.java index 3388d181a5..b792bfad6f 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/AISelectMove.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/SelectMoveTask.java @@ -17,12 +17,12 @@ import pokecube.core.utils.Tools; import thut.api.entity.ai.IAICombat; -public class AISelectMove extends FightTask implements IAICombat +public class SelectMoveTask extends CombatTask implements IAICombat { Entity target; private int moveIndexCounter = 0; - public AISelectMove(final IPokemob mob) + public SelectMoveTask(final IPokemob mob) { super(mob); this.setMutex(0); @@ -40,7 +40,8 @@ public void reset() public void run() { // Pokemobs hunting or guarding will always select whatever is strongest - if (this.pokemob.getCombatState(CombatStates.GUARDING) || this.pokemob.getCombatState(CombatStates.HUNTING)) + if (this.pokemob.getCombatState(CombatStates.GUARDING) || this.pokemob.getCombatState(CombatStates.HUNTING) + || this.pokemob.getCombatState(CombatStates.MATEFIGHT)) { this.selectHighestDamage(); return; diff --git a/src/main/java/pokecube/core/ai/tasks/combat/AIAttack.java b/src/main/java/pokecube/core/ai/tasks/combat/UseAttacksTask.java similarity index 84% rename from src/main/java/pokecube/core/ai/tasks/combat/AIAttack.java rename to src/main/java/pokecube/core/ai/tasks/combat/UseAttacksTask.java index 681e8cbe08..59bef1f58e 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/AIAttack.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/UseAttacksTask.java @@ -36,21 +36,23 @@ * decided to battle, as well as dealing with combat between rivals over a mate. * It is the one to queue the attack for the pokemob to perform. */ -public class AIAttack extends FightTask implements IAICombat +public class UseAttacksTask extends CombatTask implements IAICombat { public static int maxWildBattleDur = 600; /** The target being attacked. */ LivingEntity entityTarget; + /** IPokemob version of entityTarget. */ - IPokemob pokemobTarget; + IPokemob pokemobTarget; /** Where the target is/was for attack. */ - Vector3 targetLoc = Vector3.getNewVector(); + Vector3 targetLoc = Vector3.getNewVector(); + Matrix3 targetBox = new Matrix3(); + Matrix3 attackerBox = new Matrix3(); + /** Move we are using */ Move_Base attack; - Matrix3 targetBox = new Matrix3(); - Matrix3 attackerBox = new Matrix3(); /** Temp vectors for checking things. */ Vector3 v = Vector3.getNewVector(); @@ -63,11 +65,10 @@ public class AIAttack extends FightTask implements IAICombat protected int chaseTime; /** Used for when to execute attacks. */ protected int delayTime = -1; - boolean running = false; - int battleTime = 0; + boolean waitingToStart = false; - public AIAttack(final IPokemob mob) + public UseAttacksTask(final IPokemob mob) { super(mob); this.movementSpeed = this.entity.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue() * 1.8; @@ -76,49 +77,14 @@ public AIAttack(final IPokemob mob) public boolean continueExecuting() { - final IPokemob mobA = this.pokemob; - final IPokemob mobB = this.pokemobTarget; - - if (mobB != null) - { - if (mobB.getCombatState(CombatStates.FAINTED)) return false; - - final boolean weTame = mobA.getOwnerId() != null || mobA.getCombatState(CombatStates.MATEFIGHT); - final boolean theyTame = mobB.getOwnerId() != null || mobB.getCombatState(CombatStates.MATEFIGHT); - final boolean weHunt = mobA.getCombatState(CombatStates.HUNTING); - final boolean theyHunt = mobB.getCombatState(CombatStates.HUNTING); - - if (weTame == theyTame && !weTame && weHunt == theyHunt && !theyHunt) - { - final float weHealth = mobA.getEntity().getHealth() / mobA.getEntity().getMaxHealth(); - final float theyHealth = mobB.getEntity().getHealth() / mobB.getEntity().getMaxHealth(); - // Wild mobs shouldn't fight to the death unless hunting. - if (weHealth < 0.5 || theyHealth < 0.5) - { - mobA.setCombatState(CombatStates.MATEFIGHT, false); - mobB.setCombatState(CombatStates.MATEFIGHT, false); - AIFindTarget.deagro(this.entity); - return false; - } - // Give up if we took too long to fight. - if (this.battleTime > AIAttack.maxWildBattleDur) return false; - } - } - - if (mobA.getCombatState(CombatStates.FAINTED)) return false; - - if (!this.entityTarget.isAlive() || this.entityTarget.getHealth() <= 0) return false; - if (!this.entity.isAlive() || this.entity.getHealth() <= 0) return false; - return this.pokemob.getCombatState(CombatStates.ANGRY); } @Override public void reset() { - this.battleTime = 0; this.clearUseMove(); - AIFindTarget.deagro(this.entity); + this.waitingToStart = false; } private void setUseMove() @@ -136,21 +102,20 @@ private void clearUseMove() @Override public void run() { - this.battleTime++; // Check if the pokemob has an active move being used, if so return if (this.pokemob.getActiveMove() != null) return; this.attack = MovesUtils.getMoveFromName(this.pokemob.getMove(this.pokemob.getMoveIndex())); if (this.attack == null) this.attack = MovesUtils.getMoveFromName(IMoveConstants.DEFAULT_MOVE); - if (!this.running) + if (!this.waitingToStart) { if (!((this.attack.getAttackCategory() & IMoveConstants.CATEGORY_SELF) != 0) && !this.pokemob .getGeneralState(GeneralStates.CONTROLLED)) this.setWalkTo(this.entityTarget.getPositionVec(), this.movementSpeed, 0); this.targetLoc.set(this.entityTarget); this.chaseTime = 0; - this.running = true; + this.waitingToStart = true; /** * Don't want to notify if the pokemob just broke out of a * pokecube. @@ -344,12 +309,6 @@ public boolean shouldRun() if (target != this.entityTarget) this.pokemobTarget = CapabilityPokemob.getPokemobFor(target); this.entityTarget = target; - if (!this.continueExecuting()) - { - AIFindTarget.deagro(this.entity); - return false; - } - return true; } diff --git a/src/main/java/pokecube/core/ai/tasks/idle/IdleTask.java b/src/main/java/pokecube/core/ai/tasks/idle/BaseIdleTask.java similarity index 56% rename from src/main/java/pokecube/core/ai/tasks/idle/IdleTask.java rename to src/main/java/pokecube/core/ai/tasks/idle/BaseIdleTask.java index 7a2bf508bc..7c4a44cad6 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/IdleTask.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/BaseIdleTask.java @@ -11,23 +11,23 @@ import pokecube.core.ai.tasks.TaskBase; import pokecube.core.interfaces.IPokemob; -public abstract class IdleTask extends TaskBase +public abstract class BaseIdleTask extends TaskBase { private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); static { - IdleTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_ABSENT); + BaseIdleTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_ABSENT); } - public IdleTask(final IPokemob pokemob) + public BaseIdleTask(final IPokemob pokemob) { - super(pokemob, IdleTask.MEMS); + super(pokemob, BaseIdleTask.MEMS); } - public IdleTask(final IPokemob pokemob, final Map, MemoryModuleStatus> mems) + public BaseIdleTask(final IPokemob pokemob, final Map, MemoryModuleStatus> mems) { - super(pokemob, TaskBase.merge(IdleTask.MEMS, mems)); + super(pokemob, TaskBase.merge(BaseIdleTask.MEMS, mems)); } } diff --git a/src/main/java/pokecube/core/ai/tasks/idle/ForgetHuntedByTask.java b/src/main/java/pokecube/core/ai/tasks/idle/ForgetHuntedByTask.java new file mode 100644 index 0000000000..b12b6d12ab --- /dev/null +++ b/src/main/java/pokecube/core/ai/tasks/idle/ForgetHuntedByTask.java @@ -0,0 +1,39 @@ +package pokecube.core.ai.tasks.idle; + +import net.minecraft.entity.LivingEntity; +import pokecube.core.ai.brain.MemoryModules; +import pokecube.core.ai.tasks.TaskBase; +import pokecube.core.interfaces.IPokemob; + +public class ForgetHuntedByTask extends TaskBase +{ + int fleeingTicks = 0; + + final int duration; + + public ForgetHuntedByTask(final IPokemob pokemob, final int duration) + { + super(pokemob); + this.duration = duration; + } + + @Override + public void reset() + { + this.fleeingTicks = 0; + this.entity.getBrain().removeMemory(MemoryModules.HUNTED_BY); + } + + @Override + public void run() + { + this.fleeingTicks++; + } + + @Override + public boolean shouldRun() + { + return this.entity.getBrain().hasMemory(MemoryModules.HUNTED_BY) && this.fleeingTicks < this.duration; + } + +} diff --git a/src/main/java/pokecube/core/ai/tasks/idle/AIGuardEgg.java b/src/main/java/pokecube/core/ai/tasks/idle/GuardEggTask.java similarity index 89% rename from src/main/java/pokecube/core/ai/tasks/idle/AIGuardEgg.java rename to src/main/java/pokecube/core/ai/tasks/idle/GuardEggTask.java index f12772e1f4..83ec43e410 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/AIGuardEgg.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/GuardEggTask.java @@ -8,7 +8,7 @@ import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.items.pokemobeggs.EntityPokemobEgg; import thut.api.terrain.TerrainManager; @@ -19,7 +19,7 @@ * the mother's breeding cooldown from dropping while an egg is being * guarded. */ -public class AIGuardEgg extends IdleTask +public class GuardEggTask extends BaseIdleTask { public static int PATHCOOLDOWN = 50; public static int SEARCHCOOLDOWN = 50; @@ -29,7 +29,7 @@ public class AIGuardEgg extends IdleTask int eggSearchCooldown = 0; int eggPathCooldown = 0; - public AIGuardEgg(final IPokemob mob) + public GuardEggTask(final IPokemob mob) { super(mob); } @@ -49,7 +49,7 @@ public void run() if (this.entity.getDistanceSq(this.egg) < 4) return; // On cooldown if (this.eggPathCooldown-- > 0) return; - this.eggPathCooldown = AIGuardEgg.PATHCOOLDOWN; + this.eggPathCooldown = GuardEggTask.PATHCOOLDOWN; // Path to the egg. final double speed = this.entity.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue(); this.setWalkTo(this.egg.getPositionVec(), speed, 0); @@ -73,14 +73,14 @@ public boolean shouldRun() if (this.eggSearchCooldown-- > 0) return false; // Only the female (or neutral) will guard the eggs. if (this.pokemob.getSexe() == IPokemob.MALE) return false; - this.eggSearchCooldown = AIGuardEgg.SEARCHCOOLDOWN; + this.eggSearchCooldown = GuardEggTask.SEARCHCOOLDOWN; if (!TerrainManager.isAreaLoaded(this.world, this.entity.getPosition(), PokecubeCore .getConfig().guardSearchDistance + 2)) return false; final List list = new ArrayList<>(); final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); list.addAll(pokemobs); - final Predicate isEgg = input -> input instanceof EntityPokemobEgg && AIGuardEgg.this.entity + final Predicate isEgg = input -> input instanceof EntityPokemobEgg && GuardEggTask.this.entity .getUniqueID().equals(((EntityPokemobEgg) input).getMotherId()) && input.isAlive(); list.removeIf(e -> !isEgg.test(e)); list.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); @@ -89,7 +89,7 @@ public boolean shouldRun() this.egg = (EntityPokemobEgg) list.get(0); this.egg.mother = this.pokemob; - AIFindTarget.deagro(this.pokemob.getEntity()); + FindTargetsTask.deagro(this.pokemob.getEntity()); // Only run if we have a live egg to watch. if (this.egg != null) return this.egg.isAlive() ? true : false; diff --git a/src/main/java/pokecube/core/ai/tasks/idle/HerdTask.java b/src/main/java/pokecube/core/ai/tasks/idle/HerdTask.java new file mode 100644 index 0000000000..46b6229c91 --- /dev/null +++ b/src/main/java/pokecube/core/ai/tasks/idle/HerdTask.java @@ -0,0 +1,44 @@ +package pokecube.core.ai.tasks.idle; + +import java.util.Map; + +import com.google.common.collect.Maps; + +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import pokecube.core.ai.brain.MemoryModules; +import pokecube.core.interfaces.IPokemob; + +public class HerdTask extends BaseIdleTask +{ + private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); + + static + { + HerdTask.MEMS.put(MemoryModules.HERD_MEMBERS, MemoryModuleStatus.VALUE_PRESENT); + } + + public HerdTask(final IPokemob pokemob) + { + super(pokemob, HerdTask.MEMS); + } + + @Override + public void reset() + { + + } + + @Override + public void run() + { + + } + + @Override + public boolean shouldRun() + { + return false; + } + +} diff --git a/src/main/java/pokecube/core/ai/tasks/idle/AIHungry.java b/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java similarity index 88% rename from src/main/java/pokecube/core/ai/tasks/idle/AIHungry.java rename to src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java index 9a2ed3641a..4937428c6e 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/AIHungry.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java @@ -45,7 +45,7 @@ * what adds berries to their inventories based on which biome they are * currently in. */ -public class AIHungry extends IdleTask +public class HungerTask extends BaseIdleTask { public static final ResourceLocation FOODTAG = new ResourceLocation(PokecubeCore.MODID, "pokemob_food"); @@ -92,11 +92,11 @@ public static boolean hitThreshold(final float hungerValue, final float threshol static { - AIHungry.EATTASKS.add(new EatWater()); - AIHungry.EATTASKS.add(new EatRedstone()); - AIHungry.EATTASKS.add(new EatRock()); - AIHungry.EATTASKS.add(new EatPlant()); - AIHungry.EATTASKS.add(new EatFromChest()); + HungerTask.EATTASKS.add(new EatWater()); + HungerTask.EATTASKS.add(new EatRedstone()); + HungerTask.EATTASKS.add(new EatRock()); + HungerTask.EATTASKS.add(new EatPlant()); + HungerTask.EATTASKS.add(new EatFromChest()); } public static int TICKRATE = 20; @@ -108,11 +108,6 @@ public static boolean hitThreshold(final float hungerValue, final float threshol public static float DAMAGE = 0.3f; public static float DEATH = 0.0f; - // final World world; - final ItemEntity berry; - - final double distance; - int lastMessageTick1 = -1; int lastMessageTick2 = -1; @@ -127,11 +122,9 @@ public static boolean hitThreshold(final float hungerValue, final float threshol Vector3 v1 = Vector3.getNewVector(); Random rand; - public AIHungry(final IPokemob pokemob, final ItemEntity berry_, final double distance) + public HungerTask(final IPokemob pokemob) { super(pokemob); - this.berry = berry_; - this.distance = distance; this.moveSpeed = this.entity.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue() * 1.75; } @@ -175,9 +168,9 @@ protected boolean checkBait() */ protected boolean checkHunt() { - if (!this.hitThreshold(AIHungry.HUNTTHRESHOLD)) return false; + if (!this.hitThreshold(HungerTask.HUNTTHRESHOLD)) return false; if (this.pokemob.isPhototroph()) if (this.checkPhotoeat()) return true; - for (final IBlockEatTask task : AIHungry.EATTASKS) + for (final IBlockEatTask task : HungerTask.EATTASKS) if (task.tryEat(this.pokemob, this.blocks).test()) return true; // If none of these, then lets actually try to hunt. if (this.pokemob.getPokedexEntry().hasPrey() && this.entity.getBrain().hasMemory(MemoryModuleType.VISIBLE_MOBS)) @@ -203,7 +196,7 @@ protected boolean checkHunt() private boolean hitThreshold(final float threshold) { - return AIHungry.hitThreshold(this.hungerValue, threshold); + return HungerTask.hitThreshold(this.hungerValue, threshold); } /** @@ -215,14 +208,14 @@ private boolean hitThreshold(final float threshold) protected boolean checkInventory() { // Too hungry to check inventory. - if (this.hitThreshold(AIHungry.DEATH)) return false; + if (this.hitThreshold(HungerTask.DEATH)) return false; for (int i = 2; i < 7; i++) { final ItemStack stack = this.pokemob.getInventory().getStackInSlot(i); - if (ItemList.is(AIHungry.FOODTAG, stack)) + if (ItemList.is(HungerTask.FOODTAG, stack)) { - this.pokemob.eat(this.berry); + this.pokemob.eat(stack); stack.shrink(1); if (stack.isEmpty()) this.pokemob.getInventory().setInventorySlotContents(i, ItemStack.EMPTY); return true; @@ -267,7 +260,7 @@ protected boolean checkSleep() final ChunkCoordinate c = new ChunkCoordinate(this.v, this.entity.dimension.getId()); final boolean ownedSleepCheck = this.pokemob.getGeneralState(GeneralStates.TAMED) && !this.pokemob .getGeneralState(GeneralStates.STAYING); - if (this.sleepy && this.hitThreshold(AIHungry.EATTHRESHOLD) && !ownedSleepCheck) + if (this.sleepy && this.hitThreshold(HungerTask.EATTHRESHOLD) && !ownedSleepCheck) { if (!this.isGoodSleepingSpot(c)) this.setWalkTo(this.pokemob.getHome(), this.moveSpeed, 0); else if (this.entity.getNavigator().noPath()) @@ -313,11 +306,11 @@ public void run() if (Math.random() > 0.99) this.checkBait(); // Do not run this if not really hungry - if (!this.hitThreshold(AIHungry.EATTHRESHOLD)) return; + if (!this.hitThreshold(HungerTask.EATTHRESHOLD)) return; // Check if we are hunting or should be // Reset hunting status if we are not actually hungry - if (this.hitThreshold(AIHungry.HUNTTHRESHOLD)) this.checkHunt(); + if (this.hitThreshold(HungerTask.HUNTTHRESHOLD)) this.checkHunt(); final boolean hunting = this.pokemob.getCombatState(CombatStates.HUNTING); if (this.pokemob.getLogicState(LogicStates.SLEEPING) && !hunting) if (hunting) this.pokemob.setCombatState( @@ -327,13 +320,13 @@ public void run() @Override public boolean shouldRun() { - final int hungerTicks = AIHungry.TICKRATE; + final int hungerTicks = HungerTask.TICKRATE; // This can be set in configs to disable. if (hungerTicks < 0) return false; // Ensure we are not set to hunt if we shouldn't be - if (!this.hitThreshold(AIHungry.EATTHRESHOLD) && this.pokemob.getCombatState(CombatStates.HUNTING)) this.pokemob - .setCombatState(CombatStates.HUNTING, false); + if (!this.hitThreshold(HungerTask.EATTHRESHOLD) && this.pokemob.getCombatState(CombatStates.HUNTING)) + this.pokemob.setCombatState(CombatStates.HUNTING, false); // Do not run if the mob is in battle. if (this.pokemob.getCombatState(CombatStates.ANGRY)) return false; @@ -347,7 +340,7 @@ public boolean shouldRun() // Apply cooldowns and increment hunger. this.pokemob.setHungerCooldown(this.pokemob.getHungerCooldown() - hungerTicks); - if (!this.hitThreshold(AIHungry.HUNTTHRESHOLD)) this.pokemob.setHungerTime(this.pokemob.getHungerTime() + if (!this.hitThreshold(HungerTask.HUNTTHRESHOLD)) this.pokemob.setHungerTime(this.pokemob.getHungerTime() + hungerTicks); this.calculateHunger(); @@ -372,7 +365,7 @@ public boolean shouldRun() private void calculateHunger() { - this.hungerValue = AIHungry.calculateHunger(this.pokemob); + this.hungerValue = HungerTask.calculateHunger(this.pokemob); } @Override @@ -380,7 +373,7 @@ public void tick() { this.v.set(this.entity); - final int hungerTicks = AIHungry.TICKRATE; + final int hungerTicks = HungerTask.TICKRATE; // Check if we should go to sleep instead. this.checkSleep(); @@ -389,7 +382,7 @@ public void tick() final int cur = this.entity.ticksExisted / hungerTicks; final int tick = rand.nextInt(10); - if (!this.hitThreshold(AIHungry.EATTHRESHOLD)) return; + if (!this.hitThreshold(HungerTask.EATTHRESHOLD)) return; /* * Check the various hunger types if it is hunting. * And if so, refresh the hunger time counter. @@ -401,7 +394,7 @@ public void tick() // Check own inventory for berries to eat, and then if the mob is // allowed to, collect berries if none to eat. - if (this.hitThreshold(AIHungry.EATTHRESHOLD) && !this.checkInventory()) + if (this.hitThreshold(HungerTask.EATTHRESHOLD) && !this.checkInventory()) { // Pokemobs set to stay can collect berries, or wild ones, boolean tameCheck = this.pokemob.getGeneralState(GeneralStates.STAYING) || this.pokemob @@ -415,14 +408,14 @@ public void tick() // If they are allowed to, find the berries. // Only run this if we are getting close to hurt damage, mostly // to allow trying other food sources first. - if (tameCheck && this.hitThreshold(AIHungry.BERRYGEN)) new GenBerries(this.pokemob).run(this.world); + if (tameCheck && this.hitThreshold(HungerTask.BERRYGEN)) new GenBerries(this.pokemob).run(this.world); // Otherwise take damage. - if (this.hitThreshold(AIHungry.DAMAGE)) + if (this.hitThreshold(HungerTask.DAMAGE)) { - final float ratio = (AIHungry.DAMAGE - this.hungerValue) / AIHungry.DAMAGE; + final float ratio = (HungerTask.DAMAGE - this.hungerValue) / HungerTask.DAMAGE; final boolean dead = this.pokemob.getMaxHealth() * ratio > this.pokemob.getHealth() || this - .hitThreshold(AIHungry.DEATH); + .hitThreshold(HungerTask.DEATH); // Ensure it dies if it should. final float damage = dead ? this.pokemob.getMaxHealth() * 20 : this.pokemob.getMaxHealth() * ratio; if (damage >= 1 && ratio >= 0.0625 && this.entity.getHealth() > 0) diff --git a/src/main/java/pokecube/core/ai/tasks/idle/AIIdle.java b/src/main/java/pokecube/core/ai/tasks/idle/IdleWalkTask.java similarity index 92% rename from src/main/java/pokecube/core/ai/tasks/idle/AIIdle.java rename to src/main/java/pokecube/core/ai/tasks/idle/IdleWalkTask.java index ddc2dff686..d3147ff536 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/AIIdle.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/IdleWalkTask.java @@ -28,7 +28,7 @@ * This IAIRunnable makes the mobs randomly wander around if they have nothing * better to do. */ -public class AIIdle extends IdleTask +public class IdleWalkTask extends BaseIdleTask { public static int IDLETIMER = 1; @@ -61,11 +61,11 @@ public static Vector3 getRandomPointNear(final IBlockReader world, final IPokemo static { // Dont run if have a walk target - AIIdle.mems.put(MemoryModules.WALK_TARGET, MemoryModuleStatus.VALUE_ABSENT); + IdleWalkTask.mems.put(MemoryModules.WALK_TARGET, MemoryModuleStatus.VALUE_ABSENT); // Don't run if have a target location for moves - AIIdle.mems.put(MemoryModules.MOVE_TARGET, MemoryModuleStatus.VALUE_ABSENT); + IdleWalkTask.mems.put(MemoryModules.MOVE_TARGET, MemoryModuleStatus.VALUE_ABSENT); // Don't run if we have a path - AIIdle.mems.put(MemoryModules.PATH, MemoryModuleStatus.VALUE_ABSENT); + IdleWalkTask.mems.put(MemoryModules.PATH, MemoryModuleStatus.VALUE_ABSENT); } final PokedexEntry entry; @@ -79,9 +79,9 @@ public static Vector3 getRandomPointNear(final IBlockReader world, final IPokemo Vector3 v = Vector3.getNewVector(); Vector3 v1 = Vector3.getNewVector(); - public AIIdle(final IPokemob pokemob) + public IdleWalkTask(final IPokemob pokemob) { - super(pokemob, AIIdle.mems); + super(pokemob, IdleWalkTask.mems); this.entry = pokemob.getPokedexEntry(); this.speed = this.entity.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue(); } @@ -178,7 +178,7 @@ private boolean getLocation() } else { - final Vector3 v = AIIdle.getRandomPointNear(this.world, this.pokemob, this.v, distance); + final Vector3 v = IdleWalkTask.getRandomPointNear(this.world, this.pokemob, this.v, distance); if (v == null) return false; double diff = Math.max(this.pokemob.getPokedexEntry().length * this.pokemob.getSize(), this.pokemob .getPokedexEntry().width * this.pokemob.getSize()); @@ -215,13 +215,13 @@ public void run() public boolean shouldRun() { // Configs can set this to -1 to disable idle movement entirely. - if (AIIdle.IDLETIMER <= 0) return false; + if (IdleWalkTask.IDLETIMER <= 0) return false; // Not currently able to move. if (!TaskBase.canMove(this.pokemob)) return false; // Check a random number as well - if (this.entity.getRNG().nextInt(AIIdle.IDLETIMER) != 0) return false; + if (this.entity.getRNG().nextInt(IdleWalkTask.IDLETIMER) != 0) return false; // Wander disabled, so don't run. if (!this.pokemob.isRoutineEnabled(AIRoutine.WANDER)) return false; diff --git a/src/main/java/pokecube/core/ai/tasks/idle/AIMate.java b/src/main/java/pokecube/core/ai/tasks/idle/MateTask.java similarity index 71% rename from src/main/java/pokecube/core/ai/tasks/idle/AIMate.java rename to src/main/java/pokecube/core/ai/tasks/idle/MateTask.java index 4305def6b6..33b001edf3 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/AIMate.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/MateTask.java @@ -14,7 +14,7 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.brain.MemoryModules; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.interfaces.IMoveConstants.AIRoutine; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; @@ -26,13 +26,13 @@ * pokemobs. It finds the mates, initiates the fighting over a mate (if * applicable), then tells the mobs to breed if they should. */ -public class AIMate extends IdleTask +public class MateTask extends BaseIdleTask { private static final Map, MemoryModuleStatus> mems = Maps.newHashMap(); static { // only run this if we have mate targets. - AIMate.mems.put(MemoryModules.POSSIBLE_MATES, MemoryModuleStatus.VALUE_PRESENT); + MateTask.mems.put(MemoryModules.POSSIBLE_MATES, MemoryModuleStatus.VALUE_PRESENT); } int spawnBabyDelay = 0; @@ -41,9 +41,14 @@ public class AIMate extends IdleTask AgeableEntity mate; - public AIMate(final IPokemob mob) + AgeableEntity mobA = null; + AgeableEntity mobB = null; + + WalkTarget startSpot = null; + + public MateTask(final IPokemob mob) { - super(mob, AIMate.mems); + super(mob, MateTask.mems); } @Override @@ -51,7 +56,9 @@ public void reset() { this.spawnBabyDelay = 0; this.mate = null; - this.pokemob.setGeneralState(GeneralStates.MATING, false); + this.mobA = null; + this.mobB = null; + this.startSpot = null; BrainUtils.setMateTarget((AgeableEntity) this.entity, null); } @@ -69,20 +76,30 @@ public void run() this.mate = this.mates.get(0); return; } + if (this.startSpot != null) this.setWalkTo(this.startSpot); + + if (this.mobA != null && this.mobB != null && this.mates.contains(this.mobA) && this.mates.contains(this.mobB)) + return; + + // Flag them all as valid mates + for (final AgeableEntity mob : this.mates) + BrainUtils.setMateTarget(mob, (AgeableEntity) this.entity); // Battle between the first two on the list. - final AgeableEntity mobA = this.mates.get(0); - final AgeableEntity mobB = this.mates.get(1); + this.mobA = this.mates.get(0); + this.mobB = this.mates.get(1); - final IPokemob pokeA = CapabilityPokemob.getPokemobFor(mobA); - final IPokemob pokeB = CapabilityPokemob.getPokemobFor(mobB); + final IPokemob pokeA = CapabilityPokemob.getPokemobFor(this.mobA); + final IPokemob pokeB = CapabilityPokemob.getPokemobFor(this.mobB); if (pokeA != null) pokeA.setCombatState(CombatStates.MATEFIGHT, true); if (pokeB != null) pokeB.setCombatState(CombatStates.MATEFIGHT, true); // This fight should end when one gets below half health, which would // then be invalid for the next selection round of mating targets. - AIFindTarget.initiateCombat(mobA, mobB); + FindTargetsTask.initiateCombat(this.mobA, this.mobB); + + this.startSpot = new WalkTarget(this.entity.getPositionVec(), (float) this.pokemob.getMovementSpeed(), 0); } @Override @@ -94,6 +111,11 @@ public boolean shouldRun() if (this.pokemob.getSexe() == IPokemob.MALE || !this.pokemob.canBreed()) return false; if (this.pokemob.getCombatState(CombatStates.ANGRY) || BrainUtils.hasAttackTarget(this.entity)) return false; this.mate = BrainUtils.getMateTarget((AgeableEntity) this.entity); + if (this.mate != null && !this.mate.isAlive()) + { + BrainUtils.setMateTarget((AgeableEntity) this.entity, null); + this.mate = null; + } if (this.mate != null) return true; this.mates = BrainUtils.getMates((AgeableEntity) this.entity); if (this.mates != null) @@ -118,9 +140,13 @@ public void tick() this.mate.getBrain().setMemory(MemoryModules.WALK_TARGET, new WalkTarget(new EntityPosWrapper(this.entity), (float) this.pokemob.getMovementSpeed(), 0)); + BrainUtils.setMateTarget((AgeableEntity) this.entity, this.mate); + BrainUtils.setMateTarget(this.mate, (AgeableEntity) this.entity); + this.pokemob.setGeneralState(GeneralStates.MATING, true); - if (this.spawnBabyDelay++ < 50) return; final IPokemob other = CapabilityPokemob.getPokemobFor(this.mate); + if (other != null) other.setGeneralState(GeneralStates.MATING, true); + if (this.spawnBabyDelay++ < 100) return; if (other != null) this.pokemob.mateWith(other); this.reset(); other.resetLoveStatus(); diff --git a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatFromChest.java b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatFromChest.java index 50d2cf2854..d8aa64f30e 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatFromChest.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatFromChest.java @@ -9,7 +9,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.world.server.ServerWorld; import pokecube.core.ai.brain.sensors.NearBlocks.NearBlock; -import pokecube.core.ai.tasks.idle.AIHungry; +import pokecube.core.ai.tasks.idle.HungerTask; import pokecube.core.interfaces.IPokemob; import thut.api.item.ItemList; @@ -41,7 +41,7 @@ public EatResult eat(final IPokemob pokemob, final NearBlock block) for (int i1 = 0; i1 < container.getSizeInventory(); i1++) { final ItemStack stack = container.getStackInSlot(i1); - if (ItemList.is(AIHungry.FOODTAG, stack)) + if (ItemList.is(HungerTask.FOODTAG, stack)) { pokemob.eat(stack); stack.shrink(1); diff --git a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatPlant.java b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatPlant.java index 629f48261a..6120b8acf9 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatPlant.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatPlant.java @@ -10,7 +10,7 @@ import net.minecraft.world.server.ServerWorld; import pokecube.core.ai.brain.sensors.NearBlocks.NearBlock; import pokecube.core.ai.tasks.TaskBase.InventoryChange; -import pokecube.core.ai.tasks.utility.AIGatherStuff.ReplantTask; +import pokecube.core.ai.tasks.utility.GatherTask.ReplantTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.world.terrain.PokecubeTerrainChecker; diff --git a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRedstone.java b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRedstone.java index 29008ba7f7..6fe1a5c254 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRedstone.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRedstone.java @@ -23,7 +23,7 @@ public EatResult eat(final IPokemob pokemob, final NearBlock block) if (!pokemob.isElectrotroph()) return EatResult.NOEAT; final MobEntity entity = pokemob.getEntity(); - double diff = 1.5; + double diff = 3; diff = Math.max(diff, entity.getWidth()); final double dist = block.getPos().manhattanDistance(entity.getPosition()); this.setWalkTo(entity, block.getPos(), pokemob.getMovementSpeed(), 0); diff --git a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRock.java b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRock.java index 0761612247..7f998ef980 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRock.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/hunger/EatRock.java @@ -12,7 +12,7 @@ import net.minecraft.world.server.ServerWorld; import pokecube.core.ai.brain.sensors.NearBlocks.NearBlock; import pokecube.core.ai.tasks.TaskBase.InventoryChange; -import pokecube.core.ai.tasks.utility.AIGatherStuff.ReplantTask; +import pokecube.core.ai.tasks.utility.GatherTask.ReplantTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.world.terrain.PokecubeTerrainChecker; import thut.api.item.ItemList; diff --git a/src/main/java/pokecube/core/ai/tasks/utility/AIGatherStuff.java b/src/main/java/pokecube/core/ai/tasks/utility/GatherTask.java similarity index 94% rename from src/main/java/pokecube/core/ai/tasks/utility/AIGatherStuff.java rename to src/main/java/pokecube/core/ai/tasks/utility/GatherTask.java index 1095115258..f0c4bdcea8 100644 --- a/src/main/java/pokecube/core/ai/tasks/utility/AIGatherStuff.java +++ b/src/main/java/pokecube/core/ai/tasks/utility/GatherTask.java @@ -43,7 +43,7 @@ * berries. It requires an AIStoreStuff to have located a suitable storage * before it will run. */ -public class AIGatherStuff extends UtilTask +public class GatherTask extends UtilTask { /** * This manages the pokemobs replanting anything that they gather. @@ -130,11 +130,11 @@ public boolean run(final World world) // Matcher used to determine if a block is a fruit or crop to be picked. private static final Predicate harvestMatcher = input -> { - final boolean blacklisted = ItemList.is(AIGatherStuff.BLACKLIST, input); + final boolean blacklisted = ItemList.is(GatherTask.BLACKLIST, input); if (blacklisted) return false; final boolean fullCrop = input.getBlock() instanceof CropsBlock && input.get( CropsBlock.AGE) >= ((CropsBlock) input.getBlock()).getMaxAge(); - return fullCrop || ItemList.is(AIGatherStuff.HARVEST, input); + return fullCrop || ItemList.is(GatherTask.HARVEST, input); }; private static final Predicate deaditemmatcher = input -> !input.isAlive() || !input.addedToChunk @@ -153,14 +153,14 @@ public boolean run(final World world) int collectCooldown = 0; int pathCooldown = 0; - final AIStoreStuff storage; + final StoreTask storage; Vector3 seeking = Vector3.getNewVector(); Vector3 v = Vector3.getNewVector(); Vector3 v1 = Vector3.getNewVector(); - public AIGatherStuff(final IPokemob mob, final double distance, final AIStoreStuff storage) + public GatherTask(final IPokemob mob, final double distance, final StoreTask storage) { super(mob); this.distance = distance; @@ -169,8 +169,8 @@ public AIGatherStuff(final IPokemob mob, final double distance, final AIStoreStu private boolean hasStuff() { - if (this.targetItem != null && AIGatherStuff.deaditemmatcher.apply(this.targetItem)) this.targetItem = null; - if (this.targetBlock != null && !AIGatherStuff.harvestMatcher.apply(this.entity.getEntityWorld().getBlockState( + if (this.targetItem != null && GatherTask.deaditemmatcher.apply(this.targetItem)) this.targetItem = null; + if (this.targetBlock != null && !GatherTask.harvestMatcher.apply(this.entity.getEntityWorld().getBlockState( this.targetBlock.getPos()))) this.targetBlock = null; return this.targetItem != null || this.targetBlock != null; } @@ -187,7 +187,7 @@ private void findStuff() { // Check for items to possibly gather. for (final ItemEntity e : this.items) - if (!AIGatherStuff.deaditemmatcher.apply(e)) + if (!GatherTask.deaditemmatcher.apply(e)) { this.targetItem = e; return; @@ -200,7 +200,7 @@ private void findStuff() return; } // Nothing found, enter cooldown. - this.collectCooldown = AIGatherStuff.COOLDOWN_SEARCH; + this.collectCooldown = GatherTask.COOLDOWN_SEARCH; } private void gatherStuff() @@ -313,7 +313,7 @@ public boolean shouldRun() if (blocks != null) { this.blocks = Lists.newArrayList(blocks); - this.blocks.removeIf(b -> !AIGatherStuff.harvestMatcher.apply(b.getState())); + this.blocks.removeIf(b -> !GatherTask.harvestMatcher.apply(b.getState())); } // Only replace this if the new list is not null. if (items != null) this.items = items; diff --git a/src/main/java/pokecube/core/ai/tasks/utility/AIStoreStuff.java b/src/main/java/pokecube/core/ai/tasks/utility/StoreTask.java similarity index 95% rename from src/main/java/pokecube/core/ai/tasks/utility/AIStoreStuff.java rename to src/main/java/pokecube/core/ai/tasks/utility/StoreTask.java index a0540950c4..857779fca7 100644 --- a/src/main/java/pokecube/core/ai/tasks/utility/AIStoreStuff.java +++ b/src/main/java/pokecube/core/ai/tasks/utility/StoreTask.java @@ -23,7 +23,7 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.InvWrapper; -import pokecube.core.ai.tasks.idle.AIHungry; +import pokecube.core.ai.tasks.idle.HungerTask; import pokecube.core.interfaces.IMoveConstants.AIRoutine; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.pokemob.ai.GeneralStates; @@ -37,7 +37,7 @@ * allows using pokemobs for automatic harvesting and storage of berries and * dropped items. */ -public class AIStoreStuff extends UtilTask implements INBTSerializable, IInventoryChangedListener +public class StoreTask extends UtilTask implements INBTSerializable, IInventoryChangedListener { public static int COOLDOWN = 10; public static int MAXSIZE = 100; @@ -66,7 +66,7 @@ public class AIStoreStuff extends UtilTask implements INBTSerializable 9) { this.pathing = true; @@ -189,7 +189,7 @@ private boolean doBerryCheck(final IItemHandlerModifiable pokemobInv) // + " Pathing to Berries at " + this.berryLoc); return true; } - for (int i = 0; i < Math.min(berries.getSlots(), AIStoreStuff.MAXSIZE); i++) + for (int i = 0; i < Math.min(berries.getSlots(), StoreTask.MAXSIZE); i++) { final ItemStack stack = berries.getStackInSlot(i); if (stack.getItem() instanceof ItemBerry) @@ -243,7 +243,7 @@ private boolean doEmptyCheck(final IItemHandlerModifiable pokemobInv) inv: for (int slot = this.firstEmpty; slot < pokemobInv.getSlots(); slot++) if (pokemobInv.getStackInSlot(slot).isEmpty()) for (int i = start; i < Math.min(inventory.getSlots(), - AIStoreStuff.MAXSIZE); i++) + StoreTask.MAXSIZE); i++) { final ItemStack stack = inventory.getStackInSlot(i); if (!stack.isEmpty()) @@ -383,7 +383,7 @@ private IItemHandlerModifiable getInventory(final IBlockReader world, final Bloc private boolean hasItem(final ResourceLocation tag, final IItemHandlerModifiable inventory) { - for (int i = 0; i < Math.min(inventory.getSlots(), AIStoreStuff.MAXSIZE); i++) + for (int i = 0; i < Math.min(inventory.getSlots(), StoreTask.MAXSIZE); i++) { final ItemStack stack = inventory.getStackInSlot(i); if (stack.isEmpty()) continue; @@ -468,14 +468,14 @@ public void tick() boolean stuff = false; if (this.searchInventoryCooldown-- < 0) { - this.searchInventoryCooldown = AIStoreStuff.COOLDOWN; + this.searchInventoryCooldown = StoreTask.COOLDOWN; this.findBerryStorage(true); stuff = this.findItemStorage(true); - if (!stuff) this.searchInventoryCooldown = 50 * AIStoreStuff.COOLDOWN; + if (!stuff) this.searchInventoryCooldown = 50 * StoreTask.COOLDOWN; } final IItemHandlerModifiable itemhandler = new InvWrapper(this.pokemob.getInventory()); if (this.doBerryCheck(itemhandler) || this.doStorageCheck(itemhandler) || this.doEmptyCheck(itemhandler)) this.doStorageCooldown = 5; - else this.doStorageCooldown = 10 * AIStoreStuff.COOLDOWN; + else this.doStorageCooldown = 10 * StoreTask.COOLDOWN; } } diff --git a/src/main/java/pokecube/core/ai/tasks/utility/AIUseMove.java b/src/main/java/pokecube/core/ai/tasks/utility/UseMoveTask.java similarity index 96% rename from src/main/java/pokecube/core/ai/tasks/utility/AIUseMove.java rename to src/main/java/pokecube/core/ai/tasks/utility/UseMoveTask.java index ac6665a70c..b12bfc15b9 100644 --- a/src/main/java/pokecube/core/ai/tasks/utility/AIUseMove.java +++ b/src/main/java/pokecube/core/ai/tasks/utility/UseMoveTask.java @@ -25,13 +25,13 @@ import pokecube.core.moves.MovesUtils; import thut.api.maths.Vector3; -public class AIUseMove extends UtilTask +public class UseMoveTask extends UtilTask { private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); static { - AIUseMove.MEMS.put(MemoryModules.MOVE_TARGET, MemoryModuleStatus.VALUE_PRESENT); + UseMoveTask.MEMS.put(MemoryModules.MOVE_TARGET, MemoryModuleStatus.VALUE_PRESENT); } private boolean running = false; @@ -43,9 +43,9 @@ public class AIUseMove extends UtilTask double speed; - public AIUseMove(final IPokemob pokemob) + public UseMoveTask(final IPokemob pokemob) { - super(pokemob, AIUseMove.MEMS); + super(pokemob, UseMoveTask.MEMS); } @Override diff --git a/src/main/java/pokecube/core/client/gui/pokemob/GuiPokemobStorage.java b/src/main/java/pokecube/core/client/gui/pokemob/GuiPokemobStorage.java index b0f8848b12..a8b2951b0b 100644 --- a/src/main/java/pokecube/core/client/gui/pokemob/GuiPokemobStorage.java +++ b/src/main/java/pokecube/core/client/gui/pokemob/GuiPokemobStorage.java @@ -16,7 +16,7 @@ import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TranslationTextComponent; -import pokecube.core.ai.tasks.utility.AIStoreStuff; +import pokecube.core.ai.tasks.utility.StoreTask; import pokecube.core.entity.pokemobs.ContainerPokemob; import pokecube.core.interfaces.IPokemob; import pokecube.core.network.pokemobs.PacketPokemobGui; @@ -34,7 +34,7 @@ public class GuiPokemobStorage extends GuiPokemobBase TextFieldWidget storage; TextFieldWidget storageFace; TextFieldWidget empty; - AIStoreStuff ai; + StoreTask ai; TextFieldWidget emptyFace; List textBoxes = Lists.newArrayList(); @@ -45,7 +45,7 @@ public GuiPokemobStorage(final ContainerPokemob container, final PlayerInventory this.playerInventory = playerInv; this.pokeInventory = this.pokemob.getInventory(); this.entity = this.pokemob.getEntity(); - this.ai = new AIStoreStuff(this.pokemob); + this.ai = new StoreTask(this.pokemob); final CompoundNBT tag = container.data.readCompoundTag(); this.ai.deserializeNBT(tag); container.setMode(PacketPokemobGui.STORAGE); diff --git a/src/main/java/pokecube/core/database/PokedexEntry.java b/src/main/java/pokecube/core/database/PokedexEntry.java index e0387981d3..8b869a3dbe 100644 --- a/src/main/java/pokecube/core/database/PokedexEntry.java +++ b/src/main/java/pokecube/core/database/PokedexEntry.java @@ -45,7 +45,7 @@ import net.minecraftforge.fml.ModLoadingContext; import pokecube.core.PokecubeCore; import pokecube.core.PokecubeItems; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.PokedexEntryLoader.Action; import pokecube.core.database.PokedexEntryLoader.DefaultFormeHolder; import pokecube.core.database.PokedexEntryLoader.Drop; @@ -526,7 +526,7 @@ public boolean applyInteraction(final PlayerEntity player, final IPokemob pokemo if (consumeInput) held.shrink(1); if (held.isEmpty()) player.inventory.setInventorySlotContents(player.inventory.currentItem, result); else if (!player.inventory.addItemStackToInventory(result)) player.dropItem(result, false); - if (player != pokemob.getOwner()) AIFindTarget.initiateCombat(entity, player); + if (player != pokemob.getOwner()) FindTargetsTask.initiateCombat(entity, player); return true; } diff --git a/src/main/java/pokecube/core/handlers/Config.java b/src/main/java/pokecube/core/handlers/Config.java index a3a42c6234..7df07fa71b 100644 --- a/src/main/java/pokecube/core/handlers/Config.java +++ b/src/main/java/pokecube/core/handlers/Config.java @@ -13,8 +13,8 @@ import pokecube.core.PokecubeCore; import pokecube.core.PokecubeItems; import pokecube.core.ai.logic.LogicMountedControl; -import pokecube.core.ai.tasks.idle.AIHungry; -import pokecube.core.ai.tasks.idle.AIIdle; +import pokecube.core.ai.tasks.idle.HungerTask; +import pokecube.core.ai.tasks.idle.IdleWalkTask; import pokecube.core.database.Database.EnumDatabase; import pokecube.core.database.recipes.XMLRecipeHandler; import pokecube.core.database.rewards.XMLRewardsHandler; @@ -665,8 +665,8 @@ public void onUpdated() if (this.idleTickRate == 0) this.idleTickRate = 1; if (this.hungerTickRate == 0) this.hungerTickRate = 1; - AIIdle.IDLETIMER = this.idleTickRate; - AIHungry.TICKRATE = this.hungerTickRate; + IdleWalkTask.IDLETIMER = this.idleTickRate; + HungerTask.TICKRATE = this.hungerTickRate; // TODO Init secret bases. // DimensionSecretBase.init(baseSizeFunction); diff --git a/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java b/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java index 9a9283a230..ab3d53a697 100644 --- a/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java +++ b/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java @@ -49,7 +49,7 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.logic.Logic; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.Pokedex; import pokecube.core.database.PokedexEntry; import pokecube.core.database.PokedexEntry.EvolutionData; @@ -179,9 +179,9 @@ else if (giveExp) final Entity targetOwner = attackedMob.getOwner(); attacker.displayMessageToOwner(new TranslationTextComponent("pokemob.action.faint.enemy", attackedMob .getDisplayName())); - if (targetOwner instanceof PlayerEntity && attacker.getOwner() != targetOwner) AIFindTarget.initiateCombat( + if (targetOwner instanceof PlayerEntity && attacker.getOwner() != targetOwner) FindTargetsTask.initiateCombat( pokemob, (LivingEntity) targetOwner); - else AIFindTarget.deagro(pokemob); + else FindTargetsTask.deagro(pokemob); if (attacker.getPokedexEntry().isFood(attackedMob.getPokedexEntry()) && attacker.getCombatState( CombatStates.HUNTING)) { diff --git a/src/main/java/pokecube/core/handlers/events/SpawnHandler.java b/src/main/java/pokecube/core/handlers/events/SpawnHandler.java index e3cae2a218..35a3929735 100644 --- a/src/main/java/pokecube/core/handlers/events/SpawnHandler.java +++ b/src/main/java/pokecube/core/handlers/events/SpawnHandler.java @@ -28,10 +28,14 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.Difficulty; import net.minecraft.world.IWorld; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunk; import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.Heightmap; import net.minecraft.world.gen.Heightmap.Type; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.spawner.AbstractSpawner; @@ -142,13 +146,11 @@ public boolean equals(final Object obj) || input == BiomeType.NONE.getType(); }; - private static Vector3 vec1 = Vector3.getNewVector(); - private static Vector3 temp = Vector3.getNewVector(); - public static double MAX_DENSITY = 1; - public static int MAXNUM = 10; - public static boolean lvlCap = false; - public static boolean expFunction = false; - public static int capLevel = 50; + public static double MAX_DENSITY = 1; + public static int MAXNUM = 10; + public static boolean lvlCap = false; + public static boolean expFunction = false; + public static int capLevel = 50; public static boolean addForbiddenSpawningCoord(final BlockPos pos, final int dimensionId, final int distance) { @@ -266,9 +268,9 @@ else if (overrideLevel == -1) level = SpawnHandler.getSpawnLevel(world, Vector3. final double dt = (System.nanoTime() - time) / 10e3D; if (PokecubeMod.debug && dt > 100) { - SpawnHandler.temp.set(SpawnHandler.temp.set(posX, posY, posZ).getPos()); + final Vector3 v = Vector3.getNewVector().set(posX, posY, posZ); final String toLog = "location: %1$s took: %2$s\u00B5s to spawn Init for %3$s"; - PokecubeCore.LOGGER.info(String.format(toLog, SpawnHandler.temp, dt, pokemob.getDisplayName() + PokecubeCore.LOGGER.info(String.format(toLog, v.getPos(), dt, pokemob.getDisplayName() .getFormattedText())); } return pokemob.getEntity(); @@ -303,33 +305,50 @@ public static ForbidReason getNoSpawnReason(final IWorld world, final int x, fin return entry == null ? ForbidReason.NONE : entry.reason; } - public static Vector3 getRandomPointNear(final Entity player, final int range) + private static BlockPos getRandomHeight(final World worldIn, final Chunk chunk, final int yCenter, final int dy) { - if (player == null) return null; - final World world = player.getEntityWorld(); - final Vector3 v = SpawnHandler.vec1.set(player); - - final Random rand = new Random(); - // SElect random gaussians from here. - double x = rand.nextGaussian() * range; - double z = rand.nextGaussian() * range; - - // Cap x and z to distance. - if (Math.abs(x) > range) x = Math.signum(x) * range; - if (Math.abs(z) > range) z = Math.signum(z) * range; + final ChunkPos chunkpos = chunk.getPos(); + final int x = chunkpos.getXStart() + worldIn.rand.nextInt(16); + final int z = chunkpos.getZStart() + worldIn.rand.nextInt(16); + int y = yCenter - dy + worldIn.rand.nextInt(2 * dy + 1); + final int top = chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE, x, z) + 1; + if (y > top) y = top; + return new BlockPos(x, y, z); + } - // Don't select distances too far up/down from current. - final double y = Math.min(Math.max(-5, rand.nextGaussian() * 10), 10); - v.addTo(x, y, z); - v.set(v.getPos()).addTo(0.5, 0.5, 0.5); + public static Vector3 getRandomPointNear(final ServerWorld world, final Vector3 pos, final int range) + { + // Lets try a few times + int n = 10; + while (n-- > 0) + { + int dx = world.getRandom().nextInt(range); + int dz = world.getRandom().nextInt(range); + dx *= world.getRandom().nextBoolean() ? 1 : -1; + dz *= world.getRandom().nextBoolean() ? 1 : -1; + final int dy = 10; + final Vector3 vec = pos.add(dx, 0, dz); + final IChunk chunk = world.getChunk(vec.getPos()); + if (!(chunk instanceof Chunk)) continue; + final BlockPos blockpos = SpawnHandler.getRandomHeight(world, (Chunk) chunk, vec.intY(), dy); + final int j = blockpos.getX(); + final int k = blockpos.getY(); + final int l = blockpos.getZ(); + vec.set(j + 0.5, k, l + 0.5); + if (vec.distanceTo(pos) > range) continue; + final BlockState blockstate = world.getBlockState(blockpos); + if (blockstate.isNormalCube(world, blockpos)) continue; + return vec; + } + return null; - // Don't select unloaded areas. - if (!TerrainManager.isAreaLoaded(world, v, 8)) return null; + } - // Find surface - final Vector3 temp1 = SpawnHandler.getSpawnSurface(world, v, 10); - if (!(temp1.isClearOfBlocks(world) || temp1.offset(Direction.UP).isClearOfBlocks(world))) return null; - return temp1; + public static Vector3 getRandomPointNear(final Entity player, final int range) + { + if (player == null || !(player.getEntityWorld() instanceof ServerWorld)) return null; + return SpawnHandler.getRandomPointNear((ServerWorld) player.getEntityWorld(), Vector3.getNewVector().set( + player), range); } public static PokedexEntry getSpawnForLoc(final World world, final Vector3 pos) @@ -383,7 +402,7 @@ public static Vector3 getSpawnSurface(final World world, final Vector3 loc, fina { int tries = 0; BlockState state; - while (tries++ <= range) + if (loc.y > 0) while (tries++ <= range) { state = loc.getBlockState(world); if (state.getMaterial() == Material.WATER) return loc.copy(); @@ -496,7 +515,7 @@ public static void makeMeteor(final World world, final Vector3 location, final f private static int parse(final IWorld world, final Vector3 location) { - final Vector3 spawn = SpawnHandler.temp.set(world.getWorld().getSpawnPoint()); + final Vector3 spawn = Vector3.getNewVector().set(world.getWorld().getSpawnPoint()); final DimensionType type = world.getDimension().getType(); final JEP toUse = SpawnHandler.getParser(type); final Function function = SpawnHandler.getFunction(type); @@ -600,13 +619,6 @@ public static boolean removeForbiddenSpawningCoord(final int x, final int y, fin } public JEP parser = new JEP(); - Vector3 v = Vector3.getNewVector(); - - Vector3 v1 = Vector3.getNewVector(); - - Vector3 v2 = Vector3.getNewVector(); - - Vector3 v3 = Vector3.getNewVector(); public SpawnHandler() { @@ -626,14 +638,16 @@ public void doMeteor(final ServerWorld world) final Entity player = players.get(rand.nextInt(players.size())); final int dx = rand.nextInt(200) - 100; final int dz = rand.nextInt(200) - 100; - final Vector3 v = this.v.set(player).add(dx, 0, dz); + final Vector3 v = Vector3.getNewVector(); + final Vector3 v1 = Vector3.getNewVector(); + v.set(player).add(dx, 0, dz); final Vector4 loc = new Vector4(player); loc.x += dx; loc.z += dz; loc.y = world.getHeight(Type.WORLD_SURFACE, (int) loc.x, (int) loc.z); if (PokecubeSerializer.getInstance().canMeteorLand(loc, world)) { - final Vector3 direction = this.v1.set(rand.nextGaussian() / 2, -1, rand.nextGaussian() / 2); + final Vector3 direction = v1.set(rand.nextGaussian() / 2, -1, rand.nextGaussian() / 2); v.set(loc.x, loc.y, loc.z); final Vector3 location = Vector3.getNextSurfacePoint(world, v, direction, 255); if (location != null) @@ -647,12 +661,7 @@ public void doMeteor(final ServerWorld world) } } - public int doSpawnForLocation(final World world, final Vector3 v) - { - return this.doSpawnForLocation(world, v, true); - } - - public int doSpawnForLocation(final World world, final Vector3 v, final boolean checkPlayers) + public int doSpawnForLocation(final ServerWorld world, final Vector3 v) { int ret = 0; int num = 0; @@ -669,18 +678,18 @@ public int doSpawnForLocation(final World world, final Vector3 v, final boolean double dt = (System.nanoTime() - time) / 10e3D; if (PokecubeMod.debug && dt > 500) { - SpawnHandler.temp.set(v.getPos()); + final Vector3 debug = Vector3.getNewVector().set(v.getPos()); final String toLog = "location: %1$s took: %2$s\u00B5s to find a valid spawn and location"; - PokecubeCore.LOGGER.info(String.format(toLog, SpawnHandler.temp, dt)); + PokecubeCore.LOGGER.info(String.format(toLog, debug.getPos(), dt)); } time = System.nanoTime(); - ret += num = this.doSpawnForType(world, v, dbe, this.parser, t, checkPlayers); + ret += num = this.doSpawnForType(world, v, dbe, this.parser, t); dt = (System.nanoTime() - time) / 10e3D; if (PokecubeMod.debug && dt > 500) { - SpawnHandler.temp.set(v.getPos()); + final Vector3 debug = Vector3.getNewVector().set(v.getPos()); final String toLog = "location: %1$s took: %2$s\u00B5s to find a valid spawn for %3$s %4$s"; - PokecubeCore.LOGGER.info(String.format(toLog, SpawnHandler.temp, dt, num, dbe)); + PokecubeCore.LOGGER.info(String.format(toLog, debug.getPos(), dt, num, dbe)); } return ret; } @@ -690,43 +699,65 @@ public int doSpawnForLocation(final World world, final Vector3 v, final boolean * * @param player * @param world + * @param maxSpawnRadius * @return number of mobs spawned. */ - public void doSpawnForPlayer(final PlayerEntity player, final World world) + public void doSpawnForPlayer(final PlayerEntity player, final ServerWorld world, final int minRadius, + final int maxRadius) + { + final Vector3 v = Vector3.getNewVector(); + v.set(player); + this.doSpawnForPoint(v, world, minRadius, maxRadius); + return; + } + + /** + * Attempts to spawn mobs near the player. + * + * @param player + * @param world + * @param maxSpawnRadius + * @return number of mobs spawned. + */ + public void doSpawnForPoint(final Vector3 v, final ServerWorld world, final int minRadius, final int maxRadius) { long time = System.nanoTime(); - final int radius = PokecubeCore.getConfig().maxSpawnRadius; - this.v.set(player); - if (!TerrainManager.isAreaLoaded(world, this.v, radius)) return; - if (!Tools.isAnyPlayerInRange(radius, 10, world, this.v)) return; + if (!TerrainManager.isAreaLoaded(world, v, maxRadius)) return; final int height = world.getActualHeight(); - final AxisAlignedBB box = this.v.getAABB().grow(radius, Math.max(height, radius), radius); + // This lookup box uses configs rather than the passed in radius. + final int boxR = PokecubeCore.getConfig().maxSpawnRadius; + final AxisAlignedBB box = v.getAABB().grow(boxR, Math.max(height, boxR), boxR); int num = PokemobTracker.countPokemobs(world, box); if (num > SpawnHandler.MAX_DENSITY * SpawnHandler.MAXNUM) return; - final Vector3 v = SpawnHandler.getRandomPointNear(player, PokecubeCore.getConfig().maxSpawnRadius); - double dt = (System.nanoTime() - time) / 1000d; - if (PokecubeMod.debug && dt > 100) PokecubeCore.LOGGER.info("Location Find took " + dt); - if (v == null) return; + final Vector3 v1 = SpawnHandler.getRandomPointNear(world, v, maxRadius); + double dt = (System.nanoTime() - time) / 1e3D; + if (PokecubeMod.debug && dt > 100) PokecubeCore.LOGGER.debug("Location Find took " + dt); + if (v1 == null) return; + if (v.distanceTo(v1) < minRadius) return; time = System.nanoTime(); - num = this.doSpawnForLocation(world, v); - dt = (System.nanoTime() - time) / 10e3D; - if (PokecubeMod.debug && dt > 100) PokecubeCore.LOGGER.info(dt + "\u00B5" + "s for player " + player - .getDisplayName().getUnformattedComponentText() + " at " + v + ", spawned " + num); + num = this.doSpawnForLocation(world, v1); + dt = (System.nanoTime() - time) / 1e3D; + if (PokecubeMod.debug && dt > 100) PokecubeCore.LOGGER.debug(dt + "\u00B5" + "s for " + v + ", spawned " + + num); return; } - private int doSpawnForType(final World world, final Vector3 loc, final PokedexEntry dbe, final JEP parser, - final TerrainSegment t, final boolean checkPlayers) + private int doSpawnForType(final ServerWorld world, final Vector3 loc, final PokedexEntry dbe, final JEP parser, + final TerrainSegment t) { final SpawnData entry = dbe.getSpawnData(); + final Vector3 v = Vector3.getNewVector(); + final Vector3 v1 = Vector3.getNewVector(); + final Vector3 v2 = Vector3.getNewVector(); + final Vector3 v3 = Vector3.getNewVector(); int totalSpawnCount = 0; - final Vector3 offset = this.v1.clear(); - final Vector3 point = this.v2.clear(); + final Vector3 offset = v1.clear(); + final Vector3 point = v2.clear(); SpawnHandler.refreshTerrain(loc, world, false); final SpawnBiomeMatcher matcher = entry.getMatcher(world, loc); if (matcher == null) return 0; - final byte distGroupZone = 6; + final byte distGroupZone = 4; final Random rand = new Random(); final int n = Math.max(entry.getMax(matcher) - entry.getMin(matcher), 1); final int spawnNumber = entry.getMin(matcher) + rand.nextInt(n); @@ -735,8 +766,16 @@ private int doSpawnForType(final World world, final Vector3 loc, final PokedexEn { offset.set(rand.nextInt(distGroupZone) - rand.nextInt(distGroupZone), rand.nextInt(1) - rand.nextInt(1), rand.nextInt(distGroupZone) - rand.nextInt(distGroupZone)); - this.v.set(loc); - point.set(this.v.addTo(offset)); + final Vector3 dr = SpawnHandler.getRandomPointNear(world, loc, distGroupZone); + if (dr != null) + { + + } + System.out.println(dr); + + v.set(loc); + point.set(v.addTo(offset)); + if (!SpawnHandler.isPointValidForSpawn(world, point, dbe)) continue; final float x = (float) point.x; @@ -747,11 +786,6 @@ private int doSpawnForType(final World world, final Vector3 loc, final PokedexEn final float var29 = y - world.getSpawnPoint().getY(); final float var30 = z - world.getSpawnPoint().getZ(); final float distFromSpawnPoint = var28 * var28 + var29 * var29 + var30 * var30; - - if (!SpawnHandler.checkNoSpawnerInArea(world, point.intX(), point.intY(), point.intZ())) continue; - final float dist = PokecubeCore.getConfig().minSpawnRadius; - final boolean player = checkPlayers && Tools.isAnyPlayerInRange(dist, dist, world, point); - if (player) continue; if (distFromSpawnPoint >= 256.0F) { MobEntity entity = null; @@ -767,22 +801,22 @@ private int doSpawnForType(final World world, final Vector3 loc, final PokedexEn entity.setLocationAndAngles(x, y, z, world.rand.nextFloat() * 360.0F, 0.0F); if (entity.canSpawn(world, SpawnReason.NATURAL)) { - if ((entity = SpawnHandler.creatureSpecificInit(entity, world, x, y, z, this.v3.set(entity), + if ((entity = SpawnHandler.creatureSpecificInit(entity, world, x, y, z, v3.set(entity), entry.getLevel(matcher), entry.getVariance(matcher))) != null) { final IPokemob pokemob = CapabilityPokemob.getPokemobFor(entity); if (!event.getSpawnArgs().isEmpty()) { final String[] args = event.getSpawnArgs().split(" "); - Pokemake.setToArgs(args, pokemob, 0, this.v, false); + Pokemake.setToArgs(args, pokemob, 0, v, false); } else if (matcher.spawnRule.values.containsKey(SpawnBiomeMatcher.SPAWNCOMMAND)) { final String[] args = matcher.spawnRule.values.get(SpawnBiomeMatcher.SPAWNCOMMAND) .split(" "); - Pokemake.setToArgs(args, pokemob, 0, this.v, false); + Pokemake.setToArgs(args, pokemob, 0, v, false); } - final SpawnEvent.Post evt = new SpawnEvent.Post(dbe, this.v3, world, pokemob); + final SpawnEvent.Post evt = new SpawnEvent.Post(dbe, v3, world, pokemob); PokecubeCore.POKEMOB_BUS.post(evt); world.addEntity(entity); totalSpawnCount++; @@ -814,7 +848,8 @@ public void spawn(final ServerWorld world) for (final ServerPlayerEntity player : players) { if (player.dimension != world.getDimension().getType()) continue; - this.doSpawnForPlayer(player, world); + this.doSpawnForPlayer(player, world, PokecubeCore.getConfig().minSpawnRadius, PokecubeCore + .getConfig().maxSpawnRadius); } } diff --git a/src/main/java/pokecube/core/interfaces/IPokemob.java b/src/main/java/pokecube/core/interfaces/IPokemob.java index 55f1cff853..4aae6b8c71 100644 --- a/src/main/java/pokecube/core/interfaces/IPokemob.java +++ b/src/main/java/pokecube/core/interfaces/IPokemob.java @@ -475,6 +475,7 @@ default void setHeldItem(final ItemStack stack) */ default IPokemob spawnInit() { + this.resetLoveStatus(); return this.spawnInit(null); } diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobAI.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobAI.java index a943166a2e..fb7c178990 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobAI.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobAI.java @@ -36,6 +36,7 @@ public float getDirectionPitch() @Override public boolean getGeneralState(final GeneralStates state) { + if (state == GeneralStates.TAMED) return this.getOwnerId() != null; if (this.getEntity().getEntityWorld().isRemote) this.cachedGeneralState = this.dataSync().get( this.params.GENERALSTATESDW); return (this.cachedGeneralState & state.getMask()) != 0; diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java index 8d249a202a..a9473e1346 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java @@ -12,7 +12,7 @@ import net.minecraft.util.text.ITextComponent; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.PokedexEntry; import pokecube.core.database.moves.MoveEntry; import pokecube.core.interfaces.IMoveConstants; @@ -74,7 +74,7 @@ public void executeMove(final Entity target, Vector3 targetLocation, final float if (target instanceof MobEntity) { final MobEntity t = (MobEntity) target; - if (BrainUtils.getAttackTarget(t) != this.getEntity()) AIFindTarget.initiateCombat(t, this.getEntity()); + if (BrainUtils.getAttackTarget(t) != this.getEntity()) FindTargetsTask.initiateCombat(t, this.getEntity()); } if (target instanceof LivingEntity) if (((LivingEntity) target).getRevengeTarget() != this.getEntity()) { diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java index 772bad103c..7bc907ec80 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java @@ -25,7 +25,7 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.logic.LogicMountedControl; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.client.gui.GuiInfoMessages; import pokecube.core.database.PokedexEntryLoader.SpawnRule; import pokecube.core.database.abilities.AbilityManager; @@ -346,7 +346,7 @@ else if (this.getOwnerId() != null) final IPokemob targetMob = CapabilityPokemob.getPokemobFor(targ); if (targetMob != null) { - AIFindTarget.initiateCombat(targetMob.getEntity(), this.getOwner()); + FindTargetsTask.initiateCombat(targetMob.getEntity(), this.getOwner()); if (PokecubeMod.debug) PokecubeCore.LOGGER.info("Swapping agro to cowardly owner!"); } else targ.setRevengeTarget(this.getOwner()); diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java index e21b32f30b..c1fc41de98 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java @@ -12,8 +12,8 @@ import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSidedProvider; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.AIFindTarget; -import pokecube.core.ai.tasks.idle.AIHungry; +import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.tasks.idle.HungerTask; import pokecube.core.database.PokedexEntry; import pokecube.core.events.EggEvent; import pokecube.core.handlers.playerdata.advancements.triggers.Triggers; @@ -157,8 +157,8 @@ protected void mate(final IBreedingMob male) mate.setHungerTime(mate.getHungerTime() + hungerValue); this.setHungerTime(this.getHungerTime() + hungerValue); mate.resetLoveStatus(); - AIFindTarget.deagro(this.getEntity()); - AIFindTarget.deagro(mate.getEntity()); + FindTargetsTask.deagro(this.getEntity()); + FindTargetsTask.deagro(mate.getEntity()); this.lay(mate); this.resetLoveStatus(); } @@ -209,8 +209,8 @@ public boolean canBreed() PokedexEntry thisEntry = this.getPokedexEntry(); if (thisEntry.isMega) thisEntry = this.getMegaBase(); if (!thisEntry.breeds) return false; - final float hunger = AIHungry.calculateHunger(this); - if (AIHungry.hitThreshold(hunger, AIHungry.MATERESET)) return false; + final float hunger = HungerTask.calculateHunger(this); + if (HungerTask.hitThreshold(hunger, HungerTask.MATERESET)) return false; return this.loveTimer >= 0; } diff --git a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java index ea7de01a48..eb9413329c 100644 --- a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java +++ b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java @@ -8,7 +8,7 @@ import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.events.pokemob.combat.CommandAttackEvent; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.Move_Base; @@ -62,7 +62,7 @@ public void handleCommand(final IPokemob pokemob) .getDisplayName(), target.getDisplayName(), new TranslationTextComponent(MovesUtils .getUnlocalizedMove(move.getName()))); if (this.fromOwner()) pokemob.displayMessageToOwner(mess); - AIFindTarget.initiateCombat(pokemob.getEntity(), (LivingEntity) target); + FindTargetsTask.initiateCombat(pokemob.getEntity(), (LivingEntity) target); } } } diff --git a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackLocationHandler.java b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackLocationHandler.java index 9296876581..6b18e4cdef 100644 --- a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackLocationHandler.java +++ b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackLocationHandler.java @@ -5,7 +5,7 @@ import net.minecraft.util.text.TranslationTextComponent; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.idle.AIHungry; +import pokecube.core.ai.tasks.idle.HungerTask; import pokecube.core.events.pokemob.combat.CommandAttackEvent; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.Move_Base; @@ -41,10 +41,10 @@ public void handleCommand(final IPokemob pokemob) new TranslationTextComponent(MovesUtils.getUnlocalizedMove(move.getName()))); if (this.fromOwner()) pokemob.displayMessageToOwner(mess); - final float value = AIHungry.calculateHunger(pokemob); + final float value = HungerTask.calculateHunger(pokemob); // If too hungry, send message about that. - if (AIHungry.hitThreshold(value, AIHungry.HUNTTHRESHOLD)) + if (HungerTask.hitThreshold(value, HungerTask.HUNTTHRESHOLD)) { mess = new TranslationTextComponent("pokemob.action.hungry", pokemob.getDisplayName()); if (this.fromOwner()) pokemob.displayMessageToOwner(mess); diff --git a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/MoveToHandler.java b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/MoveToHandler.java index 342d3eaa5a..61ff71e589 100644 --- a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/MoveToHandler.java +++ b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/MoveToHandler.java @@ -1,7 +1,8 @@ package pokecube.core.interfaces.pokemob.commandhandlers; import io.netty.buffer.ByteBuf; -import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.brain.memory.WalkTarget; +import pokecube.core.ai.brain.MemoryModules; import pokecube.core.interfaces.IPokemob; import pokecube.core.network.pokemobs.PacketCommand.DefaultHandler; import thut.api.maths.Vector3; @@ -24,10 +25,9 @@ public MoveToHandler(final Vector3 location, final Float speed) @Override public void handleCommand(final IPokemob pokemob) throws Exception { - this.speed = (float) Math.min(this.speed, pokemob.getEntity().getAttribute( - SharedMonsterAttributes.MOVEMENT_SPEED).getValue()); - pokemob.getEntity().getNavigator().setPath(pokemob.getEntity().getNavigator().func_225466_a(this.location.x, - this.location.y, this.location.z, 0), this.speed); + this.speed = (float) Math.min(this.speed, pokemob.getMovementSpeed()); + pokemob.getEntity().getBrain().setMemory(MemoryModules.WALK_TARGET, new WalkTarget(this.location.toVec3d(), + this.speed, 0)); } @Override diff --git a/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java b/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java index ff3720e31a..29aec918be 100644 --- a/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java +++ b/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java @@ -42,7 +42,7 @@ import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; @@ -202,7 +202,7 @@ protected void onImpact(final RayTraceResult result) if (PokecubeManager.isFilled(this.getItem())) { final LivingEntity sent = SendOutManager.sendOut(this, true); - if (sent instanceof MobEntity && hit.getEntity() instanceof LivingEntity) AIFindTarget.initiateCombat( + if (sent instanceof MobEntity && hit.getEntity() instanceof LivingEntity) FindTargetsTask.initiateCombat( (MobEntity) sent, (LivingEntity) hit.getEntity()); } diff --git a/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java b/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java index e769076e54..85a39e94b4 100644 --- a/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java +++ b/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java @@ -16,7 +16,7 @@ import net.minecraftforge.eventbus.api.Event.Result; import pokecube.core.PokecubeCore; import pokecube.core.PokecubeItems; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.abilities.AbilityManager; import pokecube.core.events.pokemob.CaptureEvent; import pokecube.core.events.pokemob.CaptureEvent.Pre; @@ -161,7 +161,7 @@ public static void captureFailed(final EntityPokecubeBase cube) ((PlayerEntity) cube.shootingEntity).sendMessage(mess); } } - if (mob instanceof MobEntity && cube.shootingEntity != null) AIFindTarget.initiateCombat((MobEntity) mob, + if (mob instanceof MobEntity && cube.shootingEntity != null) FindTargetsTask.initiateCombat((MobEntity) mob, cube.shootingEntity); } diff --git a/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java b/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java index 1c063de04b..3a7aba00e9 100644 --- a/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java +++ b/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java @@ -21,7 +21,7 @@ import net.minecraftforge.common.MinecraftForge; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.PokedexEntry; import pokecube.core.events.EggEvent; import pokecube.core.interfaces.IPokemob; @@ -73,7 +73,7 @@ public boolean attackEntityFrom(final DamageSource source, final float damage) final ItemStack itemstack = this.getHeldItemMainhand(); final int i = itemstack.getCount(); final PlayerEntity player = (PlayerEntity) e; - if (this.mother != null && this.mother.getOwner() != player) AIFindTarget.initiateCombat(this.mother + if (this.mother != null && this.mother.getOwner() != player) FindTargetsTask.initiateCombat(this.mother .getEntity(), player); if (i <= 0 || player.inventory.addItemStackToInventory(itemstack)) { diff --git a/src/main/java/pokecube/core/moves/MovesUtils.java b/src/main/java/pokecube/core/moves/MovesUtils.java index 178dea4a56..d724d31370 100644 --- a/src/main/java/pokecube/core/moves/MovesUtils.java +++ b/src/main/java/pokecube/core/moves/MovesUtils.java @@ -349,8 +349,8 @@ public static float getAttackStrength(final IPokemob attacker, final IPokemob at } // If this is a fight over a mate, the strength is reduced. - if (attacker.getCombatState(CombatStates.MATEFIGHT) && attacked.getCombatState(CombatStates.MATEFIGHT)) - statusMultiplier *= 0.25; + if (attacker.getCombatState(CombatStates.MATEFIGHT) || attacked.getCombatState(CombatStates.MATEFIGHT)) + statusMultiplier *= 0.125; ATT = (int) (statusMultiplier * ATT); diff --git a/src/main/java/pokecube/core/moves/templates/Move_Basic.java b/src/main/java/pokecube/core/moves/templates/Move_Basic.java index efae8305dd..31de909468 100644 --- a/src/main/java/pokecube/core/moves/templates/Move_Basic.java +++ b/src/main/java/pokecube/core/moves/templates/Move_Basic.java @@ -23,7 +23,7 @@ import net.minecraft.world.World; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.abilities.Ability; import pokecube.core.database.moves.MoveEntry; import pokecube.core.events.pokemob.combat.MoveUse; @@ -370,7 +370,7 @@ public void onAttack(MovePacket packet) } if (attacked != attackerMob && targetPokemob != null) { - AIFindTarget.initiateCombat((MobEntity) attacked, attackerMob); + FindTargetsTask.initiateCombat((MobEntity) attacked, attackerMob); targetPokemob.setCombatState(CombatStates.ANGRY, true); } if (efficiency > 0 && packet.applyOngoing) diff --git a/src/main/java/pokecube/core/network/pokemobs/PacketPokemobGui.java b/src/main/java/pokecube/core/network/pokemobs/PacketPokemobGui.java index c278fc5896..3d3e74ade8 100644 --- a/src/main/java/pokecube/core/network/pokemobs/PacketPokemobGui.java +++ b/src/main/java/pokecube/core/network/pokemobs/PacketPokemobGui.java @@ -9,7 +9,7 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.network.NetworkHooks; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.utility.AIStoreStuff; +import pokecube.core.ai.tasks.utility.StoreTask; import pokecube.core.entity.pokemobs.ContainerPokemob; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; @@ -88,10 +88,10 @@ public void handleServer(final ServerPlayerEntity player) }); return; case STORAGE: - AIStoreStuff ai = null; + StoreTask ai = null; for (final IAIRunnable run : pokemob.getTasks()) - if (run instanceof AIStoreStuff) ai = (AIStoreStuff) run; - final AIStoreStuff toSend = ai; + if (run instanceof StoreTask) ai = (StoreTask) run; + final StoreTask toSend = ai; buffer.writeCompoundTag(toSend.serializeNBT()); provider = new SimpleNamedContainerProvider((i, p, e) -> new ContainerPokemob(i, p, buffer), entity .getDisplayName()); diff --git a/src/main/java/pokecube/mobs/abilities/a/ArenaTrap.java b/src/main/java/pokecube/mobs/abilities/a/ArenaTrap.java index b1d63c9e2d..224c7d746c 100644 --- a/src/main/java/pokecube/mobs/abilities/a/ArenaTrap.java +++ b/src/main/java/pokecube/mobs/abilities/a/ArenaTrap.java @@ -1,22 +1,37 @@ package pokecube.mobs.abilities.a; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.world.server.ServerWorld; import pokecube.core.PokecubeCore; import pokecube.core.database.abilities.Ability; import pokecube.core.interfaces.IPokemob; +import thut.api.maths.Vector3; public class ArenaTrap extends Ability { // the part that usually prevents switching is still "TODO" + int range = 4; + + @Override + public Ability init(final Object... args) + { + if (args == null) return this; + for (final Object arg : args) + if (arg instanceof Integer) + { + this.range = (int) arg; + return this; + } + return this; + } + @Override - public void onUpdate(IPokemob mob) + public void onUpdate(final IPokemob mob) { + if (!(mob.getEntity().getEntityWorld() instanceof ServerWorld)) return; if (mob.getEntity().ticksExisted % 20 == 0) { - if (!(mob.getOwner() instanceof ServerPlayerEntity)) return; - PokecubeCore.spawner.doSpawnForPlayer((PlayerEntity) mob.getOwner(), mob.getOwner() - .getEntityWorld()); + final ServerWorld world = (ServerWorld) mob.getEntity().getEntityWorld(); + PokecubeCore.spawner.doSpawnForPoint(Vector3.getNewVector().set(mob.getEntity()), world, 0, this.range); } } } diff --git a/src/main/java/pokecube/mobs/abilities/eventwatchers/Damp.java b/src/main/java/pokecube/mobs/abilities/eventwatchers/Damp.java index 7dce8cf877..6831c4ae8e 100644 --- a/src/main/java/pokecube/mobs/abilities/eventwatchers/Damp.java +++ b/src/main/java/pokecube/mobs/abilities/eventwatchers/Damp.java @@ -1,6 +1,5 @@ package pokecube.mobs.abilities.eventwatchers; -import net.minecraft.entity.LivingEntity; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.ExplosionEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -14,10 +13,11 @@ public class Damp extends Ability { IPokemob mob; - int range = 16; + + int range = 16; @SubscribeEvent - public void denyBoom(ExplosionEvent.Start boom) + public void denyBoom(final ExplosionEvent.Start boom) { if (!this.mob.getEntity().isAlive()) this.destroy(); else @@ -35,7 +35,7 @@ public void destroy() } @Override - public Ability init(Object... args) + public Ability init(final Object... args) { if (ThutCore.proxy.isClientSide()) return this; for (int i = 0; i < 2; i++) @@ -52,12 +52,7 @@ public Ability init(Object... args) } @Override - public void onAgress(IPokemob mob, LivingEntity target) - { - } - - @Override - public void onMoveUse(IPokemob mob, MovePacket move) + public void onMoveUse(final IPokemob mob, final MovePacket move) { if (move.getMove() instanceof Move_Explode) { @@ -67,7 +62,7 @@ public void onMoveUse(IPokemob mob, MovePacket move) } @Override - public void onUpdate(IPokemob mob) + public void onUpdate(final IPokemob mob) { this.mob = mob; } diff --git a/src/main/java/pokecube/mobs/abilities/h/HoneyGather.java b/src/main/java/pokecube/mobs/abilities/h/HoneyGather.java index 1d8c4515eb..410f2796ce 100644 --- a/src/main/java/pokecube/mobs/abilities/h/HoneyGather.java +++ b/src/main/java/pokecube/mobs/abilities/h/HoneyGather.java @@ -23,10 +23,11 @@ public class HoneyGather extends Ability @Override public Ability init(final Object... args) { - for (int i = 0; i < 2; i++) - if (args != null && args.length > i) if (args[i] instanceof Integer) + if (args == null) return this; + for (final Object arg : args) + if (arg instanceof Integer) { - this.range = (int) args[i]; + this.range = (int) arg; return this; } return this; diff --git a/src/main/java/pokecube/mobs/abilities/i/Illuminate.java b/src/main/java/pokecube/mobs/abilities/i/Illuminate.java index eae1121ebe..8cb8e0653e 100644 --- a/src/main/java/pokecube/mobs/abilities/i/Illuminate.java +++ b/src/main/java/pokecube/mobs/abilities/i/Illuminate.java @@ -1,21 +1,36 @@ package pokecube.mobs.abilities.i; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.world.server.ServerWorld; import pokecube.core.PokecubeCore; import pokecube.core.database.abilities.Ability; import pokecube.core.interfaces.IPokemob; +import thut.api.maths.Vector3; public class Illuminate extends Ability { + int range = 4; + + @Override + public Ability init(final Object... args) + { + if (args == null) return this; + for (final Object arg : args) + if (arg instanceof Integer) + { + this.range = (int) arg; + return this; + } + return this; + } + @Override - public void onUpdate(IPokemob mob) + public void onUpdate(final IPokemob mob) { + if (!(mob.getEntity().getEntityWorld() instanceof ServerWorld)) return; if (mob.getEntity().ticksExisted % 20 == 0) { - if (!(mob.getOwner() instanceof ServerPlayerEntity)) return; - PokecubeCore.spawner.doSpawnForPlayer((PlayerEntity) mob.getOwner(), mob.getOwner() - .getEntityWorld()); + final ServerWorld world = (ServerWorld) mob.getEntity().getEntityWorld(); + PokecubeCore.spawner.doSpawnForPoint(Vector3.getNewVector().set(mob.getEntity()), world, 0, this.range); } } } diff --git a/src/main/java/pokecube/mobs/abilities/s/Swarm.java b/src/main/java/pokecube/mobs/abilities/s/Swarm.java index 87cf05b57f..db7c1dc61c 100644 --- a/src/main/java/pokecube/mobs/abilities/s/Swarm.java +++ b/src/main/java/pokecube/mobs/abilities/s/Swarm.java @@ -1,32 +1,47 @@ package pokecube.mobs.abilities.s; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.world.server.ServerWorld; import pokecube.core.PokecubeCore; import pokecube.core.database.abilities.Ability; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.pokemob.moves.MovePacket; import pokecube.core.utils.PokeType; +import thut.api.maths.Vector3; public class Swarm extends Ability { + int range = 4; + @Override - public void onMoveUse(IPokemob mob, MovePacket move) + public Ability init(final Object... args) { - - if (!move.pre) return; - if (mob == move.attacker && move.attackType == PokeType.getType("bug") && mob.getEntity().getHealth() < mob - .getEntity().getMaxHealth() / 3) move.PWR *= 1.5; + if (args == null) return this; + for (final Object arg : args) + if (arg instanceof Integer) + { + this.range = (int) arg; + return this; + } + return this; } @Override - public void onUpdate(IPokemob mob) + public void onUpdate(final IPokemob mob) { + if (!(mob.getEntity().getEntityWorld() instanceof ServerWorld)) return; if (mob.getEntity().ticksExisted % 20 == 0) { - if (!(mob.getOwner() instanceof ServerPlayerEntity)) return; - PokecubeCore.spawner.doSpawnForPlayer((PlayerEntity) mob.getOwner(), mob.getOwner() - .getEntityWorld()); + final ServerWorld world = (ServerWorld) mob.getEntity().getEntityWorld(); + PokecubeCore.spawner.doSpawnForPoint(Vector3.getNewVector().set(mob.getEntity()), world, 0, this.range); } } + + @Override + public void onMoveUse(final IPokemob mob, final MovePacket move) + { + + if (!move.pre) return; + if (mob == move.attacker && move.attackType == PokeType.getType("bug") && mob.getEntity().getHealth() < mob + .getEntity().getMaxHealth() / 3) move.PWR *= 1.5; + } } diff --git a/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java b/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java index 107074af34..5112a85a73 100644 --- a/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java +++ b/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java @@ -1,6 +1,6 @@ package pokecube.mobs.moves.attacks.special; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.pokemob.moves.MovePacket; import pokecube.core.moves.templates.Move_Basic; @@ -16,7 +16,7 @@ public Teleport() public void postAttack(final MovePacket packet) { final IPokemob attacker = packet.attacker; - AIFindTarget.deagro(attacker.getEntity()); + FindTargetsTask.deagro(attacker.getEntity()); super.postAttack(packet); } } diff --git a/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java b/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java index 1077475fe2..82ddbf65ea 100644 --- a/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java +++ b/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java @@ -5,7 +5,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.interfaces.IMoveAnimation; import pokecube.core.interfaces.IMoveConstants; import pokecube.core.interfaces.IMoveNames; @@ -78,7 +78,7 @@ public void attack(final IPokemob attacker, final Entity attacked) final IPokemob attackedMob = CapabilityPokemob.getPokemobFor(attacked); if (attacked instanceof LivingEntity) { - AIFindTarget.initiateCombat(attacker.getEntity(), (LivingEntity) attacked); + FindTargetsTask.initiateCombat(attacker.getEntity(), (LivingEntity) attacked); attacker.setTransformedTo(attacked); } else if (attackedMob != null) diff --git a/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java b/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java index abcf2834e9..1c93a18352 100644 --- a/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java +++ b/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java @@ -1,6 +1,6 @@ package pokecube.mobs.moves.attacks.special; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; @@ -39,6 +39,6 @@ public void postAttack(final MovePacket packet) attacked.setCombatState(CombatStates.ANGRY, false); } // ends the battle - AIFindTarget.deagro(packet.attacker.getEntity()); + FindTargetsTask.deagro(packet.attacker.getEntity()); } } diff --git a/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java b/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java index 8fcc2e520b..6d0612a631 100644 --- a/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java +++ b/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java @@ -6,7 +6,7 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.AIFindTarget; +import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.handlers.events.EventsHandler; import pokecube.core.handlers.events.SpawnHandler; import pokecube.core.interfaces.IMoveAction; @@ -95,7 +95,7 @@ public boolean applyEffect(final IPokemob user, final Vector3 location) } else if (angry) { - AIFindTarget.deagro(user.getEntity()); + FindTargetsTask.deagro(user.getEntity()); if (user.getGeneralState(GeneralStates.TAMED)) user.onRecall(); else ActionTeleport.teleportRandomly(user.getEntity()); } diff --git a/src/main/java/thut/api/OwnableCaps.java b/src/main/java/thut/api/OwnableCaps.java index b36dea6502..d663d31a7c 100644 --- a/src/main/java/thut/api/OwnableCaps.java +++ b/src/main/java/thut/api/OwnableCaps.java @@ -276,22 +276,25 @@ public static IOwnable getOwnable(final ICapabilityProvider in) @SubscribeEvent(priority = EventPriority.LOWEST) public static void attachMobs(final AttachCapabilitiesEvent event) { + // Check if someone else adds this first (like say an IPokemob + for (final ICapabilityProvider p : event.getCapabilities().values()) + if (p.getCapability(ThutCaps.OWNABLE_CAP).isPresent()) return; // We check if it is already here, incase someone else wants to wrap a // tameable differently. - if (!event.getCapabilities().containsKey(OwnableCaps.LOCWRAP)) - { - if (event.getObject() instanceof TameableEntity) event.addCapability(OwnableCaps.LOCWRAP, new TameWrapper( - (TameableEntity) event.getObject())); - else if (event.getObject() instanceof AbstractHorseEntity) event.addCapability(OwnableCaps.LOCWRAP, - new HorseWrapper((AbstractHorseEntity) event.getObject())); - } + if (event.getObject() instanceof TameableEntity) event.addCapability(OwnableCaps.LOCWRAP, new TameWrapper( + (TameableEntity) event.getObject())); + else if (event.getObject() instanceof AbstractHorseEntity) event.addCapability(OwnableCaps.LOCWRAP, + new HorseWrapper((AbstractHorseEntity) event.getObject())); else if (OwnableCaps.MOBS.contains(event.getObject().getClass())) event.addCapability(OwnableCaps.LOCBASE, new Impl()); } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOWEST) public static void attachTEs(final AttachCapabilitiesEvent event) { + // Check if someone else adds this first (like say an IPokemob + for (final ICapabilityProvider p : event.getCapabilities().values()) + if (p.getCapability(ThutCaps.OWNABLE_CAP).isPresent()) return; if (OwnableCaps.TILES.contains(event.getObject().getClass())) event.addCapability(OwnableCaps.LOCBASE, new ImplTE()); } diff --git a/src/main/java/thut/core/common/network/TileUpdate.java b/src/main/java/thut/core/common/network/TileUpdate.java index ea66d8ce2b..13626729fe 100644 --- a/src/main/java/thut/core/common/network/TileUpdate.java +++ b/src/main/java/thut/core/common/network/TileUpdate.java @@ -15,7 +15,7 @@ public static void sendUpdate(final TileEntity tile) { if (tile.getWorld().isRemote) { - ThutCore.LOGGER.error("Packet sent on wrong side!", new IllegalArgumentException()); + ThutCore.LOGGER.error("Packet sent on wrong side!"); return; } final CompoundNBT tag = new CompoundNBT(); diff --git a/src/main/resources/assets/pokecube_adventures/lang/en_us.json b/src/main/resources/assets/pokecube_adventures/lang/en_us.json index 769411c659..afb3722080 100644 --- a/src/main/resources/assets/pokecube_adventures/lang/en_us.json +++ b/src/main/resources/assets/pokecube_adventures/lang/en_us.json @@ -2,6 +2,10 @@ "_comment": "Pokecube Adventures translation", "block.rfsiphon.info": "Energy Output: %1$s/%2$s", + "block.afa.ability.none": "No Ability Set", + "block.afa.ability.info": "Ability: %s", + "block.afa.range.info": "Range: %s", + "block.afa.power.info": "Power: %1$s/%2$s", "item.pokecube_adventures.target": "Target", "item.pokecube_adventures.linker": "Location Linker", @@ -424,7 +428,5 @@ "_comment": "Misc", "pokecube.config.tmRecipe.tooltip": "Can TMs be crafted", - "pokedex.inspect.geneticsguide": "§aYou recieved a Genetics Guide from the Pokédex.", - - "pokeadv.infobook1.json": "{pages:[\"{\\\"text\\\":\\\"Pokemob Genetics Guide\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n V.1.0\\\"}\",\"[\\\"\\\",{\\\"text\\\":\\\"Index\\\",\\\"bold\\\":true,\\\"underlined\\\":true},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"Basic Terms\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_red\\\",\\\"clickEvent\\\":{\\\"action\\\":\\\"change_page\\\",\\\"value\\\":3}},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\",\\\"underlined\\\":true},{\\\"text\\\":\\\"Pokemob DNA\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_aqua\\\",\\\"clickEvent\\\":{\\\"action\\\":\\\"change_page\\\",\\\"value\\\":7}},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\",\\\"underlined\\\":true},{\\\"text\\\":\\\"Extracting DNA\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_green\\\",\\\"clickEvent\\\":{\\\"action\\\":\\\"change_page\\\",\\\"value\\\":14}},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\" \\\",\\\"color\\\":\\\"dark_green\\\"},{\\\"text\\\":\\\"DNA Selectors\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_green\\\",\\\"clickEvent\\\":{\\\"action\\\":\\\"change_page\\\",\\\"value\\\":15}},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\" \\\",\\\"color\\\":\\\"dark_green\\\"},{\\\"text\\\":\\\"Gene Extractor\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_green\\\",\\\"clickEvent\\\":{\\\"action\\\":\\\"change_page\\\",\\\"value\\\":18}},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"Cloning Pokemobs\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_purple\\\",\\\"clickEvent\\\":{\\\"action\\\":\\\"change_page\\\",\\\"value\\\":23}},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\",\\\"underlined\\\":true},{\\\"text\\\":\\\"Splicing DNA\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"blue\\\",\\\"clickEvent\\\":{\\\"action\\\":\\\"change_page\\\",\\\"value\\\":25}}]\",\"[\\\"\\\",{\\\"text\\\":\\\"Basic Terminology\\\\n\\\\nExpressed Gene (EG):\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_red\\\"},{\\\"text\\\":\\\"\\\\nThis is the trait that shows on your mob.\\\\n\\\\n\\\",\\\"color\\\":\\\"dark_red\\\"},{\\\"text\\\":\\\"Parent Genes (PG):\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_red\\\"},{\\\"text\\\":\\\"\\\\nThese are the inherited genes which, when merged, result in the Expressed Gene. Each EG corresponds to 2 PGs\\\",\\\"color\\\":\\\"dark_red\\\"}]\",\"[\\\"\\\",{\\\"text\\\":\\\"Recessive:\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_red\\\"},{\\\"text\\\":\\\"\\\\nRecessive genes require both of the PGs to be the same for them to be expressed.\\\",\\\"color\\\":\\\"dark_red\\\"},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"Co-dominant\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_red\\\"},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"Co-dominant genes will select a random PG for the EG.\\\",\\\"color\\\":\\\"dark_red\\\"}]\",\"[\\\"\\\",{\\\"text\\\":\\\"\\\\n\\\"},{\\\"text\\\":\\\"Epigenetic:\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_red\\\"},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"If a gene is epigenetic, then instead of using a PG for inheritance, it will use the EG, and the EG will change based on the pokemob.\\\",\\\"color\\\":\\\"dark_red\\\"}]\",\"[\\\"\\\",{\\\"text\\\":\\\"Pokemob DNA\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_aqua\\\"},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"There are presently 9 known genes that Pokemobs can have.\\\\n\\\\nOf these 9, 2 are strictly Epigenetic, and 1 has a low chance of showing Epigenetic tendencies.\\\",\\\"color\\\":\\\"dark_aqua\\\"}]\",\"[\\\"\\\",{\\\"text\\\":\\\"The known Genes are:\\\",\\\"color\\\":\\\"dark_aqua\\\"},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"ability\\\",\\\"color\\\":\\\"dark_aqua\\\"},{\\\"text\\\":\\\"\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"colour\\\\nsize\\\\nnature\\\\nshiny\\\\nmoves*\\\\nivs\\\\nevs*\\\\nspecies\\\\n\\\\n*Epigenetic\\\",\\\"color\\\":\\\"dark_aqua\\\"}]\",\"{\\\"text\\\":\\\"Most of these genes appear to be Co-Dominant, with a low rate of mutation. The exceptions are listed below:\\\\n\\\\nNature\\\\nShiny\\\\nSpecies\\\\nMoves\\\",\\\"color\\\":\\\"dark_aqua\\\"}\",\"{\\\"text\\\":\\\"Nature Gene:\\\\n\\\\nThe nature gene appears to exhibit a merging effect rather than dominance, the EG will be a merge of the two PG, with a small chance of being entirely random instead.\\\",\\\"color\\\":\\\"dark_aqua\\\"}\",\"{\\\"text\\\":\\\"Shiny Gene:\\\\n\\\\nThe Shiny Gene appears to be a rare, recessive Gene. \\\\n\\\\nThe Shiny Charm seems to somehow force expression of this gene, without actually allowing it to be passed on.\\\",\\\"color\\\":\\\"dark_aqua\\\"}\",\"{\\\"text\\\":\\\"Species Gene:\\\\n\\\\nFor the Species Gene, it seems dominance is based on whether one of the genes is gendered. Genderless Species Genes are recessive.\\\\n\\\\nThis gene sometimes shows Epigenetic tendencies.\\\",\\\"color\\\":\\\"dark_aqua\\\"}\",\"{\\\"text\\\":\\\"Moves Gene:\\\\n\\\\nThe Moves Gene only seems to be expressed if both PG share a similarity in this gene. In most cases this is not the case.\\\",\\\"color\\\":\\\"dark_aqua\\\"}\",\"[\\\"\\\",{\\\"text\\\":\\\"Extracting DNA\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_green\\\"},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"DNA is Extracted via the Gene Extractor.\\\\n\\\\nThis process requires Power, a Bottle of Water (for DNA to go into), a Selector, and a DNA Source.\\\",\\\"color\\\":\\\"dark_green\\\"}]\",\"[\\\"\\\",{\\\"text\\\":\\\"DNA Selectors\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_green\\\"},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"DNA Selectors will let the machine know which Gene to target for Extraction or Splicing.\\\\n\\\\nThere are 2 ways to make a selector, via a Computer Interface (Open Computers) or via a written book.\\\",\\\"color\\\":\\\"dark_green\\\"}]\",\"{\\\"text\\\":\\\"A Book selector can be made by creating a written book named \\\\\\\"Selector\\\\\\\", then placing the name of each gene to select on a seperate line of the first page.\\\\n\\\\n\\\\\\\"all\\\\\\\" can also be used to select all genes.\\\",\\\"color\\\":\\\"dark_green\\\"}\",\"{\\\"text\\\":\\\"Book Selectors can then be crafted with various objects to change their chances of breaking themselves or the source of the DNA. The only currently known object for this is a nether star.\\\",\\\"color\\\":\\\"dark_green\\\"}\",\"[\\\"\\\",{\\\"text\\\":\\\"Gene Extractor\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_green\\\"},{\\\"text\\\":\\\"\\\\n\\\\nThe Gene Extractor is used to extract DNA from a source, and into a bottle. Known sources are:\\\\n\\\\nFilled Pokecubes\\\\nPokemob Eggs\\\\nFossils (only have species)\\\",\\\"color\\\":\\\"dark_green\\\"}]\",\"{\\\"text\\\":\\\"The slots in the Extractor are marked according to what should go in them, and it will automatically begin extraction as soon as the slots are filled.\\\\n\\\\nWhen using a computer to specify the Selector, no book is needed.\\\",\\\"color\\\":\\\"dark_green\\\"}\",\"{\\\"text\\\":\\\"The tooltip on the Selector will display the genes being selected, and will have 2 numbers at the bottom.\\\\n\\\\nThese numbers represent how unstable the selector is, larger numbers are bad, these numbers go from 0-1.\\\",\\\"color\\\":\\\"dark_green\\\"}\",\"{\\\"text\\\":\\\"The first number represents the chance of the selector breaking during extraction, and the second represents the chance the DNA source will break during extraction.\\\",\\\"color\\\":\\\"dark_green\\\"}\",\"{\\\"text\\\":\\\"The DNA source will also have a tooltip, which will display the EGs for the source. \\\\n\\\\nTo get information on the PGs, you need to use the computer interface.\\\",\\\"color\\\":\\\"dark_green\\\"}\",\"[\\\"\\\",{\\\"text\\\":\\\"Cloning Pokemobs\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"dark_purple\\\"},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"Once you have extracted some Species DNA, you can place the bottle of it in the bottle slot of the cloning device. The Egg slot needs to be provided with an egg as well, this can be any egg, even a chicken.\\\",\\\"color\\\":\\\"dark_purple\\\"}]\",\"{\\\"text\\\":\\\"The cloning process will require energy, and when complete, will result in a Pokemob infront of the device, usually at level 20.\\\\n\\\\nAny source of Species DNA should work, and if any other genes are present, they will be applied to the Pokemob.\\\",\\\"color\\\":\\\"dark_purple\\\"}\",\"[\\\"\\\",{\\\"text\\\":\\\"Splicing DNA\\\",\\\"underlined\\\":true,\\\"color\\\":\\\"blue\\\"},{\\\"text\\\":\\\"\\\\n\\\\n\\\",\\\"color\\\":\\\"reset\\\"},{\\\"text\\\":\\\"The Gene Splicer can be used to splice together DNA from different sources. The Selector used is the same as in the Gene Extractor, but now the destination and source slots can both take DNA.\\\",\\\"color\\\":\\\"blue\\\"}]\"],title:\"Pokemob Genetics\",author:Thutmose,display:{Lore:[\"Your Guide to Pokemob Genetics\"]}}" + "pokedex.inspect.geneticsguide": "§aYou recieved a Genetics Guide from the Pokédex." } From 6ca9c2ce921ea49a388d9a7a9268b117d1907c84 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 05:52:36 -0400 Subject: [PATCH 11/27] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 3 +++ .github/ISSUE_TEMPLATE/feature_request.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 95c0b41307..7b260569b3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,9 @@ --- name: Bug report about: Create a report to help us improve +title: '' +labels: Unconfirmed +assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 066b2d920a..11fc491ef1 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,6 +1,9 @@ --- name: Feature request about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' --- From 322806fcec5755a7f5c315f4754accc838283832 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 06:32:32 -0400 Subject: [PATCH 12/27] Update SpawnHandler.java adjustments to some spawning checks --- .../core/handlers/events/SpawnHandler.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/main/java/pokecube/core/handlers/events/SpawnHandler.java b/src/main/java/pokecube/core/handlers/events/SpawnHandler.java index 35a3929735..cf2a871e9d 100644 --- a/src/main/java/pokecube/core/handlers/events/SpawnHandler.java +++ b/src/main/java/pokecube/core/handlers/events/SpawnHandler.java @@ -748,11 +748,9 @@ private int doSpawnForType(final ServerWorld world, final Vector3 loc, final Pok final SpawnData entry = dbe.getSpawnData(); final Vector3 v = Vector3.getNewVector(); - final Vector3 v1 = Vector3.getNewVector(); final Vector3 v2 = Vector3.getNewVector(); final Vector3 v3 = Vector3.getNewVector(); int totalSpawnCount = 0; - final Vector3 offset = v1.clear(); final Vector3 point = v2.clear(); SpawnHandler.refreshTerrain(loc, world, false); final SpawnBiomeMatcher matcher = entry.getMatcher(world, loc); @@ -764,19 +762,11 @@ private int doSpawnForType(final ServerWorld world, final Vector3 loc, final Pok for (int i = 0; i < spawnNumber; i++) { - offset.set(rand.nextInt(distGroupZone) - rand.nextInt(distGroupZone), rand.nextInt(1) - rand.nextInt(1), - rand.nextInt(distGroupZone) - rand.nextInt(distGroupZone)); final Vector3 dr = SpawnHandler.getRandomPointNear(world, loc, distGroupZone); - if (dr != null) - { - - } - System.out.println(dr); - - v.set(loc); - point.set(v.addTo(offset)); + if (dr != null) point.set(dr); + else continue; - if (!SpawnHandler.isPointValidForSpawn(world, point, dbe)) continue; + if (!SpawnHandler.checkNoSpawnerInArea(world, point.intX(), point.intY(), point.intZ())) continue; final float x = (float) point.x; final float y = (float) point.y; From f313cefce23537d3e06058991e48ee3717515f28 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 07:42:33 -0400 Subject: [PATCH 13/27] re-arrange and cleanup some configs (code side) --- .../client/render/mobs/RenderPokemob.java | 1 + .../java/pokecube/core/handlers/Config.java | 62 ++++++++++--------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/main/java/pokecube/core/client/render/mobs/RenderPokemob.java b/src/main/java/pokecube/core/client/render/mobs/RenderPokemob.java index fe54ff2d73..4f6103297f 100644 --- a/src/main/java/pokecube/core/client/render/mobs/RenderPokemob.java +++ b/src/main/java/pokecube/core/client/render/mobs/RenderPokemob.java @@ -546,6 +546,7 @@ public static void register() final Holder holder = new Holder(entry); RenderPokemob.holderMap.put(type, holder); RenderPokemob.holders.put(entry, holder); + if (PokecubeCore.getConfig().preloadModels) holder.init(); } } diff --git a/src/main/java/pokecube/core/handlers/Config.java b/src/main/java/pokecube/core/handlers/Config.java index 7df07fa71b..1377537cca 100644 --- a/src/main/java/pokecube/core/handlers/Config.java +++ b/src/main/java/pokecube/core/handlers/Config.java @@ -177,11 +177,6 @@ private static SoundEvent getRegisteredSoundEvent(final String id) @Configure(category = Config.moves) public boolean defaultIceActions = true; - @Configure(category = Config.moves, type = Type.CLIENT) - public double moveVolumeCry = 0.0625f; - @Configure(category = Config.moves, type = Type.CLIENT) - public double moveVolumeEffect = 1; - // AI Related settings @Configure(category = Config.mobAI) public int mateMultiplier = 1; @@ -444,54 +439,63 @@ private static SoundEvent getRegisteredSoundEvent(final String id) // Gui/client settings @Configure(category = Config.client, type = Type.CLIENT) - public String guiRef = "top_left"; + public String guiRef = "top_left"; @Configure(category = Config.client, type = Type.CLIENT) - public String messageRef = "right_middle"; + public String messageRef = "right_middle"; @Configure(category = Config.client, type = Type.CLIENT) - public String targetRef = "top_right"; + public String targetRef = "top_right"; @Configure(category = Config.client, type = Type.CLIENT) - public String teleRef = "top_right"; + public String teleRef = "top_right"; + @Configure(category = Config.client, type = Type.CLIENT) - public List guiPos = Lists.newArrayList(new Integer[] { 0, 0 }); + public List guiPos = Lists.newArrayList(new Integer[] { 0, 0 }); @Configure(category = Config.client, type = Type.CLIENT) - public double guiSize = 1; + public List telePos = Lists.newArrayList(new Integer[] { 89, 17 }); @Configure(category = Config.client, type = Type.CLIENT) - public List telePos = Lists.newArrayList(new Integer[] { 89, 17 }); + public List targetPos = Lists.newArrayList(new Integer[] { 147, -42 }); @Configure(category = Config.client, type = Type.CLIENT) - public double teleSize = 1; + public List messagePos = Lists.newArrayList(new Integer[] { -150, -100 }); @Configure(category = Config.client, type = Type.CLIENT) - public List targetPos = Lists.newArrayList(new Integer[] { 147, -42 }); + public List messagePadding = Lists.newArrayList(new Integer[] { 0, 0 }); + @Configure(category = Config.client, type = Type.CLIENT) - public double targetSize = 1; + public double guiSize = 1; @Configure(category = Config.client, type = Type.CLIENT) - public List messagePos = Lists.newArrayList(new Integer[] { -150, -100 }); + public double teleSize = 1; @Configure(category = Config.client, type = Type.CLIENT) - public int messageWidth = 150;; + public double targetSize = 1; @Configure(category = Config.client, type = Type.CLIENT) - public List messagePadding = Lists.newArrayList(new Integer[] { 0, 0 }); + public double messageSize = 1; @Configure(category = Config.client, type = Type.CLIENT) - public double messageSize = 1; + public double captureVolume = 0.2; + @Configure(category = Config.moves, type = Type.CLIENT) + public double moveVolumeCry = 0.0625f; + @Configure(category = Config.moves, type = Type.CLIENT) + public double moveVolumeEffect = 1; + @Configure(category = Config.client, type = Type.CLIENT) - public boolean guiDown = true; + public boolean guiDown = true; @Configure(category = Config.client, type = Type.CLIENT) - public boolean guiAutoScale = false; + public boolean guiAutoScale = false; @Configure(category = Config.client, type = Type.CLIENT) - public boolean autoSelectMoves = false; + public boolean autoSelectMoves = false; @Configure(category = Config.client, type = Type.CLIENT) - public boolean autoRecallPokemobs = false; + public boolean autoRecallPokemobs = false; @Configure(category = Config.client, type = Type.CLIENT) - public int autoRecallDistance = 32; + public boolean riddenMobsTurnWithLook = true; @Configure(category = Config.client, type = Type.CLIENT) - public boolean riddenMobsTurnWithLook = true; + public boolean extraberries = false; @Configure(category = Config.client, type = Type.CLIENT) - public boolean extraberries = false; + public boolean battleLogInChat = false; @Configure(category = Config.client, type = Type.CLIENT) - public boolean battleLogInChat = false; + public boolean pokeCenterMusic = true; @Configure(category = Config.client, type = Type.CLIENT) - public boolean pokeCenterMusic = true; + public boolean preloadModels = false; @Configure(category = Config.client, type = Type.CLIENT) - public double captureVolume = 0.2; + public int messageWidth = 150;; + @Configure(category = Config.client, type = Type.CLIENT) + public int autoRecallDistance = 32; @Configure(category = Config.advanced) public List mystLocs = Lists.newArrayList(); From e3da5a9d74f1841dd4916939fc6e17391368f84e Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 07:43:35 -0400 Subject: [PATCH 14/27] Update PokecubeAdv.java update network version as new packets were added --- src/main/java/pokecube/adventures/PokecubeAdv.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pokecube/adventures/PokecubeAdv.java b/src/main/java/pokecube/adventures/PokecubeAdv.java index ccd206bee1..b9de64d295 100644 --- a/src/main/java/pokecube/adventures/PokecubeAdv.java +++ b/src/main/java/pokecube/adventures/PokecubeAdv.java @@ -251,7 +251,7 @@ static void init() public final static CommonProxy proxy = DistExecutor.runForDist(() -> () -> new ClientProxy(), () -> () -> new CommonProxy()); - private static final String NETVERSION = "1.0.0"; + private static final String NETVERSION = "1.0.1"; // Handler for network stuff. public static final PacketHandler packets = new PacketHandler(new ResourceLocation(PokecubeAdv.MODID, "comms"), PokecubeAdv.NETVERSION); From afaf4b763591d44fd8c3c8fbbdf09248c54e9559 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 08:21:18 -0400 Subject: [PATCH 15/27] some more config options for adjusting some AI running rates --- .../core/ai/brain/sensors/NearBlocks.java | 6 +- .../core/ai/tasks/idle/HungerTask.java | 1 + .../java/pokecube/core/handlers/Config.java | 137 ++++++++++-------- .../handlers/events/PokemobEventsHandler.java | 4 +- 4 files changed, 84 insertions(+), 64 deletions(-) diff --git a/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java b/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java index 1c13388787..902742a57c 100644 --- a/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java +++ b/src/main/java/pokecube/core/ai/brain/sensors/NearBlocks.java @@ -21,6 +21,7 @@ import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.math.Vec3d; import net.minecraft.world.server.ServerWorld; +import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.brain.MemoryModules; import thut.api.maths.Cruncher; @@ -68,7 +69,7 @@ public BlockState getState() } } - long lastUpdate = 0; + int tick = 0; @Override protected void update(final ServerWorld worldIn, final LivingEntity entityIn) @@ -76,6 +77,9 @@ protected void update(final ServerWorld worldIn, final LivingEntity entityIn) if (BrainUtils.hasAttackTarget(entityIn)) return; if (BrainUtils.hasMoveUseTarget(entityIn)) return; + this.tick++; + if (this.tick % PokecubeCore.getConfig().nearBlockUpdateRate != 0) return; + final Vector3 r = Vector3.getNewVector(), rAbs = Vector3.getNewVector(); final Vector3 origin = Vector3.getNewVector(); origin.set(entityIn); diff --git a/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java b/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java index 4937428c6e..82425c0278 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java @@ -170,6 +170,7 @@ protected boolean checkHunt() { if (!this.hitThreshold(HungerTask.HUNTTHRESHOLD)) return false; if (this.pokemob.isPhototroph()) if (this.checkPhotoeat()) return true; + if (this.entity.ticksExisted % PokecubeCore.getConfig().huntUpdateRate != 0) return false; for (final IBlockEatTask task : HungerTask.EATTASKS) if (task.tryEat(this.pokemob, this.blocks).test()) return true; // If none of these, then lets actually try to hunt. diff --git a/src/main/java/pokecube/core/handlers/Config.java b/src/main/java/pokecube/core/handlers/Config.java index 1377537cca..13d25db6d8 100644 --- a/src/main/java/pokecube/core/handlers/Config.java +++ b/src/main/java/pokecube/core/handlers/Config.java @@ -179,120 +179,133 @@ private static SoundEvent getRegisteredSoundEvent(final String id) // AI Related settings @Configure(category = Config.mobAI) - public int mateMultiplier = 1; + public int mateMultiplier = 1; @Configure(category = Config.mobAI) - public double mateDensityWild = 2; + public int mateAIRate = 40; @Configure(category = Config.mobAI) - public int mateAIRate = 40; + public int breedingDelay = 4000; @Configure(category = Config.mobAI) - public double mateDensityPlayer = 4; - @Configure(category = Config.mobAI) - public int breedingDelay = 4000; - @Configure(category = Config.mobAI) - public int eggHatchTime = 10000; - @Configure(category = Config.mobAI) - /** do wild pokemobs which leave cullDistance despawn immediately */ - public boolean cull = false; + public int eggHatchTime = 10000; /** distance for culling */ @Configure(category = Config.mobAI) - public int cullDistance = 96; - @Configure(category = Config.mobAI) - public boolean despawn = true; + public int cullDistance = 96; /** distance for culling */ @Configure(category = Config.mobAI) - public int despawnTimer = 2000; - @Configure(category = Config.mobAI) - /** Will lithovores eat gravel */ - public boolean pokemobsEatGravel = false; - @Configure(category = Config.mobAI) - /** Will lithovores eat rocks */ - public boolean pokemobsEatRocks = true; - @Configure(category = Config.mobAI) - /** Will herbivores eat plants */ - public boolean pokemobsEatPlants = true; - @Configure(category = Config.mobAI) - /** Is there a warning before a wild pok�mob attacks the player. */ - public boolean pokemobagresswarning = true; + public int despawnTimer = 2000; @Configure(category = Config.mobAI) /** Distance to player needed to agress the player */ - public int mobAggroRadius = 3; + public int mobAggroRadius = 3; @Configure(category = Config.mobAI) /** * Approximately how many ticks between wild pokemobs running agro * checks. */ - public int mobAgroRate = 200; + public int mobAgroRate = 200; @Configure(category = Config.mobAI) /** * Approximate number of ticks before pok�mob starts taking hunger * damage */ - public int pokemobLifeSpan = 8000; + public int pokemobLifeSpan = 8000; @Configure(category = Config.mobAI) - /** Warning time before a wild pok�mob attacks a player */ - public int pokemobagressticks = 100; + /** Warning time before a wild pokemob attacks a player */ + public int pokemobagressticks = 100; + @Configure(category = Config.mobAI) - public boolean pokemobsDamageOwner = false; + public double mateDensityWild = 2; @Configure(category = Config.mobAI) - public boolean pokemobsDamagePlayers = true; + public double expFromDeathDropScale = 1; @Configure(category = Config.mobAI) - public boolean pokemobsDamageBlocks = false; + public double mateDensityPlayer = 4; + @Configure(category = Config.mobAI) - public boolean pokemobsDropItems = true; + /** do wild pokemobs which leave cullDistance despawn immediately */ + public boolean cull = false; + @Configure(category = Config.mobAI) + public boolean despawn = true; @Configure(category = Config.mobAI) - public double expFromDeathDropScale = 1; + /** Will lithovores eat gravel */ + public boolean pokemobsEatGravel = false; + @Configure(category = Config.mobAI) + /** Will lithovores eat rocks */ + public boolean pokemobsEatRocks = true; + @Configure(category = Config.mobAI) + /** Will herbivores eat plants */ + public boolean pokemobsEatPlants = true; + @Configure(category = Config.mobAI) + /** Is there a warning before a wild pok�mob attacks the player. */ + public boolean pokemobagresswarning = true; + @Configure(category = Config.mobAI) + public boolean pokemobsDamageOwner = false; + @Configure(category = Config.mobAI) + public boolean pokemobsDamagePlayers = true; + @Configure(category = Config.mobAI) + public boolean pokemobsDamageBlocks = false; + @Configure(category = Config.mobAI) + public boolean pokemobsDropItems = true; @Configure(category = Config.mobAI) /** Do explosions occur and cause damage */ - public boolean explosions = true; + public boolean explosions = true; + @Configure(category = Config.mobAI) - public int chaseDistance = 32; + public int chaseDistance = 32; @Configure(category = Config.mobAI) - public int combatDistance = 4; + public int combatDistance = 4; @Configure(category = Config.mobAI) - public int aiDisableDistance = 32; + public int aiDisableDistance = 32; @Configure(category = Config.mobAI) - public int tameGatherDelay = 20; + public int tameGatherDelay = 20; @Configure(category = Config.mobAI) - public int wildGatherDelay = 200; + public int wildGatherDelay = 200; @Configure(category = Config.mobAI) - public int tameGatherDistance = 16; + public int tameGatherDistance = 16; @Configure(category = Config.mobAI) - public int wildGatherDistance = 8; + public int wildGatherDistance = 8; + @Configure(category = Config.mobAI) - public boolean tameGather = true; + public boolean tameGather = true; @Configure(category = Config.mobAI) - public boolean wildGather = false; + public boolean wildGather = false; @Configure(category = Config.mobAI) - public boolean flyEnabled = true; + public boolean flyEnabled = true; @Configure(category = Config.mobAI) - public boolean surfEnabled = true; + public boolean surfEnabled = true; @Configure(category = Config.mobAI) - public boolean diveEnabled = true; + public boolean diveEnabled = true; + @Configure(category = Config.mobAI) - public List dodgeSounds = Lists.newArrayList("entity.witch.throw"); + public List dodgeSounds = Lists.newArrayList("entity.witch.throw"); @Configure(category = Config.mobAI) - public List leapSounds = Lists.newArrayList("entity.witch.throw"); + public List leapSounds = Lists.newArrayList("entity.witch.throw"); @Configure(category = Config.mobAI) - public List guardBlacklistClass = Lists.newArrayList("net.minecraft.entity.IMerchant", + public List guardBlacklistClass = Lists.newArrayList("net.minecraft.entity.IMerchant", "net.minecraft.entity.INpc", "pokecube.core.items.pokemobeggs.EntityPokemobEgg", "net.minecraft.entity.IProjectile"); @Configure(category = Config.mobAI) - public List guardBlacklistId = Lists.newArrayList(); + public List guardBlacklistId = Lists.newArrayList(); + @Configure(category = Config.mobAI) - public double interactHungerScale = 1; + public double interactHungerScale = 1; @Configure(category = Config.mobAI) - public double interactDelayScale = 1; + public double interactDelayScale = 1; @Configure(category = Config.mobAI) - public boolean pokemobsOnShoulder = true; + public boolean pokemobsOnShoulder = true; + @Configure(category = Config.mobAI) - public int fishHookBaitRange = 16; + public int fishHookBaitRange = 16; @Configure(category = Config.mobAI) - public boolean guardModeEnabled = true; + public boolean guardModeEnabled = true; + + @Configure(category = Config.mobAI) + public int guardSearchDistance = 16; + @Configure(category = Config.mobAI) + public int guardTickRate = 20; + @Configure(category = Config.mobAI) - public int guardSearchDistance = 16; + public int nearBlockUpdateRate = 5; @Configure(category = Config.mobAI) - public int guardTickRate = 20; + public int huntUpdateRate = 5; // Used by pathfinder's movehelper for scaling speed in air and water. @Configure(category = Config.mobAI) @@ -668,6 +681,8 @@ public void onUpdated() if (this.spawnRate <= 0) this.spawnRate = 1; if (this.idleTickRate == 0) this.idleTickRate = 1; if (this.hungerTickRate == 0) this.hungerTickRate = 1; + if (this.nearBlockUpdateRate <= 0) this.nearBlockUpdateRate = 1; + if (this.huntUpdateRate <= 0) this.huntUpdateRate = 1; IdleWalkTask.IDLETIMER = this.idleTickRate; HungerTask.TICKRATE = this.hungerTickRate; diff --git a/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java b/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java index ab3d53a697..a057538466 100644 --- a/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java +++ b/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java @@ -179,8 +179,8 @@ else if (giveExp) final Entity targetOwner = attackedMob.getOwner(); attacker.displayMessageToOwner(new TranslationTextComponent("pokemob.action.faint.enemy", attackedMob .getDisplayName())); - if (targetOwner instanceof PlayerEntity && attacker.getOwner() != targetOwner) FindTargetsTask.initiateCombat( - pokemob, (LivingEntity) targetOwner); + if (targetOwner instanceof PlayerEntity && attacker.getOwner() != targetOwner) FindTargetsTask + .initiateCombat(pokemob, (LivingEntity) targetOwner); else FindTargetsTask.deagro(pokemob); if (attacker.getPokedexEntry().isFood(attackedMob.getPokedexEntry()) && attacker.getCombatState( CombatStates.HUNTING)) From 0c273aa8a08b7d964842d6cb5407119bcbd5e400 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 09:08:09 -0400 Subject: [PATCH 16/27] Fixes some issues with genetics blocks renames cloning recipe to that, it was called fossil revive for legacy reasons. fixes the issues related to #384 fixes issues with reviving mobs that should then evolve (and having rather odd un-evolved things tht claim to ve evolved) --- .../blocks/commander/CommanderBlock.java | 2 +- .../blocks/genetics/cloner/ClonerTile.java | 4 +- .../genetics/helper/BaseGeneticsTile.java | 4 +- .../helper/recipe/PoweredProcess.java | 6 +- ...cipeFossilRevive.java => RecipeClone.java} | 76 ++++++++++--------- .../genetics/helper/recipe/RecipeExtract.java | 14 +++- .../helper/recipe/RecipeHandlers.java | 12 +-- .../genetics/helper/recipe/RecipeSplice.java | 2 +- .../jei/categories/cloner/Category.java | 10 +-- .../jei/categories/evolution/Category.java | 10 +-- .../jei/categories/interaction/Category.java | 10 +-- .../compat/jei/categories/move/Category.java | 10 +-- .../core/ai/tasks/idle/HungerTask.java | 3 +- .../core/handlers/events/SpawnHandler.java | 1 - 14 files changed, 88 insertions(+), 76 deletions(-) rename src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/{RecipeFossilRevive.java => RecipeClone.java} (80%) diff --git a/src/main/java/pokecube/adventures/blocks/commander/CommanderBlock.java b/src/main/java/pokecube/adventures/blocks/commander/CommanderBlock.java index ad0f63d379..d766c65868 100644 --- a/src/main/java/pokecube/adventures/blocks/commander/CommanderBlock.java +++ b/src/main/java/pokecube/adventures/blocks/commander/CommanderBlock.java @@ -45,7 +45,7 @@ public void neighborChanged(final BlockState state, final World world, final Blo } catch (final Exception e) { - PokecubeMod.LOGGER.warn("Invalid Commander Block use at " + pos, e); + PokecubeMod.LOGGER.warn("Invalid Commander Block use at " + pos + " " + e.getMessage()); } commander.power = power; } diff --git a/src/main/java/pokecube/adventures/blocks/genetics/cloner/ClonerTile.java b/src/main/java/pokecube/adventures/blocks/genetics/cloner/ClonerTile.java index 053df03212..e8c296e9dc 100644 --- a/src/main/java/pokecube/adventures/blocks/genetics/cloner/ClonerTile.java +++ b/src/main/java/pokecube/adventures/blocks/genetics/cloner/ClonerTile.java @@ -16,7 +16,7 @@ import pokecube.adventures.blocks.genetics.helper.ClonerHelper; import pokecube.adventures.blocks.genetics.helper.GeneticsTileParentable; import pokecube.adventures.blocks.genetics.helper.recipe.PoweredRecipe; -import pokecube.adventures.blocks.genetics.helper.recipe.RecipeFossilRevive; +import pokecube.adventures.blocks.genetics.helper.recipe.RecipeClone; import thut.api.item.ItemList; public class ClonerTile extends GeneticsTileParentable @@ -71,7 +71,7 @@ public boolean isItemValidForSlot(final int index, final ItemStack stack) @Override public boolean isValid(final Class recipe) { - return recipe == RecipeFossilRevive.class; + return recipe == RecipeClone.class; } @Override diff --git a/src/main/java/pokecube/adventures/blocks/genetics/helper/BaseGeneticsTile.java b/src/main/java/pokecube/adventures/blocks/genetics/helper/BaseGeneticsTile.java index 5d44e26955..6cd705ddf3 100644 --- a/src/main/java/pokecube/adventures/blocks/genetics/helper/BaseGeneticsTile.java +++ b/src/main/java/pokecube/adventures/blocks/genetics/helper/BaseGeneticsTile.java @@ -162,9 +162,9 @@ public boolean canExtractItem(final int index, final ItemStack stack, final Dire * Returns true if automation can insert the given item in the given slot * from the given side. */ - public boolean canInsertItem(final int index, final ItemStack itemStackIn, final Direction direction) + public boolean canInsertItem(final int index, final ItemStack stack, final Direction direction) { - return this.isItemValidForSlot(index, itemStackIn); + return this.isItemValidForSlot(index, stack); } public void checkRecipes() diff --git a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/PoweredProcess.java b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/PoweredProcess.java index b7d0daa116..a5884716f3 100644 --- a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/PoweredProcess.java +++ b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/PoweredProcess.java @@ -16,13 +16,13 @@ public class PoweredProcess "pokecube_adventures:extracting")); public static final RecipeSplice SPLICE = new RecipeSplice(new ResourceLocation( "pokecube_adventures:splicing")); - public static final RecipeFossilRevive REVIVE = new RecipeFossilRevive(new ResourceLocation( + public static final RecipeClone REVIVE = new RecipeClone(new ResourceLocation( "pokecube_adventures:reviving")); public static PoweredRecipe findRecipe(final IPoweredProgress tile, final World world) { if (!tile.getStackInSlot(tile.getOutputSlot()).isEmpty()) return null; - if (tile.isValid(RecipeFossilRevive.class) && PoweredProcess.REVIVE.matches(tile.getCraftMatrix(), world)) + if (tile.isValid(RecipeClone.class) && PoweredProcess.REVIVE.matches(tile.getCraftMatrix(), world)) return PoweredProcess.REVIVE; if (tile.isValid(RecipeExtract.class) && !PoweredProcess.EXTRACT.getCraftingResult(tile.getCraftMatrix()) .isEmpty()) return PoweredProcess.EXTRACT; @@ -36,7 +36,7 @@ public static void init(final Register> event) RecipeSelector.SERIALIZER.toString(); RecipeExtract.SERIALIZER.toString(); RecipeSplice.SERIALIZER.toString(); - RecipeFossilRevive.SERIALIZER.toString(); + RecipeClone.SERIALIZER.toString(); // This one needs registration as is actually a real crafting recipe. event.getRegistry().register(RecipeSelector.SERIALIZER.setRegistryName(new ResourceLocation( diff --git a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeFossilRevive.java b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeClone.java similarity index 80% rename from src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeFossilRevive.java rename to src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeClone.java index fc3aaa38fb..54fb76892d 100644 --- a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeFossilRevive.java +++ b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeClone.java @@ -36,7 +36,7 @@ import pokecube.core.utils.Tools; import thut.api.entity.genetics.IMobGenetics; -public class RecipeFossilRevive extends PoweredRecipe +public class RecipeClone extends PoweredRecipe { public static class AnyMatcher implements ReviveMatcher @@ -48,7 +48,7 @@ public boolean complete(final IPoweredProgress tile) { final World world = ((TileEntity) tile).getWorld(); final BlockPos pos = ((TileEntity) tile).getPos(); - final PokedexEntry entry = RecipeFossilRevive.getEntry(this, tile); + final PokedexEntry entry = RecipeClone.getEntry(this, tile); if (entry == Database.missingno) return false; final boolean tame = !entry.isLegendary(); MobEntity entity = PokecubeCore.createPokemob(entry, world); @@ -60,22 +60,24 @@ public boolean complete(final IPoweredProgress tile) entity.setHealth(entity.getMaxHealth()); // to avoid the death on spawn final int exp = Tools.levelToXp(entry.getEvolutionMode(), AnyMatcher.level); - // that will make your pokemob around level 3-5. - // You can give him more XP if you want - entity = (pokemob = pokemob.setForSpawn(exp)).getEntity(); + + final IMobGenetics genes = ClonerHelper.getGenes(dnaSource); + if (genes != null) GeneticsManager.initFromGenes(genes, pokemob); + pokemob.getEntity().getPersistentData().putInt("spawnExp", exp); + pokemob = pokemob.spawnInit(); + if (tile.getUser() != null && tame) pokemob.setOwner(tile.getUser().getUniqueID()); - final Direction dir = world.getBlockState(pos).get(HorizontalBlock.HORIZONTAL_FACING); - entity.setLocationAndAngles(pos.getX() + 0.5 + dir.getXOffset(), pos.getY() + 1, pos.getZ() + 0.5 + dir - .getZOffset(), world.rand.nextFloat() * 360F, 0.0F); - entity.getPersistentData().putBoolean("cloned", true); final CloneEvent.Spawn event = new CloneEvent.Spawn((ClonerTile) tile, pokemob); if (PokecubeCore.POKEMOB_BUS.post(event)) return false; + pokemob = event.getPokemob(); entity = pokemob.getEntity(); + final Direction dir = world.getBlockState(pos).get(HorizontalBlock.HORIZONTAL_FACING); + entity.setLocationAndAngles(pos.getX() + 0.5 + dir.getXOffset(), pos.getY() + 1, pos.getZ() + 0.5 + dir + .getZOffset(), world.rand.nextFloat() * 360F, 0.0F); + entity.getPersistentData().putBoolean("cloned", true); world.addEntity(entity); - final IMobGenetics genes = ClonerHelper.getGenes(dnaSource); - if (genes != null) GeneticsManager.initFromGenes(genes, pokemob); entity.playAmbientSound(); } return true; @@ -120,7 +122,7 @@ default int priority() default int getEnergyCost() { - return RecipeFossilRevive.ENERGYCOST; + return RecipeClone.ENERGYCOST; } default boolean shouldKeep(final ItemStack stack) @@ -129,14 +131,14 @@ default boolean shouldKeep(final ItemStack stack) } } - public static int ENERGYCOST = 10000; - public static final IRecipeSerializer SERIALIZER = IRecipeSerializer.register( - "pokecube_adventures:reviving", new SpecialRecipeSerializer<>(RecipeFossilRevive::new)); + public static int ENERGYCOST = 10000; + public static final IRecipeSerializer SERIALIZER = IRecipeSerializer.register( + "pokecube_adventures:reviving", new SpecialRecipeSerializer<>(RecipeClone::new)); - public static Function ENERGYNEED = (s) -> RecipeFossilRevive.ENERGYCOST; - private static List recipeList = Lists.newArrayList(); + public static Function ENERGYNEED = (s) -> RecipeClone.ENERGYCOST; + private static List recipeList = Lists.newArrayList(); - private static HashMap entryMap = Maps.newHashMap(); + private static HashMap entryMap = Maps.newHashMap(); public static ReviveMatcher ANYMATCHER = new AnyMatcher(); public static final List MATCHERS = Lists.newArrayList(); @@ -152,17 +154,17 @@ public static PokedexEntry getEntry(final ReviveMatcher matcher, final IPoweredP return entry; } - public static RecipeFossilRevive getRecipe(final PokedexEntry entry) + public static RecipeClone getRecipe(final PokedexEntry entry) { - return RecipeFossilRevive.entryMap.get(entry); + return RecipeClone.entryMap.get(entry); } - public static List getRecipeList() + public static List getRecipeList() { - return Lists.newArrayList(RecipeFossilRevive.recipeList); + return Lists.newArrayList(RecipeClone.recipeList); } - public RecipeFossilRevive(final ResourceLocation loc) + public RecipeClone(final ResourceLocation loc) { super(loc); } @@ -177,9 +179,9 @@ public boolean canFit(final int width, final int height) public boolean complete(final IPoweredProgress tile) { boolean completed = false; - for (final ReviveMatcher matcher : RecipeFossilRevive.MATCHERS) + for (final ReviveMatcher matcher : RecipeClone.MATCHERS) if (completed = matcher.complete(tile)) break; - if (!completed) completed = RecipeFossilRevive.ANYMATCHER.complete(tile); + if (!completed) completed = RecipeClone.ANYMATCHER.complete(tile); if (completed) { final List remaining = Lists.newArrayList(this.getRemainingItems(tile.getCraftMatrix())); @@ -203,7 +205,7 @@ public boolean complete(final IPoweredProgress tile) @Override public Function getCostFunction() { - return RecipeFossilRevive.ENERGYNEED; + return RecipeClone.ENERGYNEED; } @Override @@ -215,32 +217,32 @@ public ItemStack getCraftingResult(final CraftingInventory inv) @Override public int getEnergyCost(final IPoweredProgress tile) { - for (final ReviveMatcher matcher : RecipeFossilRevive.MATCHERS) - if (RecipeFossilRevive.getEntry(matcher, tile) != Database.missingno) return matcher.getEnergyCost(); - return RecipeFossilRevive.ANYMATCHER.getEnergyCost(); + for (final ReviveMatcher matcher : RecipeClone.MATCHERS) + if (RecipeClone.getEntry(matcher, tile) != Database.missingno) return matcher.getEnergyCost(); + return RecipeClone.ANYMATCHER.getEnergyCost(); } public PokedexEntry getPokedexEntry(final IPoweredProgress tile) { PokedexEntry entry = Database.missingno; - for (final ReviveMatcher matcher : RecipeFossilRevive.MATCHERS) - if ((entry = RecipeFossilRevive.getEntry(matcher, tile)) != Database.missingno) return entry; - return RecipeFossilRevive.getEntry(RecipeFossilRevive.ANYMATCHER, tile); + for (final ReviveMatcher matcher : RecipeClone.MATCHERS) + if ((entry = RecipeClone.getEntry(matcher, tile)) != Database.missingno) return entry; + return RecipeClone.getEntry(RecipeClone.ANYMATCHER, tile); } @Override public IRecipeSerializer getSerializer() { - return RecipeFossilRevive.SERIALIZER; + return RecipeClone.SERIALIZER; } /** Used to check if a recipe matches current crafting inventory */ @Override public boolean matches(final CraftingInventory inv, final World worldIn) { - for (final ReviveMatcher matcher : RecipeFossilRevive.MATCHERS) + for (final ReviveMatcher matcher : RecipeClone.MATCHERS) if (matcher.getEntry(inv, worldIn) != Database.missingno) return true; - return RecipeFossilRevive.ANYMATCHER.getEntry(inv, worldIn) != Database.missingno; + return RecipeClone.ANYMATCHER.getEntry(inv, worldIn) != Database.missingno; } @Override @@ -251,8 +253,8 @@ public NonNullList getRemainingItems(final CraftingInventory inv) final PoweredCraftingInventory inv_p = (PoweredCraftingInventory) inv; if (!(inv_p.inventory instanceof ClonerTile)) return nonnulllist; final ClonerTile tile = (ClonerTile) inv_p.inventory; - ReviveMatcher matcher = RecipeFossilRevive.ANYMATCHER; - for (final ReviveMatcher matcher2 : RecipeFossilRevive.MATCHERS) + ReviveMatcher matcher = RecipeClone.ANYMATCHER; + for (final ReviveMatcher matcher2 : RecipeClone.MATCHERS) if (matcher2.getEntry(inv, tile.getWorld()) != Database.missingno) { matcher = matcher2; diff --git a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeExtract.java b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeExtract.java index b978316995..951b1a9b7e 100644 --- a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeExtract.java +++ b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeExtract.java @@ -8,6 +8,7 @@ import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.SpecialRecipeSerializer; import net.minecraft.nbt.CompoundNBT; @@ -141,8 +142,19 @@ public NonNullList getRemainingItems(final CraftingInventory inv) for (int i = 0; i < nonnulllist.size(); ++i) { final ItemStack item = inv.getStackInSlot(i); - if (i == 0 && keepDNA) nonnulllist.set(i, item); if (i == 1 && keepSelector) nonnulllist.set(i, item); + if (i == 2) + { + final boolean potion = item.getItem() == Items.POTION; + final boolean multiple = item.getCount() > 1; + if (keepDNA) nonnulllist.set(i, item); + else if (potion) nonnulllist.set(i, new ItemStack(Items.GLASS_BOTTLE)); + else if (!multiple) + { + item.setTag(null); + nonnulllist.set(i, item.copy()); + } + } if (item.hasContainerItem()) nonnulllist.set(i, item.getContainerItem()); } tile.override_selector = ItemStack.EMPTY; diff --git a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeHandlers.java b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeHandlers.java index 421bb3fd51..b0839dd4a1 100644 --- a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeHandlers.java +++ b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeHandlers.java @@ -23,8 +23,8 @@ import pokecube.adventures.blocks.genetics.cloner.ClonerTile; import pokecube.adventures.blocks.genetics.helper.ClonerHelper; import pokecube.adventures.blocks.genetics.helper.ClonerHelper.DNAPack; -import pokecube.adventures.blocks.genetics.helper.recipe.RecipeFossilRevive.AnyMatcher; -import pokecube.adventures.blocks.genetics.helper.recipe.RecipeFossilRevive.ReviveMatcher; +import pokecube.adventures.blocks.genetics.helper.recipe.RecipeClone.AnyMatcher; +import pokecube.adventures.blocks.genetics.helper.recipe.RecipeClone.ReviveMatcher; import pokecube.adventures.blocks.genetics.helper.recipe.RecipeSelector.SelectorValue; import pokecube.adventures.events.CloneEvent; import pokecube.core.PokecubeCore; @@ -68,7 +68,7 @@ public static class RecipeMatcher implements ReviveMatcher boolean tame = false; int level = AnyMatcher.level; int priority = 100; - int energy = RecipeFossilRevive.ENERGYCOST; + int energy = RecipeClone.ENERGYCOST; public RecipeMatcher(final PokedexEntry entry) { @@ -80,7 +80,7 @@ public boolean complete(final IPoweredProgress tile) { final World world = ((TileEntity) tile).getWorld(); final BlockPos pos = ((TileEntity) tile).getPos(); - final PokedexEntry entry = RecipeFossilRevive.getEntry(this, tile); + final PokedexEntry entry = RecipeClone.getEntry(this, tile); if (entry == Database.missingno) return false; final boolean tame = !entry.isLegendary() && this.tame; MobEntity entity = PokecubeCore.createPokemob(entry, world); @@ -218,8 +218,8 @@ public void manageRecipe(final XMLRecipe recipe) throws NullPointerException for (final String s : remain) matcher.remains.add(Integer.parseInt(s)); } - RecipeFossilRevive.MATCHERS.add(matcher); - RecipeFossilRevive.MATCHERS.sort((o1, o2) -> o1.priority() - o2.priority()); + RecipeClone.MATCHERS.add(matcher); + RecipeClone.MATCHERS.sort((o1, o2) -> o1.priority() - o2.priority()); } } diff --git a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeSplice.java b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeSplice.java index 02431b9ebc..483e1f4f07 100644 --- a/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeSplice.java +++ b/src/main/java/pokecube/adventures/blocks/genetics/helper/recipe/RecipeSplice.java @@ -112,8 +112,8 @@ public NonNullList getRemainingItems(final CraftingInventory inv) { final ItemStack item = inv.getStackInSlot(i); if (i == 0 && keepDNA) nonnulllist.set(i, item); + else if (i == 0 && item.getItem() == Items.POTION) nonnulllist.set(i, new ItemStack(Items.GLASS_BOTTLE)); if (i == 1 && keepSelector) nonnulllist.set(i, item); - if (i == 0 && item.getItem() == Items.POTION) nonnulllist.set(i, new ItemStack(Items.GLASS_BOTTLE)); if (item.hasContainerItem()) nonnulllist.set(i, item.getContainerItem()); } tile.override_selector = ItemStack.EMPTY; diff --git a/src/main/java/pokecube/compat/jei/categories/cloner/Category.java b/src/main/java/pokecube/compat/jei/categories/cloner/Category.java index bac67cda1d..a0d3247d46 100644 --- a/src/main/java/pokecube/compat/jei/categories/cloner/Category.java +++ b/src/main/java/pokecube/compat/jei/categories/cloner/Category.java @@ -5,9 +5,9 @@ import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; import net.minecraft.util.ResourceLocation; -import pokecube.adventures.blocks.genetics.helper.recipe.RecipeFossilRevive; +import pokecube.adventures.blocks.genetics.helper.recipe.RecipeClone; -public class Category implements IRecipeCategory +public class Category implements IRecipeCategory { public Category() @@ -30,7 +30,7 @@ public IDrawable getIcon() } @Override - public Class getRecipeClass() + public Class getRecipeClass() { // TODO Auto-generated method stub return null; @@ -51,13 +51,13 @@ public ResourceLocation getUid() } @Override - public void setIngredients(final RecipeFossilRevive arg0, final IIngredients arg1) + public void setIngredients(final RecipeClone arg0, final IIngredients arg1) { // TODO Auto-generated method stub } @Override - public void setRecipe(final IRecipeLayout arg0, final RecipeFossilRevive arg1, final IIngredients arg2) + public void setRecipe(final IRecipeLayout arg0, final RecipeClone arg1, final IIngredients arg2) { // TODO Auto-generated method stub diff --git a/src/main/java/pokecube/compat/jei/categories/evolution/Category.java b/src/main/java/pokecube/compat/jei/categories/evolution/Category.java index 127fee1dd2..60d66c3a48 100644 --- a/src/main/java/pokecube/compat/jei/categories/evolution/Category.java +++ b/src/main/java/pokecube/compat/jei/categories/evolution/Category.java @@ -5,9 +5,9 @@ import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; import net.minecraft.util.ResourceLocation; -import pokecube.adventures.blocks.genetics.helper.recipe.RecipeFossilRevive; +import pokecube.adventures.blocks.genetics.helper.recipe.RecipeClone; -public class Category implements IRecipeCategory +public class Category implements IRecipeCategory { public Category() @@ -30,7 +30,7 @@ public IDrawable getIcon() } @Override - public Class getRecipeClass() + public Class getRecipeClass() { // TODO Auto-generated method stub return null; @@ -51,13 +51,13 @@ public ResourceLocation getUid() } @Override - public void setIngredients(final RecipeFossilRevive arg0, final IIngredients arg1) + public void setIngredients(final RecipeClone arg0, final IIngredients arg1) { // TODO Auto-generated method stub } @Override - public void setRecipe(final IRecipeLayout arg0, final RecipeFossilRevive arg1, final IIngredients arg2) + public void setRecipe(final IRecipeLayout arg0, final RecipeClone arg1, final IIngredients arg2) { // TODO Auto-generated method stub diff --git a/src/main/java/pokecube/compat/jei/categories/interaction/Category.java b/src/main/java/pokecube/compat/jei/categories/interaction/Category.java index db85b2199c..25e62bd939 100644 --- a/src/main/java/pokecube/compat/jei/categories/interaction/Category.java +++ b/src/main/java/pokecube/compat/jei/categories/interaction/Category.java @@ -5,9 +5,9 @@ import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; import net.minecraft.util.ResourceLocation; -import pokecube.adventures.blocks.genetics.helper.recipe.RecipeFossilRevive; +import pokecube.adventures.blocks.genetics.helper.recipe.RecipeClone; -public class Category implements IRecipeCategory +public class Category implements IRecipeCategory { public Category() @@ -30,7 +30,7 @@ public IDrawable getIcon() } @Override - public Class getRecipeClass() + public Class getRecipeClass() { // TODO Auto-generated method stub return null; @@ -51,13 +51,13 @@ public ResourceLocation getUid() } @Override - public void setIngredients(final RecipeFossilRevive arg0, final IIngredients arg1) + public void setIngredients(final RecipeClone arg0, final IIngredients arg1) { // TODO Auto-generated method stub } @Override - public void setRecipe(final IRecipeLayout arg0, final RecipeFossilRevive arg1, final IIngredients arg2) + public void setRecipe(final IRecipeLayout arg0, final RecipeClone arg1, final IIngredients arg2) { // TODO Auto-generated method stub diff --git a/src/main/java/pokecube/compat/jei/categories/move/Category.java b/src/main/java/pokecube/compat/jei/categories/move/Category.java index 9d65a0d768..6453dfbae5 100644 --- a/src/main/java/pokecube/compat/jei/categories/move/Category.java +++ b/src/main/java/pokecube/compat/jei/categories/move/Category.java @@ -5,9 +5,9 @@ import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.category.IRecipeCategory; import net.minecraft.util.ResourceLocation; -import pokecube.adventures.blocks.genetics.helper.recipe.RecipeFossilRevive; +import pokecube.adventures.blocks.genetics.helper.recipe.RecipeClone; -public class Category implements IRecipeCategory +public class Category implements IRecipeCategory { public Category() @@ -30,7 +30,7 @@ public IDrawable getIcon() } @Override - public Class getRecipeClass() + public Class getRecipeClass() { // TODO Auto-generated method stub return null; @@ -51,13 +51,13 @@ public ResourceLocation getUid() } @Override - public void setIngredients(final RecipeFossilRevive arg0, final IIngredients arg1) + public void setIngredients(final RecipeClone arg0, final IIngredients arg1) { // TODO Auto-generated method stub } @Override - public void setRecipe(final IRecipeLayout arg0, final RecipeFossilRevive arg1, final IIngredients arg2) + public void setRecipe(final IRecipeLayout arg0, final RecipeClone arg1, final IIngredients arg2) { // TODO Auto-generated method stub diff --git a/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java b/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java index 82425c0278..571c6329e5 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/HungerTask.java @@ -341,8 +341,7 @@ public boolean shouldRun() // Apply cooldowns and increment hunger. this.pokemob.setHungerCooldown(this.pokemob.getHungerCooldown() - hungerTicks); - if (!this.hitThreshold(HungerTask.HUNTTHRESHOLD)) this.pokemob.setHungerTime(this.pokemob.getHungerTime() - + hungerTicks); + this.pokemob.setHungerTime(this.pokemob.getHungerTime() + hungerTicks); this.calculateHunger(); diff --git a/src/main/java/pokecube/core/handlers/events/SpawnHandler.java b/src/main/java/pokecube/core/handlers/events/SpawnHandler.java index cf2a871e9d..3a8b877fd9 100644 --- a/src/main/java/pokecube/core/handlers/events/SpawnHandler.java +++ b/src/main/java/pokecube/core/handlers/events/SpawnHandler.java @@ -241,7 +241,6 @@ public World getWorld() IPokemob pokemob = CapabilityPokemob.getPokemobFor(MobEntity); if (pokemob != null) { - final long time = System.nanoTime(); int maxXP = 10; int level = 1; From 0676f4ce3a37b9dab4a19436865dfea6e00c1ebd Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 10:15:11 -0400 Subject: [PATCH 17/27] fixes some issues relating to pokemob hitbox locations this should address #389 --- .../pokecube/core/entity/pokemobs/helper/PokemobBase.java | 1 - .../pokecube/core/entity/pokemobs/helper/PokemobRidable.java | 3 +-- src/main/resources/META-INF/accesstransformer.cfg | 3 +++ .../pokecube_mobs/database/pokemobs/pokemobs_offsets.json | 4 ++++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobBase.java b/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobBase.java index 70b5ab652a..43e7bd0e47 100644 --- a/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobBase.java +++ b/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobBase.java @@ -20,7 +20,6 @@ public abstract class PokemobBase extends ShoulderRidingEntity implements IEntit IMobColourable { public final DefaultPokemob pokemobCap; - protected EntitySize size; public PokemobBase(final EntityType type, final World worldIn) { diff --git a/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobRidable.java b/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobRidable.java index 78d0668001..43dd7c9618 100644 --- a/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobRidable.java +++ b/src/main/java/pokecube/core/entity/pokemobs/helper/PokemobRidable.java @@ -119,7 +119,6 @@ public void updateSeat(final int index, final UUID id) { toSet = new Seat(toSet.seat, id); this.dataManager.set(PokemobRidable.SEAT[index], toSet); - } } @@ -140,7 +139,7 @@ protected void initSeats() final float dx = this.pokemobCap.getPokedexEntry().width * this.pokemobCap.getSize(), dz = this.pokemobCap .getPokedexEntry().length * this.pokemobCap.getSize(); seat.x *= dx; - seat.y *= this.getHeight(); + seat.y *= this.pokemobCap.getPokedexEntry().height * this.pokemobCap.getSize(); seat.z *= dz; this.getSeat(index).seat = seat; } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 2da2c86724..64565a19b8 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -10,6 +10,9 @@ public net.minecraft.entity.Entity field_70165_t # posX public net.minecraft.entity.Entity field_70163_u # posY public net.minecraft.entity.Entity field_70161_v # posZ +public net.minecraft.entity.EntityType field_220359_bi # size +public net.minecraft.entity.Entity field_213325_aI # size + public net.minecraft.entity.passive.SheepEntity field_200206_bz # WOOL_BY_COLOR protected net.minecraft.entity.merchant.villager.VillagerEntity func_213744_a(Lnet/minecraft/entity/ai/brain/Brain;)V # initBrain diff --git a/src/main/resources/data/pokecube_mobs/database/pokemobs/pokemobs_offsets.json b/src/main/resources/data/pokecube_mobs/database/pokemobs/pokemobs_offsets.json index 8a98820d93..4522d6bfbb 100644 --- a/src/main/resources/data/pokecube_mobs/database/pokemobs/pokemobs_offsets.json +++ b/src/main/resources/data/pokecube_mobs/database/pokemobs/pokemobs_offsets.json @@ -5,6 +5,10 @@ "name": "Doduo", "ridden_offsets": "0,0.25,-0.5" }, + { + "name": "Lapras", + "ridden_offsets": "0,0.4,0.0:0.5,0.4,0.0:-0.5,0.4,0" + }, { "name": "Rayquaza", "ridden_offsets": "0,0.75,0.15:0,0.75,0.0:0,0.75,-0.15" From fa2bd2b767fbea8d570ea9e78c0d9721975e99b6 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 13:23:50 -0400 Subject: [PATCH 18/27] More AI re-arrangement Also added in initial frameworks for some villager professions, or healing and for professor Most of these changes were a result of moving the AI tasks around, rather than actual functional changes --- .../java/pokecube/adventures/PokecubeAdv.java | 71 ++- .../adventures/ai/poi/PointsOfInterest.java | 40 ++ .../adventures/ai/poi/Professions.java | 26 + .../adventures/ai/tasks/AIBattle.java | 5 +- .../adventures/ai/tasks/AITrainerAgro.java | 6 +- .../capabilities/utils/TypeTrainer.java | 2 +- .../entity/trainer/TrainerBase.java | 1 + .../java/pokecube/core/PokecubeItems.java | 41 +- .../pokecube/core/ai/brain/BrainUtils.java | 46 ++ .../core/ai/logic/LogicInMaterials.java | 8 +- .../java/pokecube/core/ai/tasks/Tasks.java | 21 +- .../core/ai/tasks/combat/FindTargetsTask.java | 576 ------------------ .../combat/{ => attacks}/SelectMoveTask.java | 3 +- .../combat/{ => attacks}/UseAttacksTask.java | 55 +- .../combat/management/CallForHelpTask.java | 106 ++++ .../combat/management/FindTargetsTask.java | 309 ++++++++++ .../ForgetTargetTask.java} | 122 +++- .../combat/{ => movement}/CicleTask.java | 3 +- .../combat/{ => movement}/DodgeTask.java | 3 +- .../tasks/combat/{ => movement}/LeapTask.java | 2 +- .../core/ai/tasks/idle/GuardEggTask.java | 4 +- .../pokecube/core/ai/tasks/idle/MateTask.java | 22 +- .../java/pokecube/core/database/Database.java | 35 +- .../pokecube/core/database/PokedexEntry.java | 4 +- .../database/recipes/XMLRecipeHandler.java | 8 +- .../database/rewards/XMLRewardsHandler.java | 8 +- .../java/pokecube/core/entity/npc/NpcMob.java | 8 +- .../pokecube/core/entity/npc/NpcType.java | 13 + .../java/pokecube/core/handlers/Config.java | 2 +- .../handlers/events/PokemobEventsHandler.java | 9 +- .../capabilities/impl/PokemobMoves.java | 3 +- .../capabilities/impl/PokemobOwned.java | 3 +- .../capabilities/impl/PokemobSexed.java | 6 +- .../commandhandlers/AttackEntityHandler.java | 4 +- .../items/pokecubes/EntityPokecubeBase.java | 4 +- .../pokecubes/helper/CaptureManager.java | 4 +- .../items/pokemobeggs/EntityPokemobEgg.java | 3 +- .../core/moves/PokemobTerrainEffects.java | 51 +- .../moves/damage/TerrainDamageSource.java | 26 +- .../core/moves/templates/Move_Basic.java | 3 +- .../core/moves/templates/Move_Terrain.java | 8 +- .../java/pokecube/core/utils/AITools.java | 8 +- .../mobs/moves/attacks/special/Teleport.java | 4 +- .../mobs/moves/attacks/special/Transform.java | 4 +- .../mobs/moves/attacks/special/Whirlwind.java | 4 +- .../mobs/moves/world/ActionTeleport.java | 4 +- .../client/render/animation/AnimationXML.java | 8 +- .../thut/core/client/render/mca/McaXML.java | 7 +- .../thut/core/client/render/x3d/X3dXML.java | 7 +- src/main/java/thut/core/xml/bind/Factory.java | 8 +- .../resources/META-INF/accesstransformer.cfg | 2 + 51 files changed, 930 insertions(+), 800 deletions(-) create mode 100644 src/main/java/pokecube/adventures/ai/poi/PointsOfInterest.java create mode 100644 src/main/java/pokecube/adventures/ai/poi/Professions.java delete mode 100644 src/main/java/pokecube/core/ai/tasks/combat/FindTargetsTask.java rename src/main/java/pokecube/core/ai/tasks/combat/{ => attacks}/SelectMoveTask.java (98%) rename src/main/java/pokecube/core/ai/tasks/combat/{ => attacks}/UseAttacksTask.java (83%) create mode 100644 src/main/java/pokecube/core/ai/tasks/combat/management/CallForHelpTask.java create mode 100644 src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java rename src/main/java/pokecube/core/ai/tasks/combat/{ManageTargetTask.java => management/ForgetTargetTask.java} (61%) rename src/main/java/pokecube/core/ai/tasks/combat/{ => movement}/CicleTask.java (97%) rename src/main/java/pokecube/core/ai/tasks/combat/{ => movement}/DodgeTask.java (98%) rename src/main/java/pokecube/core/ai/tasks/combat/{ => movement}/LeapTask.java (98%) diff --git a/src/main/java/pokecube/adventures/PokecubeAdv.java b/src/main/java/pokecube/adventures/PokecubeAdv.java index b9de64d295..7b6538fb90 100644 --- a/src/main/java/pokecube/adventures/PokecubeAdv.java +++ b/src/main/java/pokecube/adventures/PokecubeAdv.java @@ -8,12 +8,14 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.EntityType; +import net.minecraft.entity.merchant.villager.VillagerProfession; import net.minecraft.inventory.container.ContainerType; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.ResourceLocation; +import net.minecraft.village.PointOfInterestType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.TextureStitchEvent; @@ -25,6 +27,8 @@ import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import pokecube.adventures.advancements.Triggers; +import pokecube.adventures.ai.poi.PointsOfInterest; +import pokecube.adventures.ai.poi.Professions; import pokecube.adventures.blocks.BlockEventHandler; import pokecube.adventures.blocks.afa.AfaBlock; import pokecube.adventures.blocks.afa.AfaContainer; @@ -159,6 +163,18 @@ public static void registerRecipes(final RegistryEvent.Register event) + { + PointsOfInterest.register(event); + } + + @SubscribeEvent + public static void registerProfessions(final RegistryEvent.Register event) + { + Professions.register(event); + } + @SubscribeEvent public static void registerTiles(final RegistryEvent.Register> event) { @@ -212,32 +228,36 @@ public static void textureStitch(final TextureStitchEvent.Pre event) public static final Map BADGES = Maps.newHashMap(); public static final Map BADGEINV = Maps.newHashMap(); - static void init() + static + { + PokecubeAdv.AFA = new AfaBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.COMMANDER = new CommanderBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.DAYCARE = new DaycareBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.CLONER = new ClonerBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.EXTRACTOR = new ExtractorBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.SPLICER = new SplicerBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.SIPHON = new SiphonBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.WARPPAD = new WarppadBlock(Block.Properties.create(Material.IRON)); + PokecubeAdv.EXPSHARE = new Item(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)); + PokecubeAdv.LINKER = new Linker(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)); + PokecubeAdv.BAG = new BagItem(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)); + PokecubeAdv.TRAINEREDITOR = new TrainerEditor(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)); + } + + private static void init() { - PokecubeAdv.AFA = new AfaBlock(Block.Properties.create(Material.IRON)).setRegistryName(PokecubeAdv.MODID, - "afa"); - PokecubeAdv.COMMANDER = new CommanderBlock(Block.Properties.create(Material.IRON)).setRegistryName( - PokecubeAdv.MODID, "commander"); - PokecubeAdv.DAYCARE = new DaycareBlock(Block.Properties.create(Material.IRON)).setRegistryName( - PokecubeAdv.MODID, "daycare"); - PokecubeAdv.CLONER = new ClonerBlock(Block.Properties.create(Material.IRON)).setRegistryName(PokecubeAdv.MODID, - "cloner"); - PokecubeAdv.EXTRACTOR = new ExtractorBlock(Block.Properties.create(Material.IRON)).setRegistryName( - PokecubeAdv.MODID, "extractor"); - PokecubeAdv.SPLICER = new SplicerBlock(Block.Properties.create(Material.IRON)).setRegistryName( - PokecubeAdv.MODID, "splicer"); - PokecubeAdv.SIPHON = new SiphonBlock(Block.Properties.create(Material.IRON)).setRegistryName(PokecubeAdv.MODID, - "siphon"); - PokecubeAdv.WARPPAD = new WarppadBlock(Block.Properties.create(Material.IRON)).setRegistryName( - PokecubeAdv.MODID, "warppad"); - PokecubeAdv.EXPSHARE = new Item(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)).setRegistryName( - PokecubeAdv.MODID, "exp_share"); - PokecubeAdv.LINKER = new Linker(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)).setRegistryName( - PokecubeAdv.MODID, "linker"); - PokecubeAdv.BAG = new BagItem(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)).setRegistryName( - PokecubeAdv.MODID, "bag"); - PokecubeAdv.TRAINEREDITOR = new TrainerEditor(new Item.Properties().group(PokecubeItems.POKECUBEITEMS)) - .setRegistryName(PokecubeAdv.MODID, "trainer_editor"); + PokecubeAdv.AFA.setRegistryName(PokecubeAdv.MODID, "afa"); + PokecubeAdv.COMMANDER.setRegistryName(PokecubeAdv.MODID, "commander"); + PokecubeAdv.DAYCARE.setRegistryName(PokecubeAdv.MODID, "daycare"); + PokecubeAdv.CLONER.setRegistryName(PokecubeAdv.MODID, "cloner"); + PokecubeAdv.EXTRACTOR.setRegistryName(PokecubeAdv.MODID, "extractor"); + PokecubeAdv.SPLICER.setRegistryName(PokecubeAdv.MODID, "splicer"); + PokecubeAdv.SIPHON.setRegistryName(PokecubeAdv.MODID, "siphon"); + PokecubeAdv.WARPPAD.setRegistryName(PokecubeAdv.MODID, "warppad"); + PokecubeAdv.EXPSHARE.setRegistryName(PokecubeAdv.MODID, "exp_share"); + PokecubeAdv.LINKER.setRegistryName(PokecubeAdv.MODID, "linker"); + PokecubeAdv.BAG.setRegistryName(PokecubeAdv.MODID, "bag"); + PokecubeAdv.TRAINEREDITOR.setRegistryName(PokecubeAdv.MODID, "trainer_editor"); // Initialize advancement triggers Triggers.init(); @@ -260,7 +280,6 @@ static void init() public PokecubeAdv() { - // Initialize items and blocks PokecubeAdv.init(); FMLJavaModLoadingContext.get().getModEventBus().addListener(PokecubeAdv.proxy::setup); diff --git a/src/main/java/pokecube/adventures/ai/poi/PointsOfInterest.java b/src/main/java/pokecube/adventures/ai/poi/PointsOfInterest.java new file mode 100644 index 0000000000..2e03f21879 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/poi/PointsOfInterest.java @@ -0,0 +1,40 @@ +package pokecube.adventures.ai.poi; + +import java.util.Set; + +import com.google.common.collect.Sets; + +import net.minecraft.block.BlockState; +import net.minecraft.village.PointOfInterestType; +import net.minecraftforge.event.RegistryEvent.Register; +import pokecube.adventures.PokecubeAdv; +import pokecube.core.PokecubeItems; + +public class PointsOfInterest +{ + public static Set LABMACHINES = Sets.newHashSet(); + + public static PointOfInterestType GENELAB; + public static PointOfInterestType HEALER; + + public static void register(final Register event) + { + PointsOfInterest.LABMACHINES.addAll(PokecubeAdv.EXTRACTOR.getStateContainer().getValidStates()); + PointsOfInterest.LABMACHINES.addAll(PokecubeAdv.SPLICER.getStateContainer().getValidStates()); + PointsOfInterest.LABMACHINES.addAll(PokecubeAdv.CLONER.getStateContainer().getValidStates()); + + PointsOfInterest.GENELAB = new PointOfInterestType("pokecube_adventures:gene_lab", PointsOfInterest.LABMACHINES, + 1, null, 2); + PointsOfInterest.HEALER = new PointOfInterestType("pokecube_adventures:healer", Sets.newHashSet( + PokecubeItems.HEALER.getStateContainer().getValidStates()), 1, null, 2); + System.out.println(Sets.newHashSet(PokecubeItems.HEALER.getStateContainer().getValidStates())); + System.out.println(PointsOfInterest.LABMACHINES); + + event.getRegistry().register(PointsOfInterest.GENELAB.setRegistryName("pokecube_adventures:gene_lab")); + event.getRegistry().register(PointsOfInterest.HEALER.setRegistryName("pokecube_adventures:healer")); + + PointOfInterestType.func_221052_a(PointsOfInterest.GENELAB); + PointOfInterestType.func_221052_a(PointsOfInterest.HEALER); + } + +} diff --git a/src/main/java/pokecube/adventures/ai/poi/Professions.java b/src/main/java/pokecube/adventures/ai/poi/Professions.java new file mode 100644 index 0000000000..90b79198f8 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/poi/Professions.java @@ -0,0 +1,26 @@ +package pokecube.adventures.ai.poi; + +import com.google.common.collect.ImmutableSet; + +import net.minecraft.entity.merchant.villager.VillagerProfession; +import net.minecraftforge.event.RegistryEvent.Register; +import pokecube.core.entity.npc.NpcType; + +public class Professions +{ + public static VillagerProfession HEALER; + public static VillagerProfession PROFESSOR; + + public static void register(final Register event) + { + Professions.HEALER = new VillagerProfession("pokecube_adventures:healer", PointsOfInterest.HEALER, ImmutableSet + .of(), ImmutableSet.of()); + Professions.PROFESSOR = new VillagerProfession("pokecube_adventures:professor", PointsOfInterest.GENELAB, + ImmutableSet.of(), ImmutableSet.of()); + event.getRegistry().register(Professions.HEALER.setRegistryName("pokecube_adventures:healer")); + event.getRegistry().register(Professions.PROFESSOR.setRegistryName("pokecube_adventures:professor")); + + NpcType.HEALER.setProfession(Professions.HEALER); + NpcType.PROFESSOR.setProfession(Professions.PROFESSOR); + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/AIBattle.java b/src/main/java/pokecube/adventures/ai/tasks/AIBattle.java index 4adf158e0f..84e96064ac 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/AIBattle.java +++ b/src/main/java/pokecube/adventures/ai/tasks/AIBattle.java @@ -17,7 +17,6 @@ import pokecube.adventures.capabilities.utils.MessageState; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.Database; import pokecube.core.database.PokedexEntry; import pokecube.core.handlers.events.PCEventsHandler; @@ -55,7 +54,7 @@ private boolean checkPokemobTarget() if (!this.trainer.getOutMob().getCombatState(CombatStates.ANGRY)) this.trainer.getOutMob().setCombatState( CombatStates.ANGRY, true); // check if pokemob's target is same as trainers. - if (mobTarget != this.trainer.getTarget() && target == null) FindTargetsTask.initiateCombat(this.trainer + if (mobTarget != this.trainer.getTarget() && target == null) BrainUtils.initiateCombat(this.trainer .getOutMob().getEntity(), this.trainer.getTarget()); // Return if trainer's pokemob's target is also a pokemob. return CapabilityPokemob.getPokemobFor(BrainUtils.getAttackTarget(this.trainer.getOutMob() @@ -103,7 +102,7 @@ void doAggression() if (this.entity instanceof MobEntity) { final Entity target = BrainUtils.getAttackTarget(this.entity); - if (target instanceof LivingEntity) FindTargetsTask.initiateCombat((MobEntity) this.entity, + if (target instanceof LivingEntity) BrainUtils.initiateCombat((MobEntity) this.entity, (LivingEntity) target); } diff --git a/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java b/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java index 81466aede6..d51734f5ae 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java +++ b/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java @@ -14,7 +14,7 @@ import pokecube.adventures.capabilities.TrainerCaps; import pokecube.adventures.utils.TrainerTracker; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.handlers.events.PCEventsHandler; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; @@ -182,8 +182,8 @@ public boolean shouldRun() if (target.getRevengeTarget() == this.entity) target.setRevengeTarget(null); if (this.entity.getRevengeTarget() == target) this.entity.setRevengeTarget(null); // Reset attack targets as well. - if (target instanceof MobEntity) FindTargetsTask.deagro(target); - FindTargetsTask.deagro(this.entity); + if (target instanceof MobEntity) BrainUtils.deagro(target); + BrainUtils.deagro(this.entity); this.trainer.setTarget(null); this.trainer.resetPokemob(); diff --git a/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java b/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java index d3e7c61dca..48f4e3a3c2 100644 --- a/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java +++ b/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java @@ -35,9 +35,9 @@ import pokecube.adventures.PokecubeAdv; import pokecube.adventures.ai.tasks.AIBattle; import pokecube.adventures.ai.tasks.AICapture; -import pokecube.adventures.ai.tasks.AITrainerAgro; import pokecube.adventures.ai.tasks.AIMate; import pokecube.adventures.ai.tasks.AIRetaliate; +import pokecube.adventures.ai.tasks.AITrainerAgro; import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; import pokecube.adventures.capabilities.TrainerCaps; import pokecube.adventures.entity.trainer.TrainerBase; diff --git a/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java b/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java index 5540015627..903dfb9386 100644 --- a/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java +++ b/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java @@ -323,6 +323,7 @@ public void setMale(final boolean male) @Override public NpcType getNpcType() { + if (this.pokemobsCap == null) return super.getNpcType(); return this.pokemobsCap.getType(); } } diff --git a/src/main/java/pokecube/core/PokecubeItems.java b/src/main/java/pokecube/core/PokecubeItems.java index be5a4b55e9..1e0fc1492e 100644 --- a/src/main/java/pokecube/core/PokecubeItems.java +++ b/src/main/java/pokecube/core/PokecubeItems.java @@ -156,7 +156,7 @@ public ItemStack createIcon() private static Set errored = Sets.newHashSet(); - public static void init() + static { // Items PokecubeItems.BERRYJUICE = new Item(new Properties().food(new Food.Builder().hunger(4).saturation(0.3F).build()) @@ -170,25 +170,38 @@ public static void init() // Blocks PokecubeItems.HEALER = new HealerBlock(Block.Properties.create(Material.IRON).hardnessAndResistance(2000) - .lightValue(15)).setRegistryName(PokecubeCore.MODID, "pokecenter"); - PokecubeItems.NESTBLOCK = new NestBlock(Block.Properties.create(Material.ORGANIC)).setRegistryName( - PokecubeCore.MODID, "nest"); - PokecubeItems.REPELBLOCK = new RepelBlock(Block.Properties.create(Material.ORGANIC)).setRegistryName( - PokecubeCore.MODID, "repel"); + .lightValue(15)); + PokecubeItems.NESTBLOCK = new NestBlock(Block.Properties.create(Material.ORGANIC)); + PokecubeItems.REPELBLOCK = new RepelBlock(Block.Properties.create(Material.ORGANIC)); PokecubeItems.DYNABLOCK = new MaxBlock(Block.Properties.create(Material.ROCK).lightValue(15) - .hardnessAndResistance(2000)).setRegistryName(PokecubeCore.MODID, "dynamax"); + .hardnessAndResistance(2000)); PokecubeItems.PCTOP = new PCBlock(Block.Properties.create(Material.IRON).hardnessAndResistance(2000).lightValue( - 15), true).setRegistryName(PokecubeCore.MODID, "pc_top"); + 15), true); PokecubeItems.PCBASE = new PCBlock(Block.Properties.create(Material.IRON).hardnessAndResistance(2000) - .lightValue(15), false).setRegistryName(PokecubeCore.MODID, "pc_base"); + .lightValue(15), false); PokecubeItems.TRADER = new TraderBlock(Block.Properties.create(Material.IRON).hardnessAndResistance(2000) - .lightValue(15)).setRegistryName(PokecubeCore.MODID, "trade_machine"); + .lightValue(15)); PokecubeItems.TMMACHINE = new TMBlock(Block.Properties.create(Material.IRON).hardnessAndResistance(2000) - .lightValue(15)).setRegistryName(PokecubeCore.MODID, "tm_machine"); - PokecubeItems.SECRETBASE = new BaseBlock(Block.Properties.create(Material.ROCK).hardnessAndResistance(2000)) - .setRegistryName(PokecubeCore.MODID, "secret_base"); + .lightValue(15)); + PokecubeItems.SECRETBASE = new BaseBlock(Block.Properties.create(Material.ROCK).hardnessAndResistance(2000)); PokecubeItems.FOSSILSTONE = new Block(Block.Properties.create(Material.ROCK).hardnessAndResistance(1.5f, 10) - .harvestTool(ToolType.PICKAXE)).setRegistryName(PokecubeCore.MODID, "fossilstone"); + .harvestTool(ToolType.PICKAXE)); + } + + public static void init() + { + + // Blocks + PokecubeItems.HEALER.setRegistryName(PokecubeCore.MODID, "pokecenter"); + PokecubeItems.NESTBLOCK.setRegistryName(PokecubeCore.MODID, "nest"); + PokecubeItems.REPELBLOCK.setRegistryName(PokecubeCore.MODID, "repel"); + PokecubeItems.DYNABLOCK.setRegistryName(PokecubeCore.MODID, "dynamax"); + PokecubeItems.PCTOP.setRegistryName(PokecubeCore.MODID, "pc_top"); + PokecubeItems.PCBASE.setRegistryName(PokecubeCore.MODID, "pc_base"); + PokecubeItems.TRADER.setRegistryName(PokecubeCore.MODID, "trade_machine"); + PokecubeItems.TMMACHINE.setRegistryName(PokecubeCore.MODID, "tm_machine"); + PokecubeItems.SECRETBASE.setRegistryName(PokecubeCore.MODID, "secret_base"); + PokecubeItems.FOSSILSTONE.setRegistryName(PokecubeCore.MODID, "fossilstone"); } /** diff --git a/src/main/java/pokecube/core/ai/brain/BrainUtils.java b/src/main/java/pokecube/core/ai/brain/BrainUtils.java index 590ebdc5a9..30978fe54c 100644 --- a/src/main/java/pokecube/core/ai/brain/BrainUtils.java +++ b/src/main/java/pokecube/core/ai/brain/BrainUtils.java @@ -14,6 +14,9 @@ import net.minecraft.entity.item.ItemEntity; import net.minecraft.util.math.IPosWrapper; import pokecube.core.ai.brain.sensors.NearBlocks.NearBlock; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.interfaces.pokemob.ai.CombatStates; import thut.api.entity.ai.VectorPosWrapper; import thut.api.maths.Vector3; @@ -171,4 +174,47 @@ public static void addToBrain(final Brain brain, final List implements IAICombat, ITargetFinder -{ - - public static boolean handleDamagedTargets = true; - static - { - MinecraftForge.EVENT_BUS.register(FindTargetsTask.class); - } - - public static int DEAGROTIMER = 50; - - public static void initiateCombat(final MobEntity mob, final LivingEntity target) - { - // No target self - if (mob == target) return; - // No target null - if (target == null) return; - // No target dead - if (!target.isAlive() || target.getHealth() <= 0) return; - // No target already had target - if (target == BrainUtils.getAttackTarget(mob)) return; - - final IPokemob aggressor = CapabilityPokemob.getPokemobFor(mob); - final IPokemob targetMob = CapabilityPokemob.getPokemobFor(target); - if (targetMob != null) targetMob.setCombatState(CombatStates.ANGRY, true); - if (aggressor != null) aggressor.setCombatState(CombatStates.ANGRY, true); - - BrainUtils.setAttackTarget(mob, target); - BrainUtils.setAttackTarget(target, mob); - } - - public static void deagro(final LivingEntity mob) - { - if (mob == null) return; - final IPokemob aggressor = CapabilityPokemob.getPokemobFor(mob); - - if (aggressor != null) - { - aggressor.getTargetFinder().clear(); - aggressor.setCombatState(CombatStates.ANGRY, false); - aggressor.setCombatState(CombatStates.MATEFIGHT, false); - } - if (mob instanceof MobEntity) - { - final LivingEntity oldTarget = BrainUtils.getAttackTarget(mob); - BrainUtils.setAttackTarget(mob, null); - FindTargetsTask.deagro(oldTarget); - } - mob.getBrain().removeMemory(MemoryModules.ATTACKTARGET); - mob.getBrain().removeMemory(MemoryModules.MATE_TARGET); - } - - @SubscribeEvent - public static void livingSetTargetEvent(final LivingSetAttackTargetEvent evt) - { - if (!FindTargetsTask.handleDamagedTargets || evt.getEntity().getEntityWorld().isRemote) return; - // Only handle attack target set, not revenge target set. - if (evt.getTarget() == ((LivingEntity) evt.getEntity()).getRevengeTarget()) return; - // Prevent mob from targetting self. - if (evt.getTarget() == evt.getEntity()) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.log(Level.WARN, evt.getTarget() - + " is targetting self again.", new IllegalArgumentException()); - return; - } - - // Attempt to divert the target over to one of our mobs. - final List outmobs = PCEventsHandler.getOutMobs(evt.getTarget(), true); - outmobs.removeIf(o -> o == evt.getEntityLiving() || !o.isAlive()); - if (!outmobs.isEmpty() && evt.getEntityLiving() instanceof MobEntity) - { - Collections.sort(outmobs, (o1, o2) -> - { - final double dist1 = o1.getDistanceSq(evt.getEntityLiving()); - final double dist2 = o2.getDistanceSq(evt.getEntityLiving()); - return (int) (dist1 - dist2); - }); - final Entity nearest = outmobs.get(0); - if (nearest.getDistanceSq(evt.getEntityLiving()) < 256 && nearest instanceof LivingEntity) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Diverting agro to owner!"); - FindTargetsTask.initiateCombat((MobEntity) evt.getEntityLiving(), (LivingEntity) nearest); - return; - } - } - - final IPokemob pokemob = CapabilityPokemob.getPokemobFor(evt.getEntity()); - if (pokemob != null) - { - if (evt.getTarget() != null && pokemob.getTargetID() == evt.getTarget().getEntityId()) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Already targetted!"); - return; - } - if (evt.getTarget() == null && pokemob.getTargetID() == -1) return; - - // Prevent pokemob from targetting its owner. - if (evt.getTarget() != null && evt.getTarget().getUniqueID().equals(pokemob.getOwnerId())) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.log(Level.WARN, evt.getTarget() - + " is targetting owner.", new IllegalArgumentException()); - return; - } - final boolean force = evt.getTarget() != null && evt.getTarget().getLastAttackedEntity() == evt.getEntity(); - pokemob.onSetTarget(evt.getTarget(), force); - } - } - - /** Prevents the owner from attacking their own pokemob. */ - @SubscribeEvent - public static void onAttacked(final LivingAttackEvent event) - { - if (!FindTargetsTask.handleDamagedTargets || event.getEntity().getEntityWorld().isRemote) return; - - final DamageSource source = event.getSource(); - final LivingEntity attacked = (LivingEntity) event.getEntity(); - final IPokemob pokemobCap = CapabilityPokemob.getPokemobFor(attacked); - if (pokemobCap == null) return; - - final Entity attacker = source.getTrueSource(); - - // Camcel the event if it is from owner. - if (pokemobCap.getGeneralState(GeneralStates.TAMED) && attacker instanceof PlayerEntity && attacker - .getUniqueID().equals(pokemobCap.getOwnerId())) - { - event.setCanceled(true); - event.setResult(Result.DENY); - return; - } - } - - /** - * Prevents the owner from attacking their own pokemob, and takes care of - * properly setting attack targets for whatever was hurt. - */ - @SubscribeEvent - public static void onDamaged(final LivingDamageEvent event) - { - if (!FindTargetsTask.handleDamagedTargets || event.getEntity().getEntityWorld().isRemote) return; - - final DamageSource source = event.getSource(); - final LivingEntity attacked = (LivingEntity) event.getEntity(); - final IPokemob pokemobCap = CapabilityPokemob.getPokemobFor(attacked); - if (pokemobCap == null) return; - - Entity attacker = source.getTrueSource(); - - // Cancel the event if it is from owner. - if (pokemobCap.getGeneralState(GeneralStates.TAMED) && attacker instanceof PlayerEntity - && (PlayerEntity) attacker == pokemobCap.getOwner()) - { - event.setCanceled(true); - event.setResult(Result.DENY); - return; - } - pokemobCap.setLogicState(LogicStates.SITTING, false); - - if (attacked instanceof MobEntity) - { - LivingEntity oldTarget = BrainUtils.getAttackTarget(attacked); - // Don't include dead old targets. - if (oldTarget != null && !oldTarget.isAlive()) oldTarget = null; - - if (!(oldTarget == null && attacker != attacked && attacker instanceof LivingEntity - && oldTarget != attacker)) attacker = null; - - LivingEntity newTarget = oldTarget; - // Either keep old target, or agress the attacker. - if (oldTarget != null && BrainUtils.getAttackTarget(attacked) != oldTarget) newTarget = oldTarget; - else if (attacker instanceof LivingEntity) newTarget = (LivingEntity) attacker; - final MobEntity living = (MobEntity) attacked; - FindTargetsTask.initiateCombat(living, newTarget); - } - - } - - Vector3 v = Vector3.getNewVector(); - Vector3 v1 = Vector3.getNewVector(); - - /** - * Checks the validTargts as well as team settings, will not allow - * targetting things on the same team. - */ - final Predicate validGuardTarget = input -> - { - if (input == FindTargetsTask.this.entity) return false; - if (TeamManager.sameTeam(FindTargetsTask.this.entity, input)) return false; - if (!AITools.validTargets.test(input)) return false; - return input instanceof LivingEntity; - }; - - private int agroTimer = -1; - - private LivingEntity entityTarget = null; - - public FindTargetsTask(final IPokemob mob) - { - super(mob, ImmutableMap.of(MemoryModuleType.VISIBLE_MOBS, MemoryModuleStatus.VALUE_PRESENT)); - } - - @Override - public void clear() - { - this.agroTimer = FindTargetsTask.DEAGROTIMER; - this.entityTarget = null; - } - - /** - * Check if there are any mobs nearby that will help us.
- *
- * This is called from {@link FindTargetsTask#shouldRun()} - * - * @return someone needed help. - */ - protected boolean checkForHelp(final LivingEntity from) - { - // No need to get help against null - if (from == null) return false; - - // Not social. doesn't do this. - if (!this.pokemob.getPokedexEntry().isSocial) return false; - - // Random factor for this ai to apply - if (Math.random() > 0.01 * PokecubeCore.getConfig().hordeRateFactor) return false; - - final List ret = new ArrayList<>(); - final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); - - // Select either owner or home position as the centre of the check, - // this results in it guarding either its home or its owner. Home is - // used if it is on stay, or it has no owner. - final Vector3 centre = Vector3.getNewVector(); - if (this.pokemob.getGeneralState(GeneralStates.STAYING) || this.pokemob.getOwner() == null) centre.set( - this.pokemob.getHome()); - else centre.set(this.pokemob.getOwner()); - - if (!TerrainManager.isAreaLoaded(this.world, centre, 18)) return false; - - // pokemobs = - // this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS); - - // We check for whether it is the same species and, has the same owner - // (including null) or is on the team. - final Predicate relationCheck = input -> - { - final IPokemob other = CapabilityPokemob.getPokemobFor(input); - // No pokemob, no helps. - if (other == null) return false; - // Not related, no helps. - if (!other.getPokedexEntry().areRelated(FindTargetsTask.this.pokemob.getPokedexEntry())) return false; - // Same owner (owned or null), helps. - if (other.getOwnerId() == null && FindTargetsTask.this.pokemob.getOwnerId() == null || other - .getOwnerId() != null && other.getOwnerId().equals(FindTargetsTask.this.pokemob.getOwnerId())) - return true; - // Same team, helps. - if (TeamManager.sameTeam(input, FindTargetsTask.this.entity)) return true; - return false; - }; - - // Only allow valid guard targets. - for (final LivingEntity o : pokemobs) - if (relationCheck.test(o)) ret.add(o); - - for (final LivingEntity mob : ret) - { - if (!(mob instanceof MobEntity)) continue; - // Only agress mobs that can see you are really under attack. - if (!mob.canEntityBeSeen(this.entity)) continue; - // Only agress if not currently in combat. - if (BrainUtils.hasAttackTarget(mob)) continue; - // Make all valid ones agress the target. - this.setAttackTarget((MobEntity) mob, from); - } - - return false; - } - - /** - * Check for and agress any guard targets.
- *
- * This is called from {@link FindTargetsTask#run()} - * - * @return a guard target was found - */ - protected boolean checkGuard() - { - // Disabled via the boolean config. - if (!PokecubeCore.getConfig().guardModeEnabled) return false; - - final int rate = PokecubeCore.getConfig().guardTickRate; - // Disable via rate out of bounds, or not correct time in the rate. - if (rate <= 0 || this.entity.ticksExisted % rate != 0) return false; - - // Select either owner or home position as the centre of the check, - // this results in it guarding either its home or its owner. Home is - // used if it is on stay, or it has no owner. - final Vector3 centre = Vector3.getNewVector(); - if (this.pokemob.getGeneralState(GeneralStates.STAYING) || this.pokemob.getOwner() == null) centre.set( - this.pokemob.getHome()); - else centre.set(this.pokemob.getOwner()); - - if (!TerrainManager.isAreaLoaded(this.world, centre, PokecubeCore.getConfig().guardSearchDistance + 2)) - return false; - - final List ret = new ArrayList<>(); - final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); - // Only allow valid guard targets. - for (final LivingEntity o : pokemobs) - if (this.validGuardTarget.test(o)) ret.add(o); - ret.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); - if (ret.isEmpty()) return false; - - LivingEntity newtarget = null; - double closest = Integer.MAX_VALUE; - final Vector3 here = this.v1.set(this.entity, true); - - // Select closest visible guard target. - for (final LivingEntity e : ret) - { - final double dist = e.getDistanceSq(this.entity); - this.v.set(e, true); - if (dist < closest && here.isVisible(this.world, this.v)) - { - closest = dist; - newtarget = e; - } - } - - // Agro the target. - if (newtarget != null && Vector3.isVisibleEntityFromEntity(this.entity, newtarget)) - { - this.setAttackTarget(this.entity, newtarget); - return true; - } - return false; - } - - protected void setAttackTarget(final MobEntity attacker, final LivingEntity target) - { - if (target == null) - { - FindTargetsTask.deagro(attacker); - this.clear(); - } - else - { - FindTargetsTask.initiateCombat(attacker, target); - this.entityTarget = target; - } - } - - /** - * Check if there is a target to hunt, if so, sets it as target.
- *
- * This is called from {@link FindTargetsTask#run()} - * - * @return if a hunt target was found. - */ - protected boolean checkHunt() - { - final int rate = PokecubeCore.getConfig().hungerTickRate; - // Disable via rate out of bounds, or not correct time in the rate. - if (rate <= 0 || this.entity.ticksExisted % rate != 0) return false; - - if (!TerrainManager.isAreaLoaded(this.world, this.entity.getPosition(), PokecubeCore - .getConfig().guardSearchDistance + 2)) return false; - - final List list = new ArrayList<>(); - final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); - list.addAll(pokemobs); - list.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); - if (list.isEmpty()) return false; - - if (!list.isEmpty()) for (final LivingEntity entity : list) - { - final IPokemob mob = CapabilityPokemob.getPokemobFor(entity); - if (mob != null && this.pokemob.getPokedexEntry().isFood(mob.getPokedexEntry()) && this.pokemob - .getLevel() > mob.getLevel() && Vector3.isVisibleEntityFromEntity(entity, entity)) - { - this.setAttackTarget(this.entity, entity); - return true; - } - } - return false; - } - - /** - * Check if owner is under attack, if so, agress the attacker.
- *
- * This is called from {@link FindTargetsTask#run()} - * - * @return if target was found. - */ - protected boolean checkOwner() - { - final Entity owner = this.pokemob.getOwner(); - - // Only apply if has owner. - if (owner == null) return false; - // Only apply if owner is close. - if (this.entity.getDistanceSq(owner) > 64) return false; - - final int rate = PokecubeCore.getConfig().guardTickRate; - // Disable via rate out of bounds, or not correct time in the rate. - if (rate <= 0 || this.entity.ticksExisted % rate != 0) return false; - - if (!TerrainManager.isAreaLoaded(this.world, this.entity.getPosition(), PokecubeCore - .getConfig().guardSearchDistance + 2)) return false; - - final List list = new ArrayList<>(); - final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); - list.addAll(pokemobs); - list.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); - if (list.isEmpty()) return false; - - final Entity old = BrainUtils.getAttackTarget(this.entity); - final IOwnable oldOwnable = OwnableCaps.getOwnable(old); - final Entity oldOwner = oldOwnable != null ? oldOwnable.getOwner(this.world) : null; - - if (!list.isEmpty()) for (final LivingEntity entity : list) - { - if (oldOwner != null && entity == oldOwner) return false; - final LivingEntity targ = BrainUtils.getAttackTarget(entity); - if (entity instanceof MobEntity && targ != null && targ.equals(owner) && Vector3.isVisibleEntityFromEntity( - entity, entity)) - { - this.setAttackTarget(this.entity, entity); - return true; - } - } - return false; - } - - @Override - public void reset() - { - } - - @Override - public void run() - { - final LivingEntity targ = BrainUtils.getAttackTarget(this.entity); - // No need to find a target if we have one. - if (targ != null) - { - // If target is dead, lets forget about it. - if (!targ.isAlive() || targ.getHealth() <= 0) this.clear(); - return; - } - - // If hunting, look for valid prey, and if found, agress it. - if (!this.pokemob.getLogicState(LogicStates.SITTING) && this.pokemob.isCarnivore() && this.pokemob - .getCombatState(CombatStates.HUNTING)) if (this.checkHunt()) return; - // If guarding, look for mobs not on the same team as you, and if you - // find them, try to agress them. - if (this.pokemob.getCombatState(CombatStates.GUARDING)) if (this.checkGuard()) return; - } - - @Override - public boolean shouldRun() - { - if (!this.pokemob.isRoutineEnabled(AIRoutine.AGRESSIVE)) return false; - - if (!this.entity.getBrain().hasMemory(MemoryModuleType.VISIBLE_MOBS)) return false; - - // Ensure the correct owner is tracked. - this.pokemob.getOwner(this.world); - - LivingEntity target = BrainUtils.getAttackTarget(this.entity); - - // Don't look for targets if you are sitting. - final boolean ret = target == null && !this.pokemob.getLogicState(LogicStates.SITTING); - - // Target is too far away, lets forget it. - if (target != null && this.entity.getDistance(target) > PokecubeCore.getConfig().chaseDistance) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Forgetting Target due to distance. {} -> {}", - this.entity, target); - this.setAttackTarget(this.entity, null); - return false; - } - - // Check if the pokemob is set to follow, and if so, look for mobs - // nearby trying to attack the owner of the pokemob, if any such are - // found, try to aggress them immediately. - if (!this.pokemob.getGeneralState(GeneralStates.STAYING) && this.pokemob.getGeneralState(GeneralStates.TAMED)) - if (this.checkOwner()) return false; - - /* - * Check for others to try to help you. - */ - if (this.checkForHelp(target)) return false; - - if (target == null && this.entityTarget != null) - { - target = this.entityTarget; - if (this.agroTimer == -1) this.agroTimer = FindTargetsTask.DEAGROTIMER; - else - { - this.agroTimer--; - if (this.agroTimer == -1 || !this.pokemob.getCombatState(CombatStates.ANGRY)) this.clear(); - else if (this.entity.getDistance(target) < PokecubeCore.getConfig().chaseDistance) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug( - "Somehow lost target? Well, found it back again! {} -> {}", this.entity, this.entityTarget); - this.setAttackTarget(this.entity, this.entityTarget); - } - } - } - - final boolean playerNear = this.entity.getBrain().hasMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); - // If wild, randomly decided to agro a nearby player instead. - if (ret && playerNear && AITools.shouldAgroNearestPlayer.test(this.pokemob)) - { - PlayerEntity player = this.entity.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER).get(); - if (player != null && player.getDistance(this.entity) > PokecubeCore.getConfig().mobAggroRadius) - player = null; - if (player != null && Vector3.isVisibleEntityFromEntity(this.entity, player) && this.entity.getEntityWorld() - .getDifficulty().getId() > Difficulty.EASY.getId() && AITools.validTargets.test(player)) - { - this.setAttackTarget(this.entity, player); - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug( - "Found player to be angry with, agressing."); - return false; - } - } - return ret; - } - -} \ No newline at end of file diff --git a/src/main/java/pokecube/core/ai/tasks/combat/SelectMoveTask.java b/src/main/java/pokecube/core/ai/tasks/combat/attacks/SelectMoveTask.java similarity index 98% rename from src/main/java/pokecube/core/ai/tasks/combat/SelectMoveTask.java rename to src/main/java/pokecube/core/ai/tasks/combat/attacks/SelectMoveTask.java index b792bfad6f..7bd72c0c1e 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/SelectMoveTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/attacks/SelectMoveTask.java @@ -1,4 +1,4 @@ -package pokecube.core.ai.tasks.combat; +package pokecube.core.ai.tasks.combat.attacks; import java.util.Random; @@ -7,6 +7,7 @@ import net.minecraft.entity.Entity; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.tasks.combat.CombatTask; import pokecube.core.interfaces.IMoveConstants; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.Move_Base; diff --git a/src/main/java/pokecube/core/ai/tasks/combat/UseAttacksTask.java b/src/main/java/pokecube/core/ai/tasks/combat/attacks/UseAttacksTask.java similarity index 83% rename from src/main/java/pokecube/core/ai/tasks/combat/UseAttacksTask.java rename to src/main/java/pokecube/core/ai/tasks/combat/attacks/UseAttacksTask.java index 59bef1f58e..55bff52ee4 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/UseAttacksTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/attacks/UseAttacksTask.java @@ -1,4 +1,4 @@ -package pokecube.core.ai.tasks.combat; +package pokecube.core.ai.tasks.combat.attacks; import org.apache.logging.log4j.Level; @@ -13,10 +13,10 @@ import net.minecraftforge.common.util.FakePlayer; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.tasks.combat.CombatTask; import pokecube.core.interfaces.IMoveConstants; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.Move_Base; -import pokecube.core.interfaces.PokecubeMod; import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.interfaces.pokemob.ai.GeneralStates; @@ -38,7 +38,6 @@ */ public class UseAttacksTask extends CombatTask implements IAICombat { - public static int maxWildBattleDur = 600; /** The target being attacked. */ LivingEntity entityTarget; @@ -61,8 +60,6 @@ public class UseAttacksTask extends CombatTask implements IAICombat /** Speed for pathing. */ double movementSpeed; - /** Used to determine when to give up attacking. */ - protected int chaseTime; /** Used for when to execute attacks. */ protected int delayTime = -1; @@ -114,7 +111,6 @@ public void run() .getGeneralState(GeneralStates.CONTROLLED)) this.setWalkTo(this.entityTarget.getPositionVec(), this.movementSpeed, 0); this.targetLoc.set(this.entityTarget); - this.chaseTime = 0; this.waitingToStart = true; /** * Don't want to notify if the pokemob just broke out of a @@ -154,28 +150,6 @@ public void run() // No executing move state with no target location. if (this.pokemob.getCombatState(CombatStates.EXECUTINGMOVE) && this.targetLoc.isEmpty()) this.clearUseMove(); - // If it has been too long since last seen the target, give up. - if (this.chaseTime > 200) - { - this.pokemob.setCombatState(CombatStates.ANGRY, false); - this.chaseTime = 0; - if (PokecubeMod.debug) PokecubeCore.LOGGER.log(Level.INFO, "Too Long Chase, Forgetting Target: " - + this.entity + " " + this.entityTarget); - // Send deagress message and put mob on cooldown. - final ITextComponent message = new TranslationTextComponent("pokemob.deagress.timeout", this.pokemob - .getDisplayName().getFormattedText()); - try - { - this.entityTarget.sendMessage(message); - } - catch (final Exception e) - { - PokecubeCore.LOGGER.log(Level.WARN, "Error with message for " + this.entityTarget, e); - } - this.pokemob.setAttackCooldown(PokecubeCore.getConfig().pokemobagressticks); - return; - } - Move_Base move = null; move = MovesUtils.getMoveFromName(this.pokemob.getMove(this.pokemob.getMoveIndex())); if (move == null) move = MovesUtils.getMoveFromName(IMoveConstants.DEFAULT_MOVE); @@ -213,26 +187,11 @@ else if (PokecubeCore.getConfig().contactAttackDistance > 0) final boolean canSee = BrainUtil.canSee(this.entity.getBrain(), this.entityTarget); - // If can't see, increment the timer for giving up later. - if (!canSee) - { - this.chaseTime++; - if (!this.pokemob.getCombatState(CombatStates.EXECUTINGMOVE)) this.targetLoc.set(this.entityTarget).addTo(0, - this.entityTarget.getHeight() / 2, 0); - // Try to path to target if you can't see it, regardless of what - // move you have selected. - shouldPath = true; - } - else - { - // Otherwise set timer to 0, and if newly executing the move, set - // the target location as a "aim". This aiming is done so that when - // the move is fired, it is fired at the location, not the target, - // giving option to dodge. - this.chaseTime = 0; - if (!this.pokemob.getCombatState(CombatStates.EXECUTINGMOVE)) this.targetLoc.set(this.entityTarget).addTo(0, - this.entityTarget.getHeight() / 2, 0); - } + // If we have not set a move executing, we update target location. If we + // have a move executing, we leave the old location to give the target + // time to dodge needed. + if (!this.pokemob.getCombatState(CombatStates.EXECUTINGMOVE)) this.targetLoc.set(this.entityTarget).addTo(0, + this.entityTarget.getHeight() / 2, 0); final boolean isTargetDodging = this.pokemobTarget != null && this.pokemobTarget.getCombatState( CombatStates.DODGING); diff --git a/src/main/java/pokecube/core/ai/tasks/combat/management/CallForHelpTask.java b/src/main/java/pokecube/core/ai/tasks/combat/management/CallForHelpTask.java new file mode 100644 index 0000000000..7b30fecb1a --- /dev/null +++ b/src/main/java/pokecube/core/ai/tasks/combat/management/CallForHelpTask.java @@ -0,0 +1,106 @@ +package pokecube.core.ai.tasks.combat.management; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.MobEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.tasks.combat.CombatTask; +import pokecube.core.handlers.TeamManager; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; + +public class CallForHelpTask extends CombatTask +{ + boolean checked = false; + + final float chance; + + LivingEntity target = null; + + public CallForHelpTask(final IPokemob pokemob, final float chance) + { + super(pokemob); + this.chance = chance; + } + + @Override + public void reset() + { + this.checked = false; + this.target = null; + } + + /** + * Check if there are any mobs nearby that will help us.
+ *
+ * This is called from {@link FindTargetsTask#shouldRun()} + * + * @return someone needed help. + */ + protected boolean checkForHelp(final LivingEntity from) + { + // No need to get help against null + if (from == null) return false; + + // Not social. doesn't do this. + if (!this.pokemob.getPokedexEntry().isSocial) return false; + + final List ret = new ArrayList<>(); + final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); + + // We check for whether it is the same species and, has the same owner + // (including null) or is on the team. + final Predicate relationCheck = input -> + { + final IPokemob other = CapabilityPokemob.getPokemobFor(input); + // No pokemob, no helps. + if (other == null) return false; + // Not related, no helps. + if (!other.getPokedexEntry().areRelated(this.pokemob.getPokedexEntry())) return false; + // both wild, helps. + if (other.getOwnerId() == null && this.pokemob.getOwnerId() == null) return true; + // Same team, helps. + if (TeamManager.sameTeam(input, this.entity)) return true; + return false; + }; + + pokemobs.forEach(o -> + { + // Only allow valid guard targets. + if (relationCheck.test(o)) ret.add(o); + }); + + for (final LivingEntity mob : ret) + { + if (!(mob instanceof MobEntity)) continue; + // Only agress mobs that can see you are really under attack. + if (!mob.canEntityBeSeen(this.entity)) continue; + // Only agress if not currently in combat. + if (BrainUtils.hasAttackTarget(mob)) continue; + // Make all valid ones agress the target. + BrainUtils.initiateCombat((MobEntity) mob, from); + } + return false; + } + + @Override + public void run() + { + if (this.checked) return; + this.checked = true; + if (Math.random() < this.chance) return; + this.checkForHelp(this.target); + } + + @Override + public boolean shouldRun() + { + this.target = BrainUtils.getAttackTarget(this.entity); + return this.target != null; + } + +} diff --git a/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java b/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java new file mode 100644 index 0000000000..dd1b343620 --- /dev/null +++ b/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java @@ -0,0 +1,309 @@ +package pokecube.core.ai.tasks.combat.management; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import org.apache.logging.log4j.Level; + +import com.google.common.collect.ImmutableMap; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.MobEntity; +import net.minecraft.entity.ai.brain.BrainUtil; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import pokecube.core.PokecubeCore; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.tasks.TaskBase; +import pokecube.core.handlers.TeamManager; +import pokecube.core.handlers.events.PCEventsHandler; +import pokecube.core.interfaces.IMoveConstants.AIRoutine; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.IPokemob.ITargetFinder; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.interfaces.pokemob.ai.CombatStates; +import pokecube.core.interfaces.pokemob.ai.GeneralStates; +import pokecube.core.utils.AITools; +import thut.api.IOwnable; +import thut.api.OwnableCaps; +import thut.api.entity.ai.IAICombat; +import thut.api.maths.Vector3; +import thut.api.terrain.TerrainManager; + +/** This IAIRunnable is to find targets for the pokemob to try to kill. */ +public class FindTargetsTask extends TaskBase implements IAICombat, ITargetFinder +{ + + public static boolean handleDamagedTargets = true; + static + { + MinecraftForge.EVENT_BUS.register(FindTargetsTask.class); + } + + public static int DEAGROTIMER = 50; + + @SubscribeEvent + public static void livingSetTargetEvent(final LivingSetAttackTargetEvent evt) + { + if (!FindTargetsTask.handleDamagedTargets || evt.getEntity().getEntityWorld().isRemote) return; + // Only handle attack target set, not revenge target set. + if (evt.getTarget() == ((LivingEntity) evt.getEntity()).getRevengeTarget()) return; + // Prevent mob from targetting self. + if (evt.getTarget() == evt.getEntity()) + { + if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.log(Level.WARN, evt.getTarget() + + " is targetting self again.", new IllegalArgumentException()); + return; + } + + // Attempt to divert the target over to one of our mobs. + final List outmobs = PCEventsHandler.getOutMobs(evt.getTarget(), true); + outmobs.removeIf(o -> o == evt.getEntityLiving() || !o.isAlive()); + if (!outmobs.isEmpty() && evt.getEntityLiving() instanceof MobEntity) + { + Collections.sort(outmobs, (o1, o2) -> + { + final double dist1 = o1.getDistanceSq(evt.getEntityLiving()); + final double dist2 = o2.getDistanceSq(evt.getEntityLiving()); + return (int) (dist1 - dist2); + }); + final Entity nearest = outmobs.get(0); + if (nearest.getDistanceSq(evt.getEntityLiving()) < 256 && nearest instanceof LivingEntity) + { + if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Diverting agro to owner!"); + BrainUtils.initiateCombat((MobEntity) evt.getEntityLiving(), (LivingEntity) nearest); + return; + } + } + + final IPokemob pokemob = CapabilityPokemob.getPokemobFor(evt.getEntity()); + if (pokemob != null) + { + if (evt.getTarget() != null && pokemob.getTargetID() == evt.getTarget().getEntityId()) + { + if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Already targetted!"); + return; + } + if (evt.getTarget() == null && pokemob.getTargetID() == -1) return; + + // Prevent pokemob from targetting its owner. + if (evt.getTarget() != null && evt.getTarget().getUniqueID().equals(pokemob.getOwnerId())) + { + if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.log(Level.WARN, evt.getTarget() + + " is targetting owner.", new IllegalArgumentException()); + return; + } + final boolean force = evt.getTarget() != null && evt.getTarget().getLastAttackedEntity() == evt.getEntity(); + pokemob.onSetTarget(evt.getTarget(), force); + } + } + + Vector3 v = Vector3.getNewVector(); + Vector3 v1 = Vector3.getNewVector(); + + /** + * Checks the validTargts as well as team settings, will not allow + * targetting things on the same team. + */ + final Predicate validGuardTarget = input -> + { + if (input == FindTargetsTask.this.entity) return false; + if (TeamManager.sameTeam(FindTargetsTask.this.entity, input)) return false; + if (!AITools.validTargets.test(input)) return false; + return input instanceof LivingEntity; + }; + + public FindTargetsTask(final IPokemob mob) + { + super(mob, ImmutableMap.of(MemoryModuleType.VISIBLE_MOBS, MemoryModuleStatus.VALUE_PRESENT)); + } + + @Override + public void clear() + { + } + + /** + * Check for and agress any guard targets.
+ *
+ * This is called from {@link FindTargetsTask#run()} + * + * @return a guard target was found + */ + protected boolean checkGuard() + { + // Disabled via the boolean config. + if (!PokecubeCore.getConfig().guardModeEnabled) return false; + + final int rate = PokecubeCore.getConfig().guardTickRate; + // Disable via rate out of bounds, or not correct time in the rate. + if (rate <= 0 || this.entity.ticksExisted % rate != 0) return false; + + // Select either owner or home position as the centre of the check, + // this results in it guarding either its home or its owner. Home is + // used if it is on stay, or it has no owner. + final Vector3 centre = Vector3.getNewVector(); + if (this.pokemob.getGeneralState(GeneralStates.STAYING) || this.pokemob.getOwner() == null) centre.set( + this.pokemob.getHome()); + else centre.set(this.pokemob.getOwner()); + + if (!TerrainManager.isAreaLoaded(this.world, centre, PokecubeCore.getConfig().guardSearchDistance + 2)) + return false; + + final List ret = new ArrayList<>(); + final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); + // Only allow valid guard targets. + for (final LivingEntity o : pokemobs) + if (this.validGuardTarget.test(o)) ret.add(o); + ret.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); + if (ret.isEmpty()) return false; + + LivingEntity newtarget = null; + double closest = Integer.MAX_VALUE; + final Vector3 here = this.v1.set(this.entity, true); + + // Select closest visible guard target. + for (final LivingEntity e : ret) + { + final double dist = e.getDistanceSq(this.entity); + this.v.set(e, true); + if (dist < closest && here.isVisible(this.world, this.v)) + { + closest = dist; + newtarget = e; + } + } + + // Agro the target. + if (newtarget != null && Vector3.isVisibleEntityFromEntity(this.entity, newtarget)) + { + this.setAttackTarget(this.entity, newtarget); + return true; + } + return false; + } + + protected void setAttackTarget(final MobEntity attacker, final LivingEntity target) + { + if (target == null) + { + BrainUtils.deagro(attacker); + this.clear(); + } + else BrainUtils.initiateCombat(attacker, target); + } + + /** + * Check if owner is under attack, if so, agress the attacker.
+ *
+ * This is called from {@link FindTargetsTask#run()} + * + * @return if target was found. + */ + protected boolean checkOwner() + { + final Entity owner = this.pokemob.getOwner(); + + // Only apply if has owner. + if (owner == null) return false; + // Only apply if owner is close. + if (this.entity.getDistanceSq(owner) > 64) return false; + + if (this.pokemob.getGeneralState(GeneralStates.STAYING)) return false; + + final int rate = PokecubeCore.getConfig().guardTickRate; + // Disable via rate out of bounds, or not correct time in the rate. + if (rate <= 0 || this.entity.ticksExisted % rate != 0) return false; + + if (!TerrainManager.isAreaLoaded(this.world, this.entity.getPosition(), PokecubeCore + .getConfig().guardSearchDistance + 2)) return false; + + final List list = new ArrayList<>(); + final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); + list.addAll(pokemobs); + list.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); + if (list.isEmpty()) return false; + + final Entity old = BrainUtils.getAttackTarget(this.entity); + final IOwnable oldOwnable = OwnableCaps.getOwnable(old); + final Entity oldOwner = oldOwnable != null ? oldOwnable.getOwner(this.world) : null; + + if (!list.isEmpty()) for (final LivingEntity entity : list) + { + if (oldOwner != null && entity == oldOwner) return false; + final LivingEntity targ = BrainUtils.getAttackTarget(entity); + if (entity instanceof MobEntity && targ != null && targ.equals(owner) && Vector3.isVisibleEntityFromEntity( + entity, entity)) + { + this.setAttackTarget(this.entity, entity); + return true; + } + } + return false; + } + + @Override + public void reset() + { + } + + @Override + public void run() + { + final Optional hurtBy = this.entity.getBrain().getMemory(MemoryModuleType.HURT_BY_ENTITY); + if (hurtBy != null && hurtBy.isPresent()) + { + final LivingEntity target = hurtBy.get(); + if (BrainUtil.canSee(this.entity.getBrain(), target)) + { + this.setAttackTarget(this.entity, target); + return; + } + } + + // If guarding, look for mobs not on the same team as you, and if you + // find them, try to agress them. + if (this.pokemob.getCombatState(CombatStates.GUARDING)) if (this.checkGuard()) return; + + // Ensure the correct owner is tracked. + this.pokemob.getOwner(this.world); + + // Check if the pokemob is set to follow, and if so, look for mobs + // nearby trying to attack the owner of the pokemob, if any such are + // found, try to aggress them immediately. + if (!this.pokemob.getGeneralState(GeneralStates.STAYING)) if (this.checkOwner()) return; + + final boolean playerNear = this.entity.getBrain().hasMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); + // If wild, randomly decided to agro a nearby player instead. + if (playerNear && AITools.shouldAgroNearestPlayer.test(this.pokemob)) + { + PlayerEntity player = this.entity.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER).get(); + if (player != null && player.getDistance(this.entity) > PokecubeCore.getConfig().mobAggroRadius) + player = null; + if (player != null && AITools.validTargets.test(player)) + { + this.setAttackTarget(this.entity, player); + PokecubeCore.LOGGER.debug("Found player to be angry with, agressing."); + return; + } + } + } + + @Override + public boolean shouldRun() + { + if (!this.pokemob.isRoutineEnabled(AIRoutine.AGRESSIVE)) return false; + if (!this.entity.getBrain().hasMemory(MemoryModuleType.VISIBLE_MOBS)) return false; + if (BrainUtils.hasAttackTarget(this.entity)) return false; + return true; + } + +} \ No newline at end of file diff --git a/src/main/java/pokecube/core/ai/tasks/combat/ManageTargetTask.java b/src/main/java/pokecube/core/ai/tasks/combat/management/ForgetTargetTask.java similarity index 61% rename from src/main/java/pokecube/core/ai/tasks/combat/ManageTargetTask.java rename to src/main/java/pokecube/core/ai/tasks/combat/management/ForgetTargetTask.java index 2c12377554..f04ace7e2b 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/ManageTargetTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/management/ForgetTargetTask.java @@ -1,29 +1,79 @@ -package pokecube.core.ai.tasks.combat; +package pokecube.core.ai.tasks.combat.management; + +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.logging.log4j.Level; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import net.minecraft.entity.AgeableEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.BrainUtil; import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.brain.MemoryModules; +import pokecube.core.ai.tasks.combat.CombatTask; import pokecube.core.handlers.TeamManager; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.interfaces.pokemob.ai.GeneralStates; -public class ManageTargetTask extends CombatTask +public class ForgetTargetTask extends CombatTask { + private static class ForgetEntry + { + long forgotTime; + + LivingEntity mob; + + public ForgetEntry(final long time, final LivingEntity mob) + { + this.forgotTime = time; + this.mob = mob; + } + + boolean isValid(final long gameTime) + { + if (gameTime - this.forgotTime > 100) return false; + return true; + } + + @Override + public int hashCode() + { + return this.mob.getUniqueID().hashCode(); + } + + @Override + public boolean equals(final Object obj) + { + return this.mob.getUniqueID().equals(obj); + } + } + + public static int maxWildBattleDur = 600; /** The target being attacked. */ - LivingEntity entityTarget; + LivingEntity entityTarget; /** IPokemob version of entityTarget. */ IPokemob pokemobTarget; int battleTime = 0; - public ManageTargetTask(final IPokemob pokemob) + int ticksSinceSeen = 0; + + Map forgotten = Maps.newHashMap(); + + public ForgetTargetTask(final IPokemob pokemob) { super(pokemob); } @@ -33,7 +83,9 @@ public void reset() { this.entityTarget = null; this.pokemobTarget = null; - FindTargetsTask.deagro(this.entity); + this.battleTime = 0; + this.ticksSinceSeen = 0; + BrainUtils.deagro(this.entity); } @Override @@ -54,8 +106,18 @@ public void run() mate = null; } + if (!this.forgotten.isEmpty()) + { + final Set ids = Sets.newHashSet(this.forgotten.keySet()); + for (final UUID id : ids) + if (!this.forgotten.get(id).isValid(this.world.getGameTime())) this.forgotten.remove(id); + } + boolean deAgro = mate == this.entityTarget; + final ForgetEntry entry = new ForgetEntry(this.world.getGameTime(), this.entityTarget); + if (this.forgotten.containsKey(entry.mob.getUniqueID())) deAgro = true; + agroCheck: if (mobB != null && !deAgro) { @@ -74,7 +136,7 @@ public void run() final boolean oneHunting = weHunt || theyHunt; // Give up if we took too long to fight. - if (bothWild && this.battleTime > UseAttacksTask.maxWildBattleDur) + if (bothWild && this.battleTime > ForgetTargetTask.maxWildBattleDur) { deAgro = true; break agroCheck; @@ -171,9 +233,51 @@ public void run() } } + + if (BrainUtil.canSee(this.entity.getBrain(), this.entityTarget)) this.ticksSinceSeen = 0; + + // If it has been too long since last seen the target, give up. + if (this.ticksSinceSeen++ > 100) + { + // Send deagress message and put mob on cooldown. + final ITextComponent message = new TranslationTextComponent("pokemob.deagress.timeout", this.pokemob + .getDisplayName().getFormattedText()); + try + { + this.entityTarget.sendMessage(message); + } + catch (final Exception e) + { + PokecubeCore.LOGGER.log(Level.WARN, "Error with message for " + this.entityTarget, e); + } + deAgro = true; + break agroCheck; + } + + // Target is too far away, lets forget it. + if (this.entity.getDistance(this.entityTarget) > PokecubeCore.getConfig().chaseDistance) + { + // Send deagress message and put mob on cooldown. + final ITextComponent message = new TranslationTextComponent("pokemob.deagress.timeout", this.pokemob + .getDisplayName().getFormattedText()); + try + { + this.entityTarget.sendMessage(message); + } + catch (final Exception e) + { + PokecubeCore.LOGGER.log(Level.WARN, "Error with message for " + this.entityTarget, e); + } + deAgro = true; + break agroCheck; + } } // All we do is deagro if needed. - if (deAgro) FindTargetsTask.deagro(this.entity); + if (deAgro) + { + this.pokemob.setAttackCooldown(PokecubeCore.getConfig().pokemobagressticks); + BrainUtils.deagro(this.entity); + } } @Override @@ -181,6 +285,10 @@ public boolean shouldRun() { this.entityTarget = BrainUtils.getAttackTarget(this.entity); this.pokemobTarget = CapabilityPokemob.getPokemobFor(this.entityTarget); + + if (this.entityTarget == null && this.entity.getBrain().hasMemory(MemoryModuleType.HURT_BY_ENTITY)) + this.entityTarget = this.entity.getBrain().getMemory(MemoryModuleType.HURT_BY_ENTITY).get(); + // Only run if we have a combat target return this.entityTarget != null; } diff --git a/src/main/java/pokecube/core/ai/tasks/combat/CicleTask.java b/src/main/java/pokecube/core/ai/tasks/combat/movement/CicleTask.java similarity index 97% rename from src/main/java/pokecube/core/ai/tasks/combat/CicleTask.java rename to src/main/java/pokecube/core/ai/tasks/combat/movement/CicleTask.java index e924b3ae85..a23d7bac7d 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/CicleTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/movement/CicleTask.java @@ -1,9 +1,10 @@ -package pokecube.core.ai.tasks.combat; +package pokecube.core.ai.tasks.combat.movement; import net.minecraft.entity.Entity; import net.minecraft.entity.SharedMonsterAttributes; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.tasks.combat.CombatTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; import thut.api.entity.ai.IAICombat; diff --git a/src/main/java/pokecube/core/ai/tasks/combat/DodgeTask.java b/src/main/java/pokecube/core/ai/tasks/combat/movement/DodgeTask.java similarity index 98% rename from src/main/java/pokecube/core/ai/tasks/combat/DodgeTask.java rename to src/main/java/pokecube/core/ai/tasks/combat/movement/DodgeTask.java index 783cd7d3f4..cc923fc342 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/DodgeTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/movement/DodgeTask.java @@ -1,4 +1,4 @@ -package pokecube.core.ai.tasks.combat; +package pokecube.core.ai.tasks.combat.movement; import java.util.Random; @@ -10,6 +10,7 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.tasks.TaskBase; +import pokecube.core.ai.tasks.combat.CombatTask; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.IPokemob.Stats; import pokecube.core.interfaces.PokecubeMod; diff --git a/src/main/java/pokecube/core/ai/tasks/combat/LeapTask.java b/src/main/java/pokecube/core/ai/tasks/combat/movement/LeapTask.java similarity index 98% rename from src/main/java/pokecube/core/ai/tasks/combat/LeapTask.java rename to src/main/java/pokecube/core/ai/tasks/combat/movement/LeapTask.java index d3a90933d5..3a5ca1e3de 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/LeapTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/movement/LeapTask.java @@ -1,4 +1,4 @@ -package pokecube.core.ai.tasks.combat; +package pokecube.core.ai.tasks.combat.movement; import java.util.Map; import java.util.Random; diff --git a/src/main/java/pokecube/core/ai/tasks/idle/GuardEggTask.java b/src/main/java/pokecube/core/ai/tasks/idle/GuardEggTask.java index 83ec43e410..1fe3bfbc19 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/GuardEggTask.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/GuardEggTask.java @@ -8,7 +8,7 @@ import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.interfaces.IPokemob; import pokecube.core.items.pokemobeggs.EntityPokemobEgg; import thut.api.terrain.TerrainManager; @@ -89,7 +89,7 @@ public boolean shouldRun() this.egg = (EntityPokemobEgg) list.get(0); this.egg.mother = this.pokemob; - FindTargetsTask.deagro(this.pokemob.getEntity()); + BrainUtils.deagro(this.pokemob.getEntity()); // Only run if we have a live egg to watch. if (this.egg != null) return this.egg.isAlive() ? true : false; diff --git a/src/main/java/pokecube/core/ai/tasks/idle/MateTask.java b/src/main/java/pokecube/core/ai/tasks/idle/MateTask.java index 33b001edf3..cec57ce669 100644 --- a/src/main/java/pokecube/core/ai/tasks/idle/MateTask.java +++ b/src/main/java/pokecube/core/ai/tasks/idle/MateTask.java @@ -7,6 +7,7 @@ import com.google.common.collect.Maps; import net.minecraft.entity.AgeableEntity; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.entity.ai.brain.memory.WalkTarget; @@ -14,7 +15,6 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.brain.MemoryModules; -import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.interfaces.IMoveConstants.AIRoutine; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; @@ -97,7 +97,7 @@ public void run() // This fight should end when one gets below half health, which would // then be invalid for the next selection round of mating targets. - FindTargetsTask.initiateCombat(this.mobA, this.mobB); + BrainUtils.initiateCombat(this.mobA, this.mobB); this.startSpot = new WalkTarget(this.entity.getPositionVec(), (float) this.pokemob.getMovementSpeed(), 0); } @@ -136,9 +136,7 @@ public void tick() if (this.mate == null) return; // Make them walk to each other - this.setWalkTo(this.mate, this.pokemob.getMovementSpeed(), 0); - this.mate.getBrain().setMemory(MemoryModules.WALK_TARGET, new WalkTarget(new EntityPosWrapper(this.entity), - (float) this.pokemob.getMovementSpeed(), 0)); + this.approachEachOther(this.entity, this.mate, (float) this.pokemob.getMovementSpeed()); BrainUtils.setMateTarget((AgeableEntity) this.entity, this.mate); BrainUtils.setMateTarget(this.mate, (AgeableEntity) this.entity); @@ -152,4 +150,18 @@ public void tick() other.resetLoveStatus(); this.pokemob.resetLoveStatus(); } + + void approachEachOther(final LivingEntity firstEntity, final LivingEntity secondEntity, final float speed) + { + this.approach(firstEntity, secondEntity, speed); + this.approach(secondEntity, firstEntity, speed); + } + + void approach(final LivingEntity living, final LivingEntity target, final float speed) + { + final EntityPosWrapper entityposwrapper = new EntityPosWrapper(target); + final WalkTarget walktarget = new WalkTarget(entityposwrapper, speed, 0); + living.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, entityposwrapper); + living.getBrain().setMemory(MemoryModuleType.WALK_TARGET, walktarget); + } } diff --git a/src/main/java/pokecube/core/database/Database.java b/src/main/java/pokecube/core/database/Database.java index 5b75a25d72..e77d6d7f64 100644 --- a/src/main/java/pokecube/core/database/Database.java +++ b/src/main/java/pokecube/core/database/Database.java @@ -16,9 +16,6 @@ import java.util.Map; import java.util.Set; -import thut.core.xml.bind.annotation.XmlAttribute; -import thut.core.xml.bind.annotation.XmlElement; -import thut.core.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import com.google.common.collect.Lists; @@ -67,6 +64,9 @@ import pokecube.core.moves.implementations.MovesAdder; import pokecube.core.utils.PokeType; import thut.core.common.ThutCore; +import thut.core.xml.bind.annotation.XmlAttribute; +import thut.core.xml.bind.annotation.XmlElement; +import thut.core.xml.bind.annotation.XmlRootElement; public class Database { @@ -666,16 +666,22 @@ public static void initSounds(final IForgeRegistry registry) { final ResourceLocation sound = new ResourceLocation(entry.soundEffectSource); final SoundEvent event = new SoundEvent(sound); - event.setRegistryName(sound); - if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) registry.register(event); + if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) + { + event.setRegistryName(sound); + registry.register(event); + } } // Register sound on target if (entry.soundEffectTarget != null) { final ResourceLocation sound = new ResourceLocation(entry.soundEffectTarget); final SoundEvent event = new SoundEvent(sound); - event.setRegistryName(sound); - if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) registry.register(event); + if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) + { + event.setRegistryName(sound); + registry.register(event); + } } // Register sounds for the animations if (entry.animations != null) for (final AnimationJson anim : entry.animations) @@ -683,9 +689,11 @@ public static void initSounds(final IForgeRegistry registry) { final ResourceLocation sound = new ResourceLocation(anim.sound); final SoundEvent event = new SoundEvent(sound); - event.setRegistryName(sound); - if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) registry.register( - event); + if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) + { + event.setRegistryName(sound); + registry.register(event); + } } } @@ -694,8 +702,11 @@ public static void initSounds(final IForgeRegistry registry) { final ResourceLocation sound = new ResourceLocation(var); final SoundEvent event = new SoundEvent(sound); - event.setRegistryName(sound); - if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) registry.register(event); + if (!registry.containsKey(sound) && !sound.getNamespace().equals("minecraft")) + { + event.setRegistryName(sound); + registry.register(event); + } } } diff --git a/src/main/java/pokecube/core/database/PokedexEntry.java b/src/main/java/pokecube/core/database/PokedexEntry.java index 8b869a3dbe..4e081fc627 100644 --- a/src/main/java/pokecube/core/database/PokedexEntry.java +++ b/src/main/java/pokecube/core/database/PokedexEntry.java @@ -45,7 +45,7 @@ import net.minecraftforge.fml.ModLoadingContext; import pokecube.core.PokecubeCore; import pokecube.core.PokecubeItems; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.database.PokedexEntryLoader.Action; import pokecube.core.database.PokedexEntryLoader.DefaultFormeHolder; import pokecube.core.database.PokedexEntryLoader.Drop; @@ -526,7 +526,7 @@ public boolean applyInteraction(final PlayerEntity player, final IPokemob pokemo if (consumeInput) held.shrink(1); if (held.isEmpty()) player.inventory.setInventorySlotContents(player.inventory.currentItem, result); else if (!player.inventory.addItemStackToInventory(result)) player.dropItem(result, false); - if (player != pokemob.getOwner()) FindTargetsTask.initiateCombat(entity, player); + if (player != pokemob.getOwner()) BrainUtils.initiateCombat(entity, player); return true; } diff --git a/src/main/java/pokecube/core/database/recipes/XMLRecipeHandler.java b/src/main/java/pokecube/core/database/recipes/XMLRecipeHandler.java index 6e7c5c6015..cafbb4d5eb 100644 --- a/src/main/java/pokecube/core/database/recipes/XMLRecipeHandler.java +++ b/src/main/java/pokecube/core/database/recipes/XMLRecipeHandler.java @@ -4,10 +4,6 @@ import java.util.Map; import java.util.Set; -import thut.core.xml.bind.annotation.XmlAnyAttribute; -import thut.core.xml.bind.annotation.XmlAttribute; -import thut.core.xml.bind.annotation.XmlElement; -import thut.core.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import com.google.common.collect.Lists; @@ -17,6 +13,10 @@ import net.minecraft.util.ResourceLocation; import pokecube.core.PokecubeCore; import pokecube.core.database.PokedexEntryLoader.Drop; +import thut.core.xml.bind.annotation.XmlAnyAttribute; +import thut.core.xml.bind.annotation.XmlAttribute; +import thut.core.xml.bind.annotation.XmlElement; +import thut.core.xml.bind.annotation.XmlRootElement; public class XMLRecipeHandler { diff --git a/src/main/java/pokecube/core/database/rewards/XMLRewardsHandler.java b/src/main/java/pokecube/core/database/rewards/XMLRewardsHandler.java index 387c9d1463..9ec58b0565 100644 --- a/src/main/java/pokecube/core/database/rewards/XMLRewardsHandler.java +++ b/src/main/java/pokecube/core/database/rewards/XMLRewardsHandler.java @@ -7,10 +7,6 @@ import java.util.Map; import java.util.Set; -import thut.core.xml.bind.annotation.XmlAnyAttribute; -import thut.core.xml.bind.annotation.XmlAttribute; -import thut.core.xml.bind.annotation.XmlElement; -import thut.core.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import org.jline.utils.InputStreamReader; @@ -39,6 +35,10 @@ import pokecube.core.handlers.PokedexInspector.IInspectReward; import pokecube.core.handlers.playerdata.PokecubePlayerCustomData; import pokecube.core.utils.Tools; +import thut.core.xml.bind.annotation.XmlAnyAttribute; +import thut.core.xml.bind.annotation.XmlAttribute; +import thut.core.xml.bind.annotation.XmlElement; +import thut.core.xml.bind.annotation.XmlRootElement; public class XMLRewardsHandler { diff --git a/src/main/java/pokecube/core/entity/npc/NpcMob.java b/src/main/java/pokecube/core/entity/npc/NpcMob.java index 2c21153ada..e6e1425ad4 100644 --- a/src/main/java/pokecube/core/entity/npc/NpcMob.java +++ b/src/main/java/pokecube/core/entity/npc/NpcMob.java @@ -103,8 +103,9 @@ protected void initBrain(final Brain brain) if (guard != null) { final GuardAI guardai = new GuardAI(this, guard); - final VillagerProfession profession = this.getVillagerData().getProfession(); + if (this.getNpcType() != null && this.getNpcType().getProfession() != profession) this.setVillagerData(this + .getVillagerData().withLevel(3).withProfession(this.getNpcType().getProfession())); final float f = (float) this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue(); if (this.isChild()) { @@ -158,7 +159,7 @@ public boolean attackEntityFrom(final DamageSource source, final float i) public void setVillagerData(final VillagerData data) { final MerchantOffers trades = this.offers; - super.setVillagerData(data.withProfession(VillagerProfession.NITWIT)); + super.setVillagerData(data); this.offers = trades; } @@ -172,7 +173,8 @@ public IPacket createSpawnPacket() public ILivingEntityData onInitialSpawn(final IWorld worldIn, final DifficultyInstance difficultyIn, final SpawnReason reason, final ILivingEntityData spawnDataIn, final CompoundNBT dataTag) { - this.setVillagerData(this.getVillagerData().withProfession(VillagerProfession.NONE)); + final VillagerProfession proff = this.getNpcType().getProfession(); + this.setVillagerData(this.getVillagerData().withProfession(proff).withLevel(3)); this.getAttribute(SharedMonsterAttributes.FOLLOW_RANGE).applyModifier(new AttributeModifier( "Random spawn bonus", this.rand.nextGaussian() * 0.05D, AttributeModifier.Operation.MULTIPLY_BASE)); if (this.rand.nextFloat() < 0.05F) this.setLeftHanded(true); diff --git a/src/main/java/pokecube/core/entity/npc/NpcType.java b/src/main/java/pokecube/core/entity/npc/NpcType.java index 81e52486c3..b1b937603b 100644 --- a/src/main/java/pokecube/core/entity/npc/NpcType.java +++ b/src/main/java/pokecube/core/entity/npc/NpcType.java @@ -5,6 +5,7 @@ import com.google.common.collect.Maps; +import net.minecraft.entity.merchant.villager.VillagerProfession; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.container.SimpleNamedContainerProvider; @@ -95,6 +96,8 @@ public static NpcType byType(String string) private ResourceLocation maleTex; private ResourceLocation femaleTex; + private VillagerProfession profession = VillagerProfession.NONE; + private IInteract interaction = (p, h, mob) -> false; public NpcType(String string) @@ -169,4 +172,14 @@ public IInteract getInteraction() { return this.interaction; } + + public VillagerProfession getProfession() + { + return this.profession; + } + + public void setProfession(final VillagerProfession profession) + { + this.profession = profession; + } } diff --git a/src/main/java/pokecube/core/handlers/Config.java b/src/main/java/pokecube/core/handlers/Config.java index 13d25db6d8..568e174025 100644 --- a/src/main/java/pokecube/core/handlers/Config.java +++ b/src/main/java/pokecube/core/handlers/Config.java @@ -327,7 +327,7 @@ private static SoundEvent getRegisteredSoundEvent(final String id) @Configure(category = Config.mobAI) public int hungerTickRate = 20; @Configure(category = Config.mobAI) - public double hordeRateFactor = 1; + public double hordeRateFactor = 0.1; @Configure(category = Config.mobAI) public double leapSpeedFactor = 1; @Configure(category = Config.mobAI) diff --git a/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java b/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java index a057538466..84b348bab7 100644 --- a/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java +++ b/src/main/java/pokecube/core/handlers/events/PokemobEventsHandler.java @@ -49,7 +49,6 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.logic.Logic; -import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.Pokedex; import pokecube.core.database.PokedexEntry; import pokecube.core.database.PokedexEntry.EvolutionData; @@ -179,13 +178,13 @@ else if (giveExp) final Entity targetOwner = attackedMob.getOwner(); attacker.displayMessageToOwner(new TranslationTextComponent("pokemob.action.faint.enemy", attackedMob .getDisplayName())); - if (targetOwner instanceof PlayerEntity && attacker.getOwner() != targetOwner) FindTargetsTask - .initiateCombat(pokemob, (LivingEntity) targetOwner); - else FindTargetsTask.deagro(pokemob); + if (targetOwner instanceof PlayerEntity && attacker.getOwner() != targetOwner) BrainUtils.initiateCombat( + pokemob, (LivingEntity) targetOwner); + else BrainUtils.deagro(pokemob); if (attacker.getPokedexEntry().isFood(attackedMob.getPokedexEntry()) && attacker.getCombatState( CombatStates.HUNTING)) { - attacker.eat(BrainUtils.getHuntTarget(pokemob)); + attacker.eat(attackedMob.getEntity()); attacker.setCombatState(CombatStates.HUNTING, false); pokemob.getNavigator().clearPath(); } diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java index a9473e1346..11e5346c6b 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobMoves.java @@ -12,7 +12,6 @@ import net.minecraft.util.text.ITextComponent; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.PokedexEntry; import pokecube.core.database.moves.MoveEntry; import pokecube.core.interfaces.IMoveConstants; @@ -74,7 +73,7 @@ public void executeMove(final Entity target, Vector3 targetLocation, final float if (target instanceof MobEntity) { final MobEntity t = (MobEntity) target; - if (BrainUtils.getAttackTarget(t) != this.getEntity()) FindTargetsTask.initiateCombat(t, this.getEntity()); + if (BrainUtils.getAttackTarget(t) != this.getEntity()) BrainUtils.initiateCombat(t, this.getEntity()); } if (target instanceof LivingEntity) if (((LivingEntity) target).getRevengeTarget() != this.getEntity()) { diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java index 7bc907ec80..b2c176d89d 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobOwned.java @@ -25,7 +25,6 @@ import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.logic.LogicMountedControl; -import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.client.gui.GuiInfoMessages; import pokecube.core.database.PokedexEntryLoader.SpawnRule; import pokecube.core.database.abilities.AbilityManager; @@ -346,7 +345,7 @@ else if (this.getOwnerId() != null) final IPokemob targetMob = CapabilityPokemob.getPokemobFor(targ); if (targetMob != null) { - FindTargetsTask.initiateCombat(targetMob.getEntity(), this.getOwner()); + BrainUtils.initiateCombat(targetMob.getEntity(), this.getOwner()); if (PokecubeMod.debug) PokecubeCore.LOGGER.info("Swapping agro to cowardly owner!"); } else targ.setRevengeTarget(this.getOwner()); diff --git a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java index c1fc41de98..4b3c471053 100644 --- a/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java +++ b/src/main/java/pokecube/core/interfaces/capabilities/impl/PokemobSexed.java @@ -12,7 +12,7 @@ import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSidedProvider; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.tasks.idle.HungerTask; import pokecube.core.database.PokedexEntry; import pokecube.core.events.EggEvent; @@ -157,8 +157,8 @@ protected void mate(final IBreedingMob male) mate.setHungerTime(mate.getHungerTime() + hungerValue); this.setHungerTime(this.getHungerTime() + hungerValue); mate.resetLoveStatus(); - FindTargetsTask.deagro(this.getEntity()); - FindTargetsTask.deagro(mate.getEntity()); + BrainUtils.deagro(this.getEntity()); + BrainUtils.deagro(mate.getEntity()); this.lay(mate); this.resetLoveStatus(); } diff --git a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java index eb9413329c..5263bb9e8c 100644 --- a/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java +++ b/src/main/java/pokecube/core/interfaces/pokemob/commandhandlers/AttackEntityHandler.java @@ -8,7 +8,7 @@ import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.events.pokemob.combat.CommandAttackEvent; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.Move_Base; @@ -62,7 +62,7 @@ public void handleCommand(final IPokemob pokemob) .getDisplayName(), target.getDisplayName(), new TranslationTextComponent(MovesUtils .getUnlocalizedMove(move.getName()))); if (this.fromOwner()) pokemob.displayMessageToOwner(mess); - FindTargetsTask.initiateCombat(pokemob.getEntity(), (LivingEntity) target); + BrainUtils.initiateCombat(pokemob.getEntity(), (LivingEntity) target); } } } diff --git a/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java b/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java index 29aec918be..8c00b12943 100644 --- a/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java +++ b/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java @@ -42,7 +42,7 @@ import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; @@ -202,7 +202,7 @@ protected void onImpact(final RayTraceResult result) if (PokecubeManager.isFilled(this.getItem())) { final LivingEntity sent = SendOutManager.sendOut(this, true); - if (sent instanceof MobEntity && hit.getEntity() instanceof LivingEntity) FindTargetsTask.initiateCombat( + if (sent instanceof MobEntity && hit.getEntity() instanceof LivingEntity) BrainUtils.initiateCombat( (MobEntity) sent, (LivingEntity) hit.getEntity()); } diff --git a/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java b/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java index 85a39e94b4..8e952b5ddf 100644 --- a/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java +++ b/src/main/java/pokecube/core/items/pokecubes/helper/CaptureManager.java @@ -16,7 +16,7 @@ import net.minecraftforge.eventbus.api.Event.Result; import pokecube.core.PokecubeCore; import pokecube.core.PokecubeItems; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.database.abilities.AbilityManager; import pokecube.core.events.pokemob.CaptureEvent; import pokecube.core.events.pokemob.CaptureEvent.Pre; @@ -161,7 +161,7 @@ public static void captureFailed(final EntityPokecubeBase cube) ((PlayerEntity) cube.shootingEntity).sendMessage(mess); } } - if (mob instanceof MobEntity && cube.shootingEntity != null) FindTargetsTask.initiateCombat((MobEntity) mob, + if (mob instanceof MobEntity && cube.shootingEntity != null) BrainUtils.initiateCombat((MobEntity) mob, cube.shootingEntity); } diff --git a/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java b/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java index 3a7aba00e9..ab595d8e65 100644 --- a/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java +++ b/src/main/java/pokecube/core/items/pokemobeggs/EntityPokemobEgg.java @@ -21,7 +21,6 @@ import net.minecraftforge.common.MinecraftForge; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.PokedexEntry; import pokecube.core.events.EggEvent; import pokecube.core.interfaces.IPokemob; @@ -73,7 +72,7 @@ public boolean attackEntityFrom(final DamageSource source, final float damage) final ItemStack itemstack = this.getHeldItemMainhand(); final int i = itemstack.getCount(); final PlayerEntity player = (PlayerEntity) e; - if (this.mother != null && this.mother.getOwner() != player) FindTargetsTask.initiateCombat(this.mother + if (this.mother != null && this.mother.getOwner() != player) BrainUtils.initiateCombat(this.mother .getEntity(), player); if (i <= 0 || player.inventory.addItemStackToInventory(itemstack)) { diff --git a/src/main/java/pokecube/core/moves/PokemobTerrainEffects.java b/src/main/java/pokecube/core/moves/PokemobTerrainEffects.java index 9848b543a7..c97b330995 100644 --- a/src/main/java/pokecube/core/moves/PokemobTerrainEffects.java +++ b/src/main/java/pokecube/core/moves/PokemobTerrainEffects.java @@ -48,10 +48,15 @@ public class PokemobTerrainEffects implements ITerrainEffect public static final int CLEAR_ENTRYEFFECTS = 16; - public static final TerrainDamageSource HAILDAMAGE = new TerrainDamageSource("terrain.hail", - TerrainType.TERRAIN); - public static final TerrainDamageSource SANDSTORMDAMAGE = new TerrainDamageSource("terrain.sandstorm", - TerrainType.TERRAIN); + public static final TerrainDamageSource createHailSource(final IPokemob mobIn) + { + return new TerrainDamageSource("terrain.hail", TerrainType.TERRAIN, mobIn); + } + + public static final TerrainDamageSource createSandstormSource(final IPokemob mobIn) + { + return new TerrainDamageSource("terrain.sandstorm", TerrainType.TERRAIN, mobIn); + } public final long[] effects = new long[16]; @@ -61,19 +66,21 @@ public class PokemobTerrainEffects implements ITerrainEffect Set pokemon = new HashSet<>(); + IPokemob[] users = new IPokemob[16]; + public PokemobTerrainEffects() { } @Override - public void bindToTerrain(int x, int y, int z) + public void bindToTerrain(final int x, final int y, final int z) { this.chunkX = x; this.chunkY = y; this.chunkZ = z; } - public void doEffect(LivingEntity entity) + public void doEffect(final LivingEntity entity) { if (entity.getEntityWorld().getGameTime() % (2 * PokecubeCore.getConfig().attackCooldown) != 0) return; if (!AITools.validTargets.test(entity)) return; @@ -84,14 +91,16 @@ public void doEffect(LivingEntity entity) { final float thisMaxHP = entity.getMaxHealth(); final int damage = Math.max(1, (int) (0.0625 * thisMaxHP)); - entity.attackEntityFrom(PokemobTerrainEffects.HAILDAMAGE, damage); + entity.attackEntityFrom(PokemobTerrainEffects.createHailSource( + this.users[PokemobTerrainEffects.EFFECT_WEATHER_HAIL]), damage); } if (this.effects[PokemobTerrainEffects.EFFECT_WEATHER_SAND] > 0 && !(mob.isType(PokeType.getType("rock")) || mob.isType(PokeType.getType("steel")) || mob.isType(PokeType.getType("ground")))) { final float thisMaxHP = entity.getMaxHealth(); final int damage = Math.max(1, (int) (0.0625 * thisMaxHP)); - entity.attackEntityFrom(PokemobTerrainEffects.SANDSTORMDAMAGE, damage); + entity.attackEntityFrom(PokemobTerrainEffects.createSandstormSource( + this.users[PokemobTerrainEffects.EFFECT_WEATHER_SAND]), damage); } if (this.effects[PokemobTerrainEffects.EFFECT_TERRAIN_ELECTRIC] > 0 && mob.isOnGround()) if (mob .getStatus() == IMoveConstants.STATUS_SLP) mob.healStatus(); @@ -111,13 +120,15 @@ else if (PokecubeCore.getConfig().pokemobsDamagePlayers) { final float thisMaxHP = entity.getMaxHealth(); final int damage = Math.max(1, (int) (0.0625 * thisMaxHP)); - entity.attackEntityFrom(PokemobTerrainEffects.HAILDAMAGE, damage); + entity.attackEntityFrom(PokemobTerrainEffects.createHailSource( + this.users[PokemobTerrainEffects.EFFECT_WEATHER_HAIL]), damage); } if (this.effects[PokemobTerrainEffects.EFFECT_WEATHER_SAND] > 0) { final float thisMaxHP = entity.getMaxHealth(); final int damage = Math.max(1, (int) (0.0625 * thisMaxHP)); - entity.attackEntityFrom(PokemobTerrainEffects.SANDSTORMDAMAGE, damage); + entity.attackEntityFrom(PokemobTerrainEffects.createSandstormSource( + this.users[PokemobTerrainEffects.EFFECT_WEATHER_SAND]), damage); } if (this.effects[PokemobTerrainEffects.EFFECT_TERRAIN_GRASS] > 0 && entity.onGround) { @@ -131,13 +142,13 @@ else if (PokecubeCore.getConfig().pokemobsDamagePlayers) } @Override - public void doEffect(LivingEntity entity, boolean firstEntry) + public void doEffect(final LivingEntity entity, final boolean firstEntry) { if (firstEntry) this.doEntryEffect(entity); else this.doEffect(entity); } - public void doEntryEffect(LivingEntity entity) + public void doEntryEffect(final LivingEntity entity) { final IPokemob mob = CapabilityPokemob.getPokemobFor(entity); if (mob != null) @@ -166,7 +177,7 @@ public void doEntryEffect(LivingEntity entity) } } - private void dropDurations(Entity e) + private void dropDurations(final Entity e) { final long time = e.getEntityWorld().getGameTime(); boolean send = false; @@ -177,6 +188,7 @@ private void dropDurations(Entity e) if (diff < 0) { this.effects[i] = 0; + this.users[i] = null; send = true; } } @@ -184,7 +196,7 @@ private void dropDurations(Entity e) this.chunkZ, this); } - public long getEffect(int effect) + public long getEffect(final int effect) { return this.effects[effect]; } @@ -204,12 +216,12 @@ public boolean hasEffects() } @Override - public void readFromNBT(CompoundNBT nbt) + public void readFromNBT(final CompoundNBT nbt) { } @OnlyIn(Dist.CLIENT) - private void renderEffect(Vector3 direction, float tick) + private void renderEffect(final Vector3 direction, final float tick) { GlStateManager.disableTexture(); final Vector3 temp = Vector3.getNewVector(); @@ -236,7 +248,7 @@ private void renderEffect(Vector3 direction, float tick) } @OnlyIn(Dist.CLIENT) - public void renderTerrainEffects(RenderFogEvent event) + public void renderTerrainEffects(final RenderFogEvent event) { if (this.hasEffects()) { @@ -271,8 +283,9 @@ public void renderTerrainEffects(RenderFogEvent event) * how long this effect lasts, this counter is decreased every * time a pokemob uses a move. */ - public void setEffect(int effect, long duration) + public void setEffect(final int effect, final long duration, final IPokemob user) { + this.users[effect] = user; if (effect == PokemobTerrainEffects.EFFECT_WEATHER_HAIL) { this.effects[PokemobTerrainEffects.EFFECT_WEATHER_RAIN] = 0; @@ -309,7 +322,7 @@ public void setEffect(int effect, long duration) } @Override - public void writeToNBT(CompoundNBT nbt) + public void writeToNBT(final CompoundNBT nbt) { } diff --git a/src/main/java/pokecube/core/moves/damage/TerrainDamageSource.java b/src/main/java/pokecube/core/moves/damage/TerrainDamageSource.java index c2a93a66d0..90e3afe62d 100644 --- a/src/main/java/pokecube/core/moves/damage/TerrainDamageSource.java +++ b/src/main/java/pokecube/core/moves/damage/TerrainDamageSource.java @@ -1,9 +1,11 @@ package pokecube.core.moves.damage; +import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.util.DamageSource; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; +import pokecube.core.interfaces.IPokemob; public class TerrainDamageSource extends DamageSource implements IPokedamage { @@ -14,10 +16,13 @@ public static enum TerrainType public final TerrainType type; - public TerrainDamageSource(final String damageTypeIn, final TerrainType type) + public final IPokemob user; + + public TerrainDamageSource(final String damageTypeIn, final TerrainType type, final IPokemob user) { super(damageTypeIn); this.type = type; + this.user = user; } @Override @@ -27,4 +32,23 @@ public ITextComponent getDeathMessage(final LivingEntity LivingEntityIn) final String s = "death.attack." + this.damageType; return new TranslationTextComponent(s, LivingEntityIn.getDisplayName()); } + + @Override + public Entity getImmediateSource() + { + if (this.user != null) return this.user.getEntity(); + return super.getImmediateSource(); + } + + @Override + public Entity getTrueSource() + { + if (this.user != null) + { + Entity source = this.user.getEntity(); + if (this.user.getOwner() != null) source = this.user.getOwner(); + return source; + } + return super.getTrueSource(); + } } diff --git a/src/main/java/pokecube/core/moves/templates/Move_Basic.java b/src/main/java/pokecube/core/moves/templates/Move_Basic.java index 31de909468..b55bfbc53a 100644 --- a/src/main/java/pokecube/core/moves/templates/Move_Basic.java +++ b/src/main/java/pokecube/core/moves/templates/Move_Basic.java @@ -23,7 +23,6 @@ import net.minecraft.world.World; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.tasks.combat.FindTargetsTask; import pokecube.core.database.abilities.Ability; import pokecube.core.database.moves.MoveEntry; import pokecube.core.events.pokemob.combat.MoveUse; @@ -370,7 +369,7 @@ public void onAttack(MovePacket packet) } if (attacked != attackerMob && targetPokemob != null) { - FindTargetsTask.initiateCombat((MobEntity) attacked, attackerMob); + BrainUtils.initiateCombat((MobEntity) attacked, attackerMob); targetPokemob.setCombatState(CombatStates.ANGRY, true); } if (efficiency > 0 && packet.applyOngoing) diff --git a/src/main/java/pokecube/core/moves/templates/Move_Terrain.java b/src/main/java/pokecube/core/moves/templates/Move_Terrain.java index fc5d5e1f60..546d8dc494 100644 --- a/src/main/java/pokecube/core/moves/templates/Move_Terrain.java +++ b/src/main/java/pokecube/core/moves/templates/Move_Terrain.java @@ -22,7 +22,7 @@ public class Move_Terrain extends Move_Basic * @param name * @param effect */ - public Move_Terrain(String name) + public Move_Terrain(final String name) { super(name); this.effect = this.move.baseEntry.extraInfo; @@ -38,7 +38,7 @@ public Move_Terrain(String name) * @param finalAttackStrength * the number of HPs the attack takes from target */ - public void doWorldAction(IPokemob attacker, Vector3 location) + public void doWorldAction(final IPokemob attacker, final Vector3 location) { if (attacker.getMoveStats().SPECIALCOUNTER > 0) return; attacker.getMoveStats().SPECIALCOUNTER = 20; @@ -51,14 +51,14 @@ public void doWorldAction(IPokemob attacker, Vector3 location) // TODO check if effect already exists, and send message if so. // Otherwise send the it starts to effect message - teffect.setEffect(this.effect, this.duration + world.getGameTime()); + teffect.setEffect(this.effect, this.duration + world.getGameTime(), attacker); if (attacker.getEntity().isServerWorld()) PacketSyncTerrain.sendTerrainEffects(attacker.getEntity(), segment.chunkX, segment.chunkY, segment.chunkZ, teffect); } - public void setDuration(int duration) + public void setDuration(final int duration) { this.duration = duration; } diff --git a/src/main/java/pokecube/core/utils/AITools.java b/src/main/java/pokecube/core/utils/AITools.java index b7b06e2b1d..8fbbf19dfa 100644 --- a/src/main/java/pokecube/core/utils/AITools.java +++ b/src/main/java/pokecube/core/utils/AITools.java @@ -48,12 +48,14 @@ public boolean test(final Entity input) // Then check if disabled via class for (final Class clas : AITools.invalidClasses) if (clas.isInstance(input)) return false; - // Then check if is a spectating player. + // Then check if is a valid player. if (input instanceof ServerPlayerEntity) { final ServerPlayerEntity player = (ServerPlayerEntity) input; - if (player.isSpectator() || player.getServerWorld().getDifficulty().getId() <= Difficulty.EASY.getId()) - return false; + // Do not target creative or spectator + if (player.isCreative() || player.isSpectator()) return false; + // Do not target any player on easy or peaceful + if (player.getServerWorld().getDifficulty().getId() <= Difficulty.EASY.getId()) return false; } // Confirm is not an egg or a pokecube as well if (input instanceof EntityPokemobEgg) return false; diff --git a/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java b/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java index 5112a85a73..4e08bc5c2a 100644 --- a/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java +++ b/src/main/java/pokecube/mobs/moves/attacks/special/Teleport.java @@ -1,6 +1,6 @@ package pokecube.mobs.moves.attacks.special; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.pokemob.moves.MovePacket; import pokecube.core.moves.templates.Move_Basic; @@ -16,7 +16,7 @@ public Teleport() public void postAttack(final MovePacket packet) { final IPokemob attacker = packet.attacker; - FindTargetsTask.deagro(attacker.getEntity()); + BrainUtils.deagro(attacker.getEntity()); super.postAttack(packet); } } diff --git a/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java b/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java index 82ddbf65ea..5843a84a34 100644 --- a/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java +++ b/src/main/java/pokecube/mobs/moves/attacks/special/Transform.java @@ -5,7 +5,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.interfaces.IMoveAnimation; import pokecube.core.interfaces.IMoveConstants; import pokecube.core.interfaces.IMoveNames; @@ -78,7 +78,7 @@ public void attack(final IPokemob attacker, final Entity attacked) final IPokemob attackedMob = CapabilityPokemob.getPokemobFor(attacked); if (attacked instanceof LivingEntity) { - FindTargetsTask.initiateCombat(attacker.getEntity(), (LivingEntity) attacked); + BrainUtils.initiateCombat(attacker.getEntity(), (LivingEntity) attacked); attacker.setTransformedTo(attacked); } else if (attackedMob != null) diff --git a/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java b/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java index 1c93a18352..71cac65c04 100644 --- a/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java +++ b/src/main/java/pokecube/mobs/moves/attacks/special/Whirlwind.java @@ -1,6 +1,6 @@ package pokecube.mobs.moves.attacks.special; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; @@ -39,6 +39,6 @@ public void postAttack(final MovePacket packet) attacked.setCombatState(CombatStates.ANGRY, false); } // ends the battle - FindTargetsTask.deagro(packet.attacker.getEntity()); + BrainUtils.deagro(packet.attacker.getEntity()); } } diff --git a/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java b/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java index 6d0612a631..4bab7e658e 100644 --- a/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java +++ b/src/main/java/pokecube/mobs/moves/world/ActionTeleport.java @@ -6,7 +6,7 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import pokecube.core.PokecubeCore; -import pokecube.core.ai.tasks.combat.FindTargetsTask; +import pokecube.core.ai.brain.BrainUtils; import pokecube.core.handlers.events.EventsHandler; import pokecube.core.handlers.events.SpawnHandler; import pokecube.core.interfaces.IMoveAction; @@ -95,7 +95,7 @@ public boolean applyEffect(final IPokemob user, final Vector3 location) } else if (angry) { - FindTargetsTask.deagro(user.getEntity()); + BrainUtils.deagro(user.getEntity()); if (user.getGeneralState(GeneralStates.TAMED)) user.onRecall(); else ActionTeleport.teleportRandomly(user.getEntity()); } diff --git a/src/main/java/thut/core/client/render/animation/AnimationXML.java b/src/main/java/thut/core/client/render/animation/AnimationXML.java index f136549209..2a1b83e342 100644 --- a/src/main/java/thut/core/client/render/animation/AnimationXML.java +++ b/src/main/java/thut/core/client/render/animation/AnimationXML.java @@ -4,10 +4,6 @@ import java.util.List; import java.util.Map; -import thut.core.xml.bind.annotation.XmlAnyAttribute; -import thut.core.xml.bind.annotation.XmlAttribute; -import thut.core.xml.bind.annotation.XmlElement; -import thut.core.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import com.google.common.collect.Lists; @@ -15,6 +11,10 @@ import thut.core.common.ThutCore; import thut.core.xml.bind.Factory; +import thut.core.xml.bind.annotation.XmlAnyAttribute; +import thut.core.xml.bind.annotation.XmlAttribute; +import thut.core.xml.bind.annotation.XmlElement; +import thut.core.xml.bind.annotation.XmlRootElement; public class AnimationXML { diff --git a/src/main/java/thut/core/client/render/mca/McaXML.java b/src/main/java/thut/core/client/render/mca/McaXML.java index 0848134d86..df441fa296 100644 --- a/src/main/java/thut/core/client/render/mca/McaXML.java +++ b/src/main/java/thut/core/client/render/mca/McaXML.java @@ -4,16 +4,15 @@ import java.util.ArrayList; import java.util.List; -import thut.core.xml.bind.annotation.XmlAttribute; -import thut.core.xml.bind.annotation.XmlElement; -import thut.core.xml.bind.annotation.XmlRootElement; - import com.google.common.collect.Lists; import thut.core.client.render.model.Vertex; import thut.core.client.render.texturing.TextureCoordinate; import thut.core.client.render.x3d.ModelFormatException; import thut.core.xml.bind.Factory; +import thut.core.xml.bind.annotation.XmlAttribute; +import thut.core.xml.bind.annotation.XmlElement; +import thut.core.xml.bind.annotation.XmlRootElement; public class McaXML { diff --git a/src/main/java/thut/core/client/render/x3d/X3dXML.java b/src/main/java/thut/core/client/render/x3d/X3dXML.java index 2eef84f677..8351051fd0 100644 --- a/src/main/java/thut/core/client/render/x3d/X3dXML.java +++ b/src/main/java/thut/core/client/render/x3d/X3dXML.java @@ -5,10 +5,6 @@ import java.util.List; import java.util.Set; -import thut.core.xml.bind.annotation.XmlAttribute; -import thut.core.xml.bind.annotation.XmlElement; -import thut.core.xml.bind.annotation.XmlRootElement; - import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -16,6 +12,9 @@ import thut.core.client.render.model.Vertex; import thut.core.common.ThutCore; import thut.core.xml.bind.Factory; +import thut.core.xml.bind.annotation.XmlAttribute; +import thut.core.xml.bind.annotation.XmlElement; +import thut.core.xml.bind.annotation.XmlRootElement; public class X3dXML { diff --git a/src/main/java/thut/core/xml/bind/Factory.java b/src/main/java/thut/core/xml/bind/Factory.java index cac2b19470..718d616819 100644 --- a/src/main/java/thut/core/xml/bind/Factory.java +++ b/src/main/java/thut/core/xml/bind/Factory.java @@ -11,10 +11,6 @@ import java.util.Map; import javax.xml.XMLConstants; -import thut.core.xml.bind.annotation.XmlAnyAttribute; -import thut.core.xml.bind.annotation.XmlAttribute; -import thut.core.xml.bind.annotation.XmlElement; -import thut.core.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -32,6 +28,10 @@ import com.google.common.collect.Maps; import thut.core.common.ThutCore; +import thut.core.xml.bind.annotation.XmlAnyAttribute; +import thut.core.xml.bind.annotation.XmlAttribute; +import thut.core.xml.bind.annotation.XmlElement; +import thut.core.xml.bind.annotation.XmlRootElement; public class Factory { diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 64565a19b8..7be2f96779 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -24,6 +24,8 @@ public net.minecraft.entity.ai.brain.Brain field_218231_b # sensors public net.minecraft.pathfinding.PathNavigator func_225464_a(Ljava/util/Set;IZI)Lnet/minecraft/pathfinding/Path; # func_225464_a +public net.minecraft.village.PointOfInterestType func_221052_a(Lnet/minecraft/village/PointOfInterestType;)Lnet/minecraft/village/PointOfInterestType; # registerBlockStates + # Player related public net.minecraft.network.play.ServerPlayNetHandler field_147365_f # floatingTickCount public net.minecraft.network.play.ServerPlayNetHandler field_184346_E # vehicleFloatingTickCount From 3cc5fd1bc2a30d3158bc2cf8cadb01ca101aa2c4 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 15:13:19 -0400 Subject: [PATCH 19/27] some updates for npc targetting AI --- .../adventures/ai/tasks/AIRetaliate.java | 2 ++ .../adventures/ai/tasks/AITrainerAgro.java | 27 +++++++++++++------ .../capabilities/CapabilityHasPokemobs.java | 2 -- .../pokecube/core/entity/npc/NpcType.java | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java b/src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java index 6a945f5b28..f3d5615386 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java +++ b/src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java @@ -1,6 +1,7 @@ package pokecube.adventures.ai.tasks; import net.minecraft.entity.LivingEntity; +import net.minecraft.util.EntityPredicates; import pokecube.adventures.capabilities.CapabilityHasPokemobs.ITargetWatcher; public class AIRetaliate extends AITrainerBase implements ITargetWatcher @@ -51,6 +52,7 @@ public boolean isValidTarget(final LivingEntity target) { if (target == null) return false; if (!(target.isAlive() && this.entity.canEntityBeSeen(target))) return false; + if (!EntityPredicates.CAN_AI_TARGET.test(target)) return false; if (target != null && target.getLastAttackedEntity() == this.entity && target .getLastAttackedEntityTime() < target.ticksExisted + 20) return true; final int timer = this.entity.getRevengeTimer(); diff --git a/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java b/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java index d51734f5ae..64bc586fd9 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java +++ b/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java @@ -3,10 +3,14 @@ import java.util.List; import java.util.function.Predicate; +import com.google.common.collect.Lists; + import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.util.EntityPredicates; +import net.minecraft.util.math.Vec3d; import pokecube.adventures.PokecubeAdv; import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; import pokecube.adventures.capabilities.CapabilityHasPokemobs.ITargetWatcher; @@ -22,7 +26,6 @@ import thut.api.IOwnable; import thut.api.OwnableCaps; import thut.api.maths.Vector3; -import thut.api.terrain.TerrainManager; public class AITrainerAgro extends AITrainerBase implements ITargetWatcher { @@ -206,13 +209,13 @@ public boolean shouldRun() return false; } // Dead trainers can't fight. - if (!this.entity.isAlive() || this.entity.ticksExisted % 20 != 0) return false; + if (!this.entity.isAlive()) return false; // Permfriendly trainers shouldn't fight. if (this.aiTracker != null && this.aiTracker.getAIState(IHasNPCAIStates.PERMFRIENDLY)) return false; // Trainers on cooldown shouldn't fight, neither should friendly ones if (this.trainer.getCooldown() > this.entity.getEntityWorld().getGameTime() || !this.trainer.isAgressive()) return false; - return true; + return this.entity.getBrain().hasMemory(MemoryModuleType.VISIBLE_MOBS); } @Override @@ -243,12 +246,19 @@ public void updateTask() LivingEntity target = null; final int sight = this.trainer.getAgressDistance(); - if (!TerrainManager.isAreaLoaded(this.world, this.here, sight + 3)) return; + final Vec3d start = new Vec3d(this.here.x, this.here.y, this.here.z); + final Vector3 look = Vector3.getNewVector().set(this.entity.getLook(1)).scalarMultBy(sight).addTo(this.here); + final Vec3d end = new Vec3d(look.x, look.y, look.z); + + final Predicate matcher = e -> e instanceof LivingEntity && this.isValidTarget((LivingEntity) e) && e + .getDistance(this.entity) <= sight && e.getBoundingBox().rayTrace(start, end).isPresent(); + + final List targets = Lists.newArrayList(this.entity.getBrain().getMemory( + MemoryModuleType.VISIBLE_MOBS).get()); + + targets.removeIf(e -> !matcher.test(e)); - final Predicate matcher = e -> e instanceof LivingEntity && this.isValidTarget((LivingEntity) e); - final Entity match = this.here.firstEntityExcluding(sight, this.entity.getLook(0), this.world, this.entity, - matcher); - if (match instanceof LivingEntity) target = (LivingEntity) match; + if (!targets.isEmpty()) target = targets.get(0); // If no target, return false. if (target == null) @@ -268,6 +278,7 @@ public void updateTask() @Override public boolean isValidTarget(final LivingEntity target) { + if (!EntityPredicates.CAN_AI_TARGET.test(target)) return false; this.here.set(this.entity, true); final int dist = PokecubeAdv.config.trainer_crowding_radius; final int num = PokecubeAdv.config.trainer_crowding_number; diff --git a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java index e0796d3160..4fef737b0a 100644 --- a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java @@ -17,7 +17,6 @@ import net.minecraft.nbt.INBT; import net.minecraft.nbt.ListNBT; import net.minecraft.util.Direction; -import net.minecraft.util.EntityPredicates; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilitySerializable; @@ -190,7 +189,6 @@ public ListNBT save() public DefaultPokemobs() { - this.addTargetWatcher((e) -> EntityPredicates.CAN_AI_TARGET.test(e)); } @Override diff --git a/src/main/java/pokecube/core/entity/npc/NpcType.java b/src/main/java/pokecube/core/entity/npc/NpcType.java index b1b937603b..2052a2ebd9 100644 --- a/src/main/java/pokecube/core/entity/npc/NpcType.java +++ b/src/main/java/pokecube/core/entity/npc/NpcType.java @@ -96,7 +96,7 @@ public static NpcType byType(String string) private ResourceLocation maleTex; private ResourceLocation femaleTex; - private VillagerProfession profession = VillagerProfession.NONE; + private VillagerProfession profession = VillagerProfession.NITWIT; private IInteract interaction = (p, h, mob) -> false; From 05dfdf2ccdca448b93534e310805d9e3407f1da6 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Fri, 22 May 2020 21:25:40 -0400 Subject: [PATCH 20/27] performance tweaks for looking up owned pokemobs --- .../core/ai/logic/LogicMiscUpdate.java | 35 +++- .../core/client/EventsHandlerClient.java | 22 +++ .../client/gui/GuiDisplayPokecubeInfo.java | 4 +- .../pokecube/core/database/PokedexEntry.java | 2 +- .../core/entity/pokemobs/EntityPokemob.java | 9 +- .../core/handlers/events/EventsHandler.java | 35 +--- .../core/handlers/events/PCEventsHandler.java | 5 +- .../core/items/pokecubes/EntityPokecube.java | 5 +- .../items/pokecubes/EntityPokecubeBase.java | 35 ++-- .../pokecube/core/utils/PokemobTracker.java | 175 ++++++++++++++++-- 10 files changed, 246 insertions(+), 81 deletions(-) diff --git a/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java b/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java index a37817da5a..4f1e67d17e 100644 --- a/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java +++ b/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java @@ -2,6 +2,7 @@ import java.util.Calendar; import java.util.Random; +import java.util.UUID; import net.minecraft.entity.AgeableEntity; import net.minecraft.entity.LivingEntity; @@ -29,6 +30,7 @@ import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.interfaces.pokemob.ai.GeneralStates; import pokecube.core.interfaces.pokemob.ai.LogicStates; +import pokecube.core.utils.PokemobTracker; import thut.api.item.ItemList; import thut.api.maths.Vector3; @@ -46,17 +48,22 @@ public class LogicMiscUpdate extends LogicBase public static final boolean holiday = Calendar.getInstance().get(Calendar.DAY_OF_MONTH) == 25 && Calendar .getInstance().get(Calendar.MONTH) == 11; - private int lastHadTargetTime = 0; - private final int[] flavourAmounts = new int[5]; + private int lastHadTargetTime = 0; + + private final int[] flavourAmounts = new int[5]; + private PokedexEntry entry; - private String particle = null; - private boolean reset = false; - private boolean initHome = false; - private boolean checkedEvol = false; - private int pathTimer = 0; - private long dynatime = -1; - private boolean de_dyna = false; - Vector3 v = Vector3.getNewVector(); + private String particle = null; + private boolean reset = false; + private boolean initHome = false; + private boolean checkedEvol = false; + private int pathTimer = 0; + private long dynatime = -1; + private boolean de_dyna = false; + + Vector3 v = Vector3.getNewVector(); + + UUID prevOwner = null; public LogicMiscUpdate(final IPokemob entity) { @@ -272,6 +279,14 @@ public void tick(final World world) if (id < 0 && targ != null) BrainUtils.setAttackTarget(this.entity, null); if (targ != null && !targ.isAlive()) BrainUtils.setAttackTarget(this.entity, null); + // Sync the addition of this, as onAddedToWorld is called before this + // value is synchronized + if (this.prevOwner == null && this.pokemob.getOwnerId() != null) + { + this.prevOwner = this.pokemob.getOwnerId(); + PokemobTracker.addPokemob(this.pokemob); + } + // Particle stuff below here, WARNING, RESETTING RNG HERE rand = new Random(); final Vector3 particleLoc = Vector3.getNewVector().set(this.entity); diff --git a/src/main/java/pokecube/core/client/EventsHandlerClient.java b/src/main/java/pokecube/core/client/EventsHandlerClient.java index 132b304eea..e21418d3a9 100644 --- a/src/main/java/pokecube/core/client/EventsHandlerClient.java +++ b/src/main/java/pokecube/core/client/EventsHandlerClient.java @@ -1,6 +1,7 @@ package pokecube.core.client; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -23,6 +24,7 @@ import net.minecraft.client.renderer.entity.PlayerRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.container.Slot; @@ -69,11 +71,13 @@ import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.interfaces.pokemob.ai.GeneralStates; import pokecube.core.interfaces.pokemob.commandhandlers.StanceHandler; +import pokecube.core.items.pokecubes.EntityPokecubeBase; import pokecube.core.items.pokecubes.PokecubeManager; import pokecube.core.network.pokemobs.PacketChangeForme; import pokecube.core.network.pokemobs.PacketCommand; import pokecube.core.network.pokemobs.PacketMountedControl; import pokecube.core.proxy.ClientProxy; +import pokecube.core.utils.PokemobTracker; import pokecube.core.utils.TagNames; import pokecube.core.utils.Tools; import thut.api.entity.genetics.GeneRegistry; @@ -87,6 +91,24 @@ public class EventsHandlerClient static long lastSetTime = 0; + /** + * Gets all pokemobs owned by owner within the given distance. + * + * @param owner + * @param distance + * @return + */ + public static List getPokemobs(final LivingEntity owner, final double distance) + { + final List ret = new ArrayList<>(); + for (final Entity e : PokemobTracker.getMobs(owner, e -> !(e instanceof EntityPokecubeBase))) + { + final IPokemob mob = CapabilityPokemob.getPokemobFor(e); + if (mob != null) ret.add(mob); + } + return ret; + } + @SubscribeEvent public static void clientTick(final TickEvent.PlayerTickEvent event) { diff --git a/src/main/java/pokecube/core/client/gui/GuiDisplayPokecubeInfo.java b/src/main/java/pokecube/core/client/gui/GuiDisplayPokecubeInfo.java index 4184a1a9a8..a2e96c2c0a 100644 --- a/src/main/java/pokecube/core/client/gui/GuiDisplayPokecubeInfo.java +++ b/src/main/java/pokecube/core/client/gui/GuiDisplayPokecubeInfo.java @@ -35,10 +35,10 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.client.EventsHandlerClient; import pokecube.core.client.GuiEvent; import pokecube.core.client.Resources; import pokecube.core.client.gui.pokemob.GuiPokemobBase; -import pokecube.core.handlers.events.EventsHandler; import pokecube.core.interfaces.IMoveConstants; import pokecube.core.interfaces.IMoveConstants.AIRoutine; import pokecube.core.interfaces.IMoveNames; @@ -531,7 +531,7 @@ public IPokemob[] getPokemobsToDisplay() if (player == null || player.getEntityWorld() == null) return new IPokemob[0]; - final List pokemobs = EventsHandler.getPokemobs(player, 96); + final List pokemobs = EventsHandlerClient.getPokemobs(player, 96); final List ret = new ArrayList<>(); for (final IPokemob pokemob : pokemobs) { diff --git a/src/main/java/pokecube/core/database/PokedexEntry.java b/src/main/java/pokecube/core/database/PokedexEntry.java index 4e081fc627..4fe689615d 100644 --- a/src/main/java/pokecube/core/database/PokedexEntry.java +++ b/src/main/java/pokecube/core/database/PokedexEntry.java @@ -1781,7 +1781,7 @@ protected void initRelations() * returns whether the interaction logic has a response listed for the * given key. * - * @param pokemob + * @param cube * @param doInteract * - if false, will not actually do anything. * @return diff --git a/src/main/java/pokecube/core/entity/pokemobs/EntityPokemob.java b/src/main/java/pokecube/core/entity/pokemobs/EntityPokemob.java index ad2bf19ce2..aec9f0e3a9 100644 --- a/src/main/java/pokecube/core/entity/pokemobs/EntityPokemob.java +++ b/src/main/java/pokecube/core/entity/pokemobs/EntityPokemob.java @@ -292,9 +292,12 @@ protected void handleFluidJump(final Tag fluidTag) @Override public void onAddedToWorld() { - PokemobTracker.addPokemob(this.pokemobCap); - if (this.pokemobCap.isPlayerOwned() && this.pokemobCap.getOwnerId() != null) PlayerPokemobCache.UpdateCache( - this.pokemobCap); + if (!this.isAddedToWorld()) + { + PokemobTracker.addPokemob(this.pokemobCap); + if (this.pokemobCap.isPlayerOwned() && this.pokemobCap.getOwnerId() != null) PlayerPokemobCache.UpdateCache( + this.pokemobCap); + } super.onAddedToWorld(); } diff --git a/src/main/java/pokecube/core/handlers/events/EventsHandler.java b/src/main/java/pokecube/core/handlers/events/EventsHandler.java index 3713516970..815cbf3ba8 100644 --- a/src/main/java/pokecube/core/handlers/events/EventsHandler.java +++ b/src/main/java/pokecube/core/handlers/events/EventsHandler.java @@ -29,7 +29,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; @@ -97,6 +96,7 @@ import pokecube.core.network.packets.PacketPokedex; import pokecube.core.utils.PokeType; import pokecube.core.utils.PokecubeSerializer; +import pokecube.core.utils.PokemobTracker; import pokecube.core.world.gen.jigsaw.JigsawPieces; import thut.api.boom.ExplosionCustom; import thut.api.entity.ShearableCaps; @@ -421,30 +421,6 @@ public static void explosionEvents(final ExplosionEvent.Detonate evt) } } - /** - * Gets all pokemobs owned by owner within the given distance. - * - * @param owner - * @param distance - * @return - */ - public static List getPokemobs(final LivingEntity owner, final double distance) - { - final List ret = new ArrayList<>(); - - final AxisAlignedBB box = new AxisAlignedBB(owner.posX, owner.posY, owner.posZ, owner.posX, owner.posY, - owner.posZ).grow(distance, distance, distance); - - final List pokemobs = owner.getEntityWorld().getEntitiesWithinAABB(LivingEntity.class, box); - for (final LivingEntity o : pokemobs) - { - final IPokemob mob = CapabilityPokemob.getPokemobFor(o); - if (mob != null) if (mob.getOwner() == owner) ret.add(mob); - } - - return ret; - } - @SubscribeEvent public static void denySpawns(final LivingSpawnEvent.CheckSpawn event) { @@ -520,17 +496,16 @@ public static void PokecubeWatchEvent(final StartTracking event) public static void recallAllPokemobs(final LivingEntity user) { if (!user.isServerWorld()) return; - final ServerWorld world = (ServerWorld) user.getEntityWorld(); - final List pokemobs = new ArrayList<>(world.getEntities(null, e -> EventsHandler.validRecall(user, e, - null, true))); + final List pokemobs = PokemobTracker.getMobs(user, e -> EventsHandler.validRecall(user, e, null, + false)); PCEventsHandler.recallAll(pokemobs, true); } public static void recallAllPokemobsExcluding(final ServerPlayerEntity player, final IPokemob excluded, final boolean includeStaying) { - final List pokemobs = new ArrayList<>(player.getServerWorld().getEntities(null, e -> EventsHandler - .validRecall(player, e, excluded, includeStaying))); + final List pokemobs = PokemobTracker.getMobs(player, e -> EventsHandler.validRecall(player, e, excluded, + includeStaying)); PCEventsHandler.recallAll(pokemobs, true); } diff --git a/src/main/java/pokecube/core/handlers/events/PCEventsHandler.java b/src/main/java/pokecube/core/handlers/events/PCEventsHandler.java index f6bef9500d..3d3abe2661 100644 --- a/src/main/java/pokecube/core/handlers/events/PCEventsHandler.java +++ b/src/main/java/pokecube/core/handlers/events/PCEventsHandler.java @@ -38,6 +38,7 @@ import pokecube.core.items.pokecubes.PokecubeManager; import pokecube.core.items.pokecubes.helper.SendOutManager; import pokecube.core.network.packets.PacketPC; +import pokecube.core.utils.PokemobTracker; import thut.core.common.ThutCore; public class PCEventsHandler @@ -54,8 +55,7 @@ public class PCEventsHandler public static List getOutMobs(final LivingEntity player, final boolean includeStay) { if (player == null) return Collections.emptyList(); - return ((ServerWorld) player.getEntityWorld()).getEntities(null, c -> EventsHandler.validRecall(player, c, null, - false, includeStay)); + return PokemobTracker.getMobs(player, c -> EventsHandler.validRecall(player, c, null, false, includeStay)); } /** @@ -173,6 +173,7 @@ public static void recallAll(final List mobs, final boolean cubesToPC) for (final Entity o : mobs) { final IPokemob pokemob = CapabilityPokemob.getPokemobFor(o); + if (!o.isAddedToWorld()) continue; if (pokemob != null) pokemob.onRecall(); else if (o instanceof EntityPokecube) { diff --git a/src/main/java/pokecube/core/items/pokecubes/EntityPokecube.java b/src/main/java/pokecube/core/items/pokecubes/EntityPokecube.java index c4027568b6..db6186a348 100644 --- a/src/main/java/pokecube/core/items/pokecubes/EntityPokecube.java +++ b/src/main/java/pokecube/core/items/pokecubes/EntityPokecube.java @@ -96,8 +96,9 @@ void writeToNBT(final CompoundNBT nbt) .immuneToFire().size(0.25f, 0.25f).build("pokecube"); } - public long reset = 0; - public long resetTime = 0; + public long reset = 0; + public long resetTime = 0; + public ArrayList players = Lists.newArrayList(); public ArrayList loot = Lists.newArrayList(); public ArrayList lootStacks = Lists.newArrayList(); diff --git a/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java b/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java index 8c00b12943..9d3c1c2304 100644 --- a/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java +++ b/src/main/java/pokecube/core/items/pokecubes/EntityPokecubeBase.java @@ -48,6 +48,7 @@ import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.items.pokecubes.helper.CaptureManager; import pokecube.core.items.pokecubes.helper.SendOutManager; +import pokecube.core.utils.PokemobTracker; import pokecube.core.utils.TagNames; import thut.api.maths.Vector3; import thut.core.common.network.EntityUpdate; @@ -124,6 +125,8 @@ public static void setNoCaptureBasedOnConfigs(final IPokemob pokemob) NonNullList stuff = NonNullList.create(); + public IPokemob containedMob; + public EntityPokecubeBase(final EntityType type, final World worldIn) { super(type, worldIn); @@ -215,6 +218,20 @@ protected void onImpact(final RayTraceResult result) } } + @Override + public void onAddedToWorld() + { + if (!this.isAddedToWorld()) PokemobTracker.addPokecube(this); + super.onAddedToWorld(); + } + + @Override + public void onRemovedFromWorld() + { + PokemobTracker.removePokecube(this); + super.onRemovedFromWorld(); + } + @Override public boolean canBeCollidedWith() { @@ -448,13 +465,13 @@ protected void registerData() /** Sets the ItemStack for this entity */ public void setItem(final ItemStack stack) { + if (this.isAddedToWorld()) PokemobTracker.removePokecube(this); this.getDataManager().set(EntityPokecubeBase.ITEM, stack); - } - - // For compatiblity - public void setItemEntityStack(final ItemStack stack) - { - this.setItem(stack); + if (this.isAddedToWorld()) + { + this.containedMob = PokecubeManager.itemToPokemob(stack, PokecubeCore.proxy.getWorld()); + PokemobTracker.addPokecube(this); + } } @Override @@ -552,12 +569,6 @@ public ItemStack getItem() return itemstack.isEmpty() ? new ItemStack(Blocks.STONE) : itemstack; } - // For compatiblity. - public ItemStack getItemEntity() - { - return this.getItem(); - } - @Override public ItemStack getItemStackFromSlot(final EquipmentSlotType slotIn) { diff --git a/src/main/java/pokecube/core/utils/PokemobTracker.java b/src/main/java/pokecube/core/utils/PokemobTracker.java index a9e4885816..2a211bcdc5 100644 --- a/src/main/java/pokecube/core/utils/PokemobTracker.java +++ b/src/main/java/pokecube/core/utils/PokemobTracker.java @@ -1,28 +1,37 @@ package pokecube.core.utils; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; +import com.google.common.collect.Lists; + +import net.minecraft.entity.Entity; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.event.world.WorldEvent.Load; import net.minecraftforge.eventbus.api.SubscribeEvent; import pokecube.core.database.PokedexEntry; import pokecube.core.interfaces.IPokemob; +import pokecube.core.items.pokecubes.EntityPokecubeBase; import thut.api.maths.Vector3; public class PokemobTracker { - private static class Entry implements Comparable + private static class MobEntry implements Comparable { final IPokemob pokemob; - public Entry(final IPokemob pokemob) + public MobEntry(final IPokemob pokemob) { this.pokemob = pokemob; } @@ -35,7 +44,7 @@ public BlockPos getPos() @Override public boolean equals(final Object obj) { - if (obj instanceof Entry) return ((Entry) obj).pokemob.getEntity().getUniqueID().equals(this.pokemob + if (obj instanceof MobEntry) return ((MobEntry) obj).pokemob.getEntity().getUniqueID().equals(this.pokemob .getEntity().getUniqueID()); return false; } @@ -47,41 +56,151 @@ public int hashCode() } @Override - public int compareTo(final Entry o) + public int compareTo(final MobEntry o) + { + return this.getPos().compareTo(o.getPos()); + } + } + + private static class CubeEntry implements Comparable + { + final EntityPokecubeBase cube; + + public CubeEntry(final EntityPokecubeBase cube) + { + this.cube = cube; + } + + public BlockPos getPos() + { + return this.cube.getEntity().getPosition(); + } + + @Override + public boolean equals(final Object obj) + { + if (obj instanceof MobEntry) return ((MobEntry) obj).pokemob.getEntity().getUniqueID().equals(this.cube + .getEntity().getUniqueID()); + return false; + } + + @Override + public int hashCode() + { + return this.cube.getEntity().getUniqueID().hashCode(); + } + + @Override + public int compareTo(final CubeEntry o) { return this.getPos().compareTo(o.getPos()); } } - private static Map> mobMap = new HashMap<>(); + // Client and server instances as they operate seperate worlds + private static final PokemobTracker CLIENT = new PokemobTracker(); + private static final PokemobTracker SERVER = new PokemobTracker(); - public static void addPokemob(final IPokemob pokemob) + private static PokemobTracker getFor(final Entity mob) { - // First remove the mob from all maps, incase it is in one. - PokemobTracker.removePokemob(pokemob); + return mob.getEntityWorld() instanceof ServerWorld ? PokemobTracker.SERVER : PokemobTracker.CLIENT; + } + + private static PokemobTracker getFor(final IWorld mob) + { + return mob.getWorld() instanceof ServerWorld ? PokemobTracker.SERVER : PokemobTracker.CLIENT; + } + + private final Map> liveMobs = new ConcurrentHashMap<>(); + private final Map> ownerMap = new ConcurrentHashMap<>(); + private final Map> ownedCubes = new ConcurrentHashMap<>(); + private MobEntry _addPokemob(final IPokemob pokemob) + { + // First remove the mob from all maps, incase it is in one. + final MobEntry e = PokemobTracker.removePokemob(pokemob); final DimensionType dim = pokemob.getEntity().dimension; // Find the appropriate map - final List mobList = PokemobTracker.mobMap.getOrDefault(dim, new ArrayList<>()); + final List mobList = this.liveMobs.getOrDefault(dim, new ArrayList<>()); // Register the dimension if not already there - if (!PokemobTracker.mobMap.containsKey(dim)) PokemobTracker.mobMap.put(dim, mobList); + if (!this.liveMobs.containsKey(dim)) this.liveMobs.put(dim, mobList); // Add the pokemob to the list - mobList.add(new Entry(pokemob)); + mobList.add(e); + + final UUID owner = pokemob.getOwnerId(); + if (owner == null) return e; + + final Set owned = this.ownerMap.getOrDefault(owner, new HashSet<>()); + // Register the dimension if not already there + if (!this.ownerMap.containsKey(owner)) this.ownerMap.put(owner, owned); + // Add the pokemob to the list + owned.add(e); + return e; } - public static void removePokemob(final IPokemob pokemob) + private MobEntry _removePokemob(final IPokemob pokemob) { - final Entry e = new Entry(pokemob); + final MobEntry e = new MobEntry(pokemob); + // Remove the mob from all maps, incase it is in one. + this.liveMobs.forEach((d, m) -> m.remove(e)); // Remove the mob from all maps, incase it is in one. - PokemobTracker.mobMap.forEach((d, m) -> m.remove(e)); + this.ownerMap.forEach((d, m) -> m.remove(e)); + // Thread.dumpStack(); + return e; + } + + private CubeEntry _addPokecube(final EntityPokecubeBase cube) + { + final UUID owner = cube.containedMob != null ? cube.containedMob.getOwnerId() : null; + if (owner == null) return null; + final CubeEntry e = PokemobTracker.removePokecube(cube); + final Set owned = this.ownedCubes.getOrDefault(owner, new HashSet<>()); + // Register the dimension if not already there + if (!this.ownedCubes.containsKey(owner)) this.ownedCubes.put(owner, owned); + // Add the pokemob to the list + owned.add(e); + return e; + } + + private CubeEntry _removePokecube(final EntityPokecubeBase cube) + { + final CubeEntry e = new CubeEntry(cube); + // Remove the mob from all maps, incase it is in one. + this.ownedCubes.forEach((d, m) -> m.remove(e)); + return e; + } + + public static MobEntry addPokemob(final IPokemob pokemob) + { + final PokemobTracker tracker = PokemobTracker.getFor(pokemob.getEntity()); + return tracker._addPokemob(pokemob); + } + + public static MobEntry removePokemob(final IPokemob pokemob) + { + final PokemobTracker tracker = PokemobTracker.getFor(pokemob.getEntity()); + return tracker._removePokemob(pokemob); + } + + public static CubeEntry addPokecube(final EntityPokecubeBase cube) + { + final PokemobTracker tracker = PokemobTracker.getFor(cube); + return tracker._addPokecube(cube); + } + + public static CubeEntry removePokecube(final EntityPokecubeBase cube) + { + final PokemobTracker tracker = PokemobTracker.getFor(cube); + return tracker._removePokecube(cube); } public static int countPokemobs(final IWorld world, final AxisAlignedBB box, final Predicate matches) { + final PokemobTracker tracker = PokemobTracker.getFor(world); final DimensionType dim = world.getDimension().getType(); - final Entry[] mobList = PokemobTracker.mobMap.getOrDefault(dim, new ArrayList<>()).toArray(new Entry[0]); + final MobEntry[] mobList = tracker.liveMobs.getOrDefault(dim, new ArrayList<>()).toArray(new MobEntry[0]); int num = 0; - for (final Entry e : mobList) + for (final MobEntry e : mobList) if (box.contains(e.getPos().getX(), e.getPos().getY(), e.getPos().getZ()) && matches.test(e.pokemob)) num++; return num; } @@ -111,11 +230,29 @@ public static int countPokemobs(final IWorld world, final Vector3 location, fina return PokemobTracker.countPokemobs(world, box); } + public static List getMobs(final Entity owner, final Predicate matcher) + { + final PokemobTracker tracker = PokemobTracker.getFor(owner); + final List pokemobs = Lists.newArrayList(); + final UUID id = owner.getUniqueID(); + final Set mobs = tracker.ownerMap.getOrDefault(id, Collections.emptySet()); + final Set cubes = tracker.ownedCubes.getOrDefault(id, Collections.emptySet()); + mobs.forEach(e -> + { + if (matcher.test(e.pokemob.getEntity())) pokemobs.add(e.pokemob.getEntity()); + }); + cubes.forEach(e -> + { + if (matcher.test(e.cube)) pokemobs.add(e.cube); + }); + return pokemobs; + } + @SubscribeEvent public static void worldLoadEvent(final Load evt) { - if (evt.getWorld().isRemote()) return; + final PokemobTracker tracker = PokemobTracker.getFor(evt.getWorld()); // Reset the tracked map for this world - PokemobTracker.mobMap.put(evt.getWorld().getDimension().getType(), new ArrayList<>()); + tracker.liveMobs.put(evt.getWorld().getDimension().getType(), new ArrayList<>()); } } From 74036833b4238b23f12fbe06ef0ea47558306f3f Mon Sep 17 00:00:00 2001 From: Thutmose Date: Sat, 23 May 2020 20:38:27 -0400 Subject: [PATCH 21/27] Converts trainers to new AI as well --- src/main/java/pokecube/adventures/Config.java | 15 +- .../adventures/ai/tasks/AIBattle.java | 359 ------------------ .../pokecube/adventures/ai/tasks/AIMate.java | 92 ----- .../adventures/ai/tasks/AIRetaliate.java | 62 --- .../adventures/ai/tasks/AITrainerAgro.java | 288 -------------- .../adventures/ai/tasks/AITrainerBase.java | 89 ----- .../adventures/ai/tasks/BaseTask.java | 49 +++ .../pokecube/adventures/ai/tasks/Tasks.java | 84 ++++ .../ai/tasks/battle/BaseBattleTask.java | 45 +++ .../CaptureMob.java} | 29 +- .../ai/tasks/battle/ChooseAttacks.java | 98 +++++ .../ai/tasks/battle/ManageOutMob.java | 135 +++++++ .../ai/tasks/battle/ManagePokemobTarget.java | 55 +++ .../ai/tasks/battle/agro/AgroTargets.java | 56 +++ .../ai/tasks/battle/agro/BaseAgroTask.java | 121 ++++++ .../ai/tasks/battle/agro/DeAgro.java | 129 +++++++ .../ai/tasks/battle/agro/Retaliate.java | 49 +++ .../adventures/ai/tasks/idle/Mate.java | 19 + .../capabilities/CapabilityHasPokemobs.java | 156 +++++--- .../capabilities/CapabilityNPCMessages.java | 3 +- .../capabilities/player/PlayerPokemobs.java | 11 +- .../capabilities/utils/BattleAction.java | 2 +- .../capabilities/utils/TypeTrainer.java | 62 +-- .../entity/trainer/TrainerBase.java | 15 +- .../events/TrainerEventHandler.java | 43 ++- .../pokecube/core/ai/brain/BrainUtils.java | 24 ++ .../core/ai/logic/LogicMiscUpdate.java | 9 +- .../java/pokecube/core/ai/npc/Schedules.java | 5 +- .../pokecube/core/ai/tasks/AIFollowOwner.java | 10 +- .../combat/management/FindTargetsTask.java | 100 +---- .../core/ai/tasks/utility/StoreTask.java | 2 +- .../java/pokecube/core/handlers/Config.java | 14 +- .../pokecube/core/interfaces/IPokecube.java | 25 +- .../capabilities/impl/PokemobMoves.java | 2 + .../pokecubes/DispenserBehaviorPokecube.java | 2 +- .../core/items/pokecubes/Pokecube.java | 22 +- .../java/pokecube/core/moves/MovesUtils.java | 4 +- .../java/pokecube/core/utils/AITools.java | 33 +- .../resources/META-INF/accesstransformer.cfg | 3 +- .../pokecube_adventures/lang/en_us.json | 2 + 40 files changed, 1145 insertions(+), 1178 deletions(-) delete mode 100644 src/main/java/pokecube/adventures/ai/tasks/AIBattle.java delete mode 100644 src/main/java/pokecube/adventures/ai/tasks/AIMate.java delete mode 100644 src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java delete mode 100644 src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java delete mode 100644 src/main/java/pokecube/adventures/ai/tasks/AITrainerBase.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/BaseTask.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/Tasks.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java rename src/main/java/pokecube/adventures/ai/tasks/{AICapture.java => battle/CaptureMob.java} (53%) create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/ChooseAttacks.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/battle/agro/Retaliate.java create mode 100644 src/main/java/pokecube/adventures/ai/tasks/idle/Mate.java diff --git a/src/main/java/pokecube/adventures/Config.java b/src/main/java/pokecube/adventures/Config.java index fb1f1bb04c..f79bb2b9d6 100644 --- a/src/main/java/pokecube/adventures/Config.java +++ b/src/main/java/pokecube/adventures/Config.java @@ -29,15 +29,19 @@ public class Config extends ConfigData private static final String BAG = "bag"; @Configure(category = Config.TRAINER) - public boolean npcsAreTrainers = true; + public boolean npcsAreTrainers = true; + + @Configure(category = Config.TRAINER) + public int trainerCooldown = 5000; @Configure(category = Config.TRAINER) - public int trainerCooldown = 5000; + public int trainerSightRange = 8; @Configure(category = Config.TRAINER) - public int trainerSightRange = 8; + public int trainerBattleDelay = 50; @Configure(category = Config.TRAINER) - public int trainerBattleDelay = 50; + public int trainerSendOutDelay = 50; @Configure(category = Config.TRAINER) - public int trainerSendOutDelay = 50; + public int trainerAgroRate = 20; + @Configure(category = Config.TRAINER) public boolean trainerslevel = true; @Configure(category = Config.TRAINER) @@ -157,6 +161,7 @@ public void onUpdated() AfaTile.initParser(this.afaCostFunction, this.afaCostFunctionShiny); this.dayCareTickRate = Math.max(1, this.dayCareTickRate); this.afaTickRate = Math.max(1, this.afaTickRate); + this.trainerAgroRate = Math.max(1, this.trainerAgroRate); if (this.autoAddFossilDNA) for (final Entry fossil : ItemGenerator.fossils.entrySet()) { diff --git a/src/main/java/pokecube/adventures/ai/tasks/AIBattle.java b/src/main/java/pokecube/adventures/ai/tasks/AIBattle.java deleted file mode 100644 index 84e96064ac..0000000000 --- a/src/main/java/pokecube/adventures/ai/tasks/AIBattle.java +++ /dev/null @@ -1,359 +0,0 @@ -package pokecube.adventures.ai.tasks; - -import java.util.List; - -import net.minecraft.command.arguments.EntityAnchorArgument.Type; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.MobEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.pathfinding.PathNavigator; -import net.minecraft.util.math.BlockPos; -import pokecube.adventures.Config; -import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; -import pokecube.adventures.capabilities.CapabilityNPCAIStates.IHasNPCAIStates; -import pokecube.adventures.capabilities.TrainerCaps; -import pokecube.adventures.capabilities.utils.MessageState; -import pokecube.core.PokecubeCore; -import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.database.Database; -import pokecube.core.database.PokedexEntry; -import pokecube.core.handlers.events.PCEventsHandler; -import pokecube.core.interfaces.IPokemob; -import pokecube.core.interfaces.Move_Base; -import pokecube.core.interfaces.capabilities.CapabilityPokemob; -import pokecube.core.interfaces.pokemob.ai.CombatStates; -import pokecube.core.items.pokecubes.EntityPokecubeBase; -import pokecube.core.items.pokecubes.PokecubeManager; -import pokecube.core.moves.MovesUtils; -import pokecube.core.utils.PokeType; -import thut.api.maths.Vector3; - -public class AIBattle extends AITrainerBase -{ - private boolean canPath = true; - private BlockPos battleLoc = null; - private int deagrotimer = 0; - - public AIBattle(final LivingEntity trainer) - { - this(trainer, true); - } - - public AIBattle(final LivingEntity trainer, final boolean canPath) - { - super(trainer); - this.canPath = canPath; - } - - private boolean checkPokemobTarget() - { - final Entity mobTarget = BrainUtils.getAttackTarget(this.trainer.getOutMob().getEntity()); - final IPokemob target = CapabilityPokemob.getPokemobFor(mobTarget); - if (!this.trainer.getOutMob().getCombatState(CombatStates.ANGRY)) this.trainer.getOutMob().setCombatState( - CombatStates.ANGRY, true); - // check if pokemob's target is same as trainers. - if (mobTarget != this.trainer.getTarget() && target == null) BrainUtils.initiateCombat(this.trainer - .getOutMob().getEntity(), this.trainer.getTarget()); - // Return if trainer's pokemob's target is also a pokemob. - return CapabilityPokemob.getPokemobFor(BrainUtils.getAttackTarget(this.trainer.getOutMob() - .getEntity())) != null; - } - - private void considerSwapMove() - { - // TODO choose between damaging/stats/status moves - this.setMostDamagingMove(); - } - - private boolean considerSwapPokemob() - { - // TODO check if the target pokemob is bad matchup, consider swapping to - // better choice. - - // check if can mega evolve - final IPokemob out = this.trainer.getOutMob(); - if (this.trainer.canMegaEvolve() && out != null && out.getPokedexEntry().hasMegaForm) - { - final List formes = Database.getFormes(out.getPokedexEntry()); - if (!formes.isEmpty()) - { - final int start = this.entity.getRNG().nextInt(formes.size()); - for (int i = 0; i < formes.size(); i++) - { - final PokedexEntry mega = formes.get((i + start) % formes.size()); - if (mega.isMega) - { - out.megaEvolve(mega); - break; - } - } - } - - } - return false; - } - - void doAggression() - { - // Check if we are being targetted by the enemies pokemob, if so, we - // will make it be passive for now. - if (this.entity instanceof MobEntity) - { - final Entity target = BrainUtils.getAttackTarget(this.entity); - if (target instanceof LivingEntity) BrainUtils.initiateCombat((MobEntity) this.entity, - (LivingEntity) target); - } - - // Check if maybe mob was sent out, but just not seen - final List mobs = PCEventsHandler.getOutMobs(this.entity, false); - if (!mobs.isEmpty()) - { - boolean found = false; - for (final Entity mob : mobs) - // Ones not added to chunk are in pokecubes, so wait for them to - // exit. - if (mob.addedToChunk) - { - final IPokemob pokemob = CapabilityPokemob.getPokemobFor(mob); - if (pokemob != null && !found) - { - this.trainer.setOutMob(pokemob); - found = true; - } - // Prevent players from grabbing the pokecube of the - // trainer. - else if (mob instanceof EntityPokecubeBase) - { - final EntityPokecubeBase cube = (EntityPokecubeBase) mob; - if (cube.canBePickedUp) - { - // This prevents pickup - cube.canBePickedUp = false; - // This makes it send out in 1s regardless of - // hitting anything. - cube.autoRelease = 20; - } - } - } - return; - } - - final int cooldown = this.trainer.getTarget() instanceof PlayerEntity ? this.trainer.getAttackCooldown() : 0; - - // If no mob was found, then it means trainer was not throwing cubes, as - // those are counted along with active pokemobs. - this.aiTracker.setAIState(IHasNPCAIStates.THROWING, false); - // If the trainer is on attack cooldown, then check if to send message - // about next pokemob, or to return early. - if (cooldown > 0) - { - // If no next pokemob, reset trainer and return early. - if (this.trainer.getNextPokemob().isEmpty()) - { - this.aiTracker.setAIState(IHasNPCAIStates.INBATTLE, false); - this.trainer.onLose(this.trainer.getTarget()); - this.trainer.resetPokemob(); - return; - } - // If cooldown is at specific number, send the message for sending - // out next pokemob. - if (cooldown == Config.instance.trainerSendOutDelay / 2) - { - final ItemStack nextStack = this.trainer.getNextPokemob(); - if (!nextStack.isEmpty()) - { - IPokemob next = PokecubeManager.itemToPokemob(nextStack, this.world); - if (next != null) - { - // check if our mob should evolve, if so, do so - while (next.canEvolve(next.getHeldItem())) - { - next = next.evolve(false, false); - nextStack.setTag(PokecubeManager.pokemobToItem(next).getTag()); - } - this.messages.sendMessage(MessageState.ABOUTSEND, this.trainer.getTarget(), this.entity - .getDisplayName(), next.getDisplayName(), this.trainer.getTarget().getDisplayName()); - this.messages.doAction(MessageState.ABOUTSEND, this.trainer.getTarget(), this.entity); - } - } - } - return; - } - // Send next cube at the target. - this.trainer.throwCubeAt(this.trainer.getTarget()); - } - - /** - * @param move - * - the attack to check - * @param user - * - the user of the sttack - * @param target - * - the target of the attack - * @return - the damage that will be dealt by the attack (before reduction - * due to armour) - */ - private int getPower(final String move, final IPokemob user, final Entity target) - { - final Move_Base attack = MovesUtils.getMoveFromName(move); - if (attack == null) return 0; - int pwr = attack.getPWR(user, target); - final IPokemob mob = CapabilityPokemob.getPokemobFor(target); - if (mob != null) pwr *= PokeType.getAttackEfficiency(attack.getType(user), mob.getType1(), mob.getType2()); - return pwr; - } - - /** Resets the task */ - @Override - public void reset() - { - this.trainer.resetPokemob(); - this.trainer.setTarget(null); - this.battleLoc = null; - } - - /** - * Searches for pokemobs most damaging move against the target, and sets it - * as current attack - */ - private void setMostDamagingMove() - { - final IPokemob outMob = this.trainer.getOutMob(); - int index = outMob.getMoveIndex(); - int max = 0; - final Entity target = BrainUtils.getAttackTarget(outMob.getEntity()); - final String[] moves = outMob.getMoves(); - for (int i = 0; i < 4; i++) - { - final String s = moves[i]; - if (s != null) - { - final int temp = this.getPower(s, outMob, target); - if (temp > max) - { - index = i; - max = temp; - } - } - } - outMob.setMoveIndex(index); - } - - @Override - public boolean shouldRun() - { - final LivingEntity target = this.trainer.getTarget(); - if (target == null) return false; - final IHasPokemobs other = TrainerCaps.getHasPokemobs(target); - final boolean hitUs = target.getLastAttackedEntity() == this.entity; - if (!hitUs && other != null && other.getNextPokemob().isEmpty()) - { - if (other.getOutID() != null) - { - final IPokemob outMob = other.getOutMob(); - if (outMob != null && !outMob.getEntity().isAlive()) - { - other.setOutID(null); - other.setOutMob(null); - } - } - if (other.getOutID() == null) - { - final List mobs = PCEventsHandler.getOutMobs(target, false); - if (!mobs.isEmpty()) - { - boolean found = false; - for (final Entity mob : mobs) - if (mob.addedToChunk && mob.getDistanceSq(target) < 32 * 32) - { - final IPokemob pokemob = CapabilityPokemob.getPokemobFor(mob); - if (pokemob != null && !found) - { - other.setOutMob(pokemob); - found = true; - break; - } - } - this.deagrotimer = 20; - } - if (this.deagrotimer-- < 0) - { - this.trainer.onWin(target); - if (other.getTarget() == this.entity) other.onLose(this.entity); - return false; - } - } - } - return true; - } - - @Override - public void tick() - { - // Check if trainer has any pokemobs, if not, cancel agression, no - // reward. - if (this.trainer.getPokemob(0).isEmpty()) - { - this.trainer.deAgro(this.trainer, TrainerCaps.getHasPokemobs(this.trainer.getTarget())); - this.trainer.setTarget(null); - return; - } - - // Stop trainer from pathing if it shouldn't do so during battle - if (!this.canPath && this.entity instanceof MobEntity) - { - if (this.battleLoc == null) this.battleLoc = this.entity.getPosition(); - final PathNavigator navi = ((MobEntity) this.entity).getNavigator(); - if (!navi.noPath() && navi.getPath().getFinalPathPoint().func_224758_c(this.battleLoc) > 1) navi - .clearPath(); - if (this.entity.getPosition().distanceSq(this.battleLoc) > 4) navi.setPath(navi.getPathToPos(this.battleLoc, - 0), 0.75); - } - - this.entity.lookAt(Type.EYES, this.trainer.getTarget().getEyePosition(0)); - - // If target is no longer visbile, forget about it and reset. - if (!Vector3.isVisibleEntityFromEntity(this.entity, this.trainer.getTarget())) - { - if (this.noSeeTicks++ > Config.instance.trainerDeAgressTicks) - { - this.trainer.setTarget(null); - this.trainer.resetPokemob(); - } - return; - } - this.noSeeTicks = 0; - // Check if in range, if too far, target has run away, so forget about - // it. - final double distance = this.entity.getDistanceSq(this.trainer.getTarget()); - if (distance > PokecubeCore.getConfig().chaseDistance * PokecubeCore.getConfig().chaseDistance) - { - this.trainer.setTarget(null); - this.trainer.resetPokemob(); - } - else if (this.trainer.getOutMob() != null && this.trainer.getOutMob().getEntity().isAlive() && this.trainer - .getOutMob().getEntity().addedToChunk) - { - // If trainer has a living, real mob out, tell it to do stuff. - // Check if pokemob has a valid Pokemob as a target. - if (this.checkPokemobTarget()) - { - // If not swapping the pokemob (not implemented), then Ensure - // using best move for target. - if (!this.considerSwapPokemob()) this.considerSwapMove(); - } - // Otherwise, set to most damaging more for non pokemobs. - else this.setMostDamagingMove(); - } - else - { - // Set out mob to null if it is dead so the trainer forgets about - // it. - this.trainer.setOutMob(null); - // Do agression code for sending out next pokemob. - this.doAggression(); - } - } -} diff --git a/src/main/java/pokecube/adventures/ai/tasks/AIMate.java b/src/main/java/pokecube/adventures/ai/tasks/AIMate.java deleted file mode 100644 index 303a8578af..0000000000 --- a/src/main/java/pokecube/adventures/ai/tasks/AIMate.java +++ /dev/null @@ -1,92 +0,0 @@ -package pokecube.adventures.ai.tasks; - -import net.minecraft.entity.AgeableEntity; -import net.minecraft.entity.EntityPredicate; -import net.minecraft.entity.LivingEntity; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.living.BabyEntitySpawnEvent; -import pokecube.adventures.Config; -import pokecube.adventures.capabilities.CapabilityNPCAIStates.IHasNPCAIStates; -import pokecube.adventures.utils.TrainerTracker; -import pokecube.core.PokecubeCore; -import pokecube.core.interfaces.PokecubeMod; -import thut.api.maths.Vector3; - -public class AIMate extends AITrainerBase -{ - AgeableEntity foundMate = null; - final Class targetClass; - final AgeableEntity thisEntity; - AgeableEntity child = null; - int mateTimer = -1; - final EntityPredicate predicate; - - public AIMate(final LivingEntity trainer, final Class targetClass) - { - super(trainer); - this.targetClass = targetClass; - if (trainer instanceof AgeableEntity) this.thisEntity = (AgeableEntity) trainer; - else this.thisEntity = null; - this.predicate = new EntityPredicate().setDistance(8); - } - - @Override - public boolean shouldRun() - { - if (!Config.instance.trainersMate) return false; - return this.thisEntity != null && this.thisEntity.getGrowingAge() == 0 && this.trainer.getGender() == 2 - && this.aiTracker.getAIState(IHasNPCAIStates.MATES) && TrainerTracker.countTrainers(this.world, Vector3 - .getNewVector().set(this.thisEntity), - Config.instance.trainerBox) < Config.instance.trainerDensity * 2; - } - - @Override - public void tick() - { - super.tick(); - if (this.shouldRun()) - { - if (PokecubeMod.debug) PokecubeCore.LOGGER.debug(this.thisEntity + " is Looking for mate"); - this.foundMate = this.world.getClosestEntityWithinAABB(this.targetClass, this.predicate, this.thisEntity, - this.thisEntity.posX, this.thisEntity.posY + this.thisEntity.getEyeHeight(), this.thisEntity.posZ, - this.thisEntity.getBoundingBox().grow(8.0D, 3.0D, 8.0D)); - if (this.foundMate == null) - { - this.thisEntity.setGrowingAge(600); - return; - } - if (this.world.getEntitiesWithinAABB(this.targetClass, this.thisEntity.getBoundingBox().grow(16.0D, 10.0D, - 16.0D)).size() > 3) - { - this.thisEntity.setGrowingAge(6000); - return; - } - this.child = this.thisEntity.createChild(this.foundMate); - this.thisEntity.setGrowingAge(6000); - this.foundMate.setGrowingAge(6000); - final BabyEntitySpawnEvent event = new net.minecraftforge.event.entity.living.BabyEntitySpawnEvent( - this.thisEntity, this.foundMate, this.child); - if (MinecraftForge.EVENT_BUS.post(event) || event.getChild() == null) return; - this.child = event.getChild(); - this.child.setGrowingAge(-24000); - this.mateTimer = 50; - } - if (this.child != null && this.foundMate != null) if (this.mateTimer-- <= 0) - { - this.thisEntity.getNavigator().tryMoveToEntityLiving(this.foundMate, this.thisEntity.getAIMoveSpeed()); - this.foundMate.getNavigator().tryMoveToEntityLiving(this.thisEntity, this.foundMate.getAIMoveSpeed()); - } - else - { - final Vector3 loc = Vector3.getNewVector().set(this.thisEntity.getLookVec()); - loc.y = 0; - loc.norm(); - this.child.setLocationAndAngles(this.thisEntity.posX + loc.x, this.thisEntity.posY, this.thisEntity.posZ - + loc.z, 0.0F, 0.0F); - this.world.addEntity(this.child); - this.world.setEntityState(this.child, (byte) 12); - this.child = null; - this.foundMate = null; - } - } -} diff --git a/src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java b/src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java deleted file mode 100644 index f3d5615386..0000000000 --- a/src/main/java/pokecube/adventures/ai/tasks/AIRetaliate.java +++ /dev/null @@ -1,62 +0,0 @@ -package pokecube.adventures.ai.tasks; - -import net.minecraft.entity.LivingEntity; -import net.minecraft.util.EntityPredicates; -import pokecube.adventures.capabilities.CapabilityHasPokemobs.ITargetWatcher; - -public class AIRetaliate extends AITrainerBase implements ITargetWatcher -{ - - public AIRetaliate(final LivingEntity entityIn) - { - super(entityIn); - this.trainer.addTargetWatcher(this); - } - - @Override - public boolean shouldRun() - { - if (this.trainer.getTarget() != null) return false; - // Dead trainers can't fight. - if (!this.entity.isAlive()) return false; - // Trainers on cooldown shouldn't fight, neither should friendly ones - if (this.trainer.getCooldown() > this.entity.getEntityWorld().getGameTime() || !this.trainer.isAgressive()) - return false; - final LivingEntity target = this.entity.getAttackingEntity(); - return this.isValidTarget(target); - } - - @Override - public void tick() - { - this.updateTask(); - } - - public void updateTask() - { - // If target is valid, return. - if (this.trainer.getTarget() != null) return; - final LivingEntity target = this.entity.getAttackingEntity(); - - if (target != null) - { - // Set trainers target - this.trainer.setTarget(target); - // Ensure no cooldown - this.trainer.setAttackCooldown(-1); - } - } - - @Override - public boolean isValidTarget(final LivingEntity target) - { - if (target == null) return false; - if (!(target.isAlive() && this.entity.canEntityBeSeen(target))) return false; - if (!EntityPredicates.CAN_AI_TARGET.test(target)) return false; - if (target != null && target.getLastAttackedEntity() == this.entity && target - .getLastAttackedEntityTime() < target.ticksExisted + 20) return true; - final int timer = this.entity.getRevengeTimer(); - final int age = this.entity.ticksExisted - 50; - return this.entity.getAttackingEntity() == target && timer > age; - } -} diff --git a/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java b/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java deleted file mode 100644 index 64bc586fd9..0000000000 --- a/src/main/java/pokecube/adventures/ai/tasks/AITrainerAgro.java +++ /dev/null @@ -1,288 +0,0 @@ -package pokecube.adventures.ai.tasks; - -import java.util.List; -import java.util.function.Predicate; - -import com.google.common.collect.Lists; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.MobEntity; -import net.minecraft.entity.ai.brain.memory.MemoryModuleType; -import net.minecraft.util.EntityPredicates; -import net.minecraft.util.math.Vec3d; -import pokecube.adventures.PokecubeAdv; -import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; -import pokecube.adventures.capabilities.CapabilityHasPokemobs.ITargetWatcher; -import pokecube.adventures.capabilities.CapabilityNPCAIStates.IHasNPCAIStates; -import pokecube.adventures.capabilities.TrainerCaps; -import pokecube.adventures.utils.TrainerTracker; -import pokecube.core.PokecubeCore; -import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.handlers.events.PCEventsHandler; -import pokecube.core.interfaces.IPokemob; -import pokecube.core.interfaces.capabilities.CapabilityPokemob; -import pokecube.core.utils.AITools; -import thut.api.IOwnable; -import thut.api.OwnableCaps; -import thut.api.maths.Vector3; - -public class AITrainerAgro extends AITrainerBase implements ITargetWatcher -{ - public static boolean canBattle(final LivingEntity input, final LivingEntity mobIn) - { - if (input != null && input.getLastAttackedEntity() == mobIn) return true; - if (mobIn.getRevengeTarget() != null && mobIn.getRevengeTarget() == input) return true; - final IHasPokemobs other = TrainerCaps.getHasPokemobs(input); - if (other == null) return true; - if (other.getTarget() != null && other.getTarget() != mobIn) return false; - if (other.getNextPokemob().isEmpty() && other.getOutID() == null) - { - boolean found = false; - if (other.getOutID() == null) - { - final List mobs = PCEventsHandler.getOutMobs(input, false); - if (!mobs.isEmpty()) for (final Entity mob : mobs) - if (mob.getDistanceSq(input) < 32 * 32) - { - final IPokemob pokemob = CapabilityPokemob.getPokemobFor(mob); - if (pokemob != null && !found) - { - other.setOutMob(pokemob); - found = true; - break; - } - } - } - return found; - } - return true; - } - - @SafeVarargs - public static Predicate match(final LivingEntity entityIn, final boolean allowTamed, - final Class... targetClass) - { - return new Predicate() - { - IHasPokemobs trainer = TrainerCaps.getHasPokemobs(entityIn); - - @Override - public boolean test(final LivingEntity input) - { - if (!AITools.validTargets.test(input)) return false; - - // If the input has attacked us recently, then return true - // regardless of following checks. - if (input.getLastAttackedEntity() == entityIn && input.ticksExisted - input - .getLastAttackedEntityTime() < 50) return true; - - final boolean validClass = this.validClass(input); - final boolean validAgro = input.attackable(); - final boolean canBattle = AITrainerAgro.canBattle(input, entityIn); - - // Only target valid classes. - if (!validClass || !validAgro || !canBattle) return false; - final IOwnable ownable = OwnableCaps.getOwnable(input); - // Don't target pets - if (ownable != null && ownable.getOwner() == entityIn) return false; - // Maybe not target other's pets as well - if (!this.tameCheck(input)) return false; - // Don't target invulnerable players (spectator/creative) - if (!EntityPredicates.CAN_AI_TARGET.test(input)) return false; - // Return true if player can battle the input. - return this.trainer.canBattle(input); - } - - private boolean tameCheck(final LivingEntity input) - { - if (allowTamed) return true; - final IOwnable mob = OwnableCaps.getOwnable(input); - if (mob == null) return true; - return mob.getOwnerId() == null; - } - - private boolean validClass(final LivingEntity input) - { - for (final Class s : targetClass) - if (s.isInstance(input)) return true; - return false; - } - }; - } - - @SafeVarargs - public static Predicate match(final LivingEntity entityIn, - final Class... targetClass) - { - return AITrainerAgro.match(entityIn, false, targetClass); - } - - // Predicated to return true for invalid targets - final Predicate validTargets; - - private float agroChance = 1f; - private int timer = 0; - private final int maxTimer; - - final Vector3 here = Vector3.getNewVector(); - - // This is whether the ai should run for the current task holder - private Predicate shouldRun = e -> true; - - public AITrainerAgro(final LivingEntity entityIn, final float agressionProbability, final int battleTime, - final Predicate validTargets) - { - super(entityIn); - this.trainer.addTargetWatcher(this); - this.maxTimer = battleTime; - this.agroChance = agressionProbability; - this.validTargets = validTargets; - } - - @SafeVarargs - public AITrainerAgro(final LivingEntity entityIn, final Class... targetClass) - { - this(entityIn, 1, -1, targetClass); - } - - @SafeVarargs - public AITrainerAgro(final LivingEntity entityIn, final float agressionProbability, - final Class... targetClass) - { - this(entityIn, agressionProbability, -1, targetClass); - } - - @SafeVarargs - public AITrainerAgro(final LivingEntity entityIn, final float agressionProbability, final int battleTime, - final Class... targetClass) - { - this(entityIn, agressionProbability, battleTime, AITrainerAgro.match(entityIn, targetClass)); - } - - public AITrainerAgro setRunCondition(final Predicate shouldRun) - { - this.shouldRun = shouldRun; - return this; - } - - @Override - public boolean shouldRun() - { - if (!this.shouldRun.test(this.entity)) return false; - if (this.trainer.getTarget() != null) - { - final LivingEntity target = this.trainer.getTarget(); - // Check if timer has run out. - if (this.maxTimer > 0 && this.timer++ >= this.maxTimer) - { - this.timer = 0; - final IHasPokemobs other = TrainerCaps.getHasPokemobs(target); - // this is an ended battle, so we cancel both side. - if (other != null) other.setTarget(null); - - // Lets reset revenge/battle targets as well. - if (target.getRevengeTarget() == this.entity) target.setRevengeTarget(null); - if (this.entity.getRevengeTarget() == target) this.entity.setRevengeTarget(null); - // Reset attack targets as well. - if (target instanceof MobEntity) BrainUtils.deagro(target); - BrainUtils.deagro(this.entity); - - this.trainer.setTarget(null); - this.trainer.resetPokemob(); - return false; - } - // Check if target is invalid. - if (!target.isAlive()) - { - this.trainer.setTarget(null); - this.trainer.resetPokemob(); - return false; - } - // check if too far away - if (this.entity.getDistance(target) > PokecubeCore.getConfig().chaseDistance) - { - this.trainer.setTarget(null); - this.trainer.resetPokemob(); - return false; - } - return false; - } - // Dead trainers can't fight. - if (!this.entity.isAlive()) return false; - // Permfriendly trainers shouldn't fight. - if (this.aiTracker != null && this.aiTracker.getAIState(IHasNPCAIStates.PERMFRIENDLY)) return false; - // Trainers on cooldown shouldn't fight, neither should friendly ones - if (this.trainer.getCooldown() > this.entity.getEntityWorld().getGameTime() || !this.trainer.isAgressive()) - return false; - return this.entity.getBrain().hasMemory(MemoryModuleType.VISIBLE_MOBS); - } - - @Override - public void tick() - { - if (this.aiTracker != null && this.aiTracker.getAIState(IHasNPCAIStates.FIXEDDIRECTION) && this.trainer - .getTarget() == null) - { - this.entity.setRotationYawHead(this.aiTracker.getDirection()); - this.entity.prevRotationYawHead = this.aiTracker.getDirection(); - this.entity.rotationYawHead = this.aiTracker.getDirection(); - this.entity.rotationYaw = this.aiTracker.getDirection(); - this.entity.prevRotationYaw = this.aiTracker.getDirection(); - } - this.updateTask(); - } - - public void updateTask() - { - // If target is valid, return. - if (this.trainer.getTarget() != null) return; - - // Check random chance of actually aquiring a target. - if (Math.random() > this.agroChance) return; - - // Look for targets - this.here.set(this.entity, true); - LivingEntity target = null; - final int sight = this.trainer.getAgressDistance(); - - final Vec3d start = new Vec3d(this.here.x, this.here.y, this.here.z); - final Vector3 look = Vector3.getNewVector().set(this.entity.getLook(1)).scalarMultBy(sight).addTo(this.here); - final Vec3d end = new Vec3d(look.x, look.y, look.z); - - final Predicate matcher = e -> e instanceof LivingEntity && this.isValidTarget((LivingEntity) e) && e - .getDistance(this.entity) <= sight && e.getBoundingBox().rayTrace(start, end).isPresent(); - - final List targets = Lists.newArrayList(this.entity.getBrain().getMemory( - MemoryModuleType.VISIBLE_MOBS).get()); - - targets.removeIf(e -> !matcher.test(e)); - - if (!targets.isEmpty()) target = targets.get(0); - - // If no target, return false. - if (target == null) - { - // If trainer was in battle (any of these 3) reset trainer before - // returning. - if (this.trainer.getOutMob() != null || this.aiTracker.getAIState(IHasNPCAIStates.THROWING) - || this.aiTracker.getAIState(IHasNPCAIStates.INBATTLE)) this.trainer.resetPokemob(); - return; - } - final IHasPokemobs other = TrainerCaps.getHasPokemobs(target); - // Set trainers target - this.trainer.setTarget(target); - if (other != null) other.setTarget(this.entity); - } - - @Override - public boolean isValidTarget(final LivingEntity target) - { - if (!EntityPredicates.CAN_AI_TARGET.test(target)) return false; - this.here.set(this.entity, true); - final int dist = PokecubeAdv.config.trainer_crowding_radius; - final int num = PokecubeAdv.config.trainer_crowding_number; - if (TrainerTracker.countTrainers(this.world, this.here, dist) > num) return false; - return this.validTargets.test(target); - } -} diff --git a/src/main/java/pokecube/adventures/ai/tasks/AITrainerBase.java b/src/main/java/pokecube/adventures/ai/tasks/AITrainerBase.java deleted file mode 100644 index 5c227038f4..0000000000 --- a/src/main/java/pokecube/adventures/ai/tasks/AITrainerBase.java +++ /dev/null @@ -1,89 +0,0 @@ -package pokecube.adventures.ai.tasks; - -import java.util.List; - -import com.google.common.collect.Lists; - -import net.minecraft.entity.LivingEntity; -import net.minecraft.world.server.ServerWorld; -import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; -import pokecube.adventures.capabilities.CapabilityNPCAIStates.IHasNPCAIStates; -import pokecube.adventures.capabilities.CapabilityNPCMessages.IHasMessages; -import pokecube.adventures.capabilities.TrainerCaps; -import pokecube.core.ai.tasks.IRunnable; -import thut.api.entity.ai.IAIRunnable; - -public class AITrainerBase implements IAIRunnable -{ - ServerWorld world; - // The trainer Entity - final LivingEntity entity; - final IHasPokemobs trainer; - final IHasNPCAIStates aiTracker; - final IHasMessages messages; - final boolean valid; - int noSeeTicks = 0; - protected List toRun = Lists.newArrayList(); - - int priority = 0; - int mutex = 0; - - public AITrainerBase(final LivingEntity trainer) - { - this.entity = trainer; - this.world = (ServerWorld) trainer.getEntityWorld(); - this.aiTracker = TrainerCaps.getNPCAIStates(trainer); - this.trainer = TrainerCaps.getHasPokemobs(trainer); - this.messages = TrainerCaps.getMessages(trainer); - this.valid = trainer != null && this.aiTracker != null && this.messages != null; - } - - @Override - public void finish() - { - this.toRun.forEach(w -> w.run(this.world)); - this.toRun.clear(); - } - - @Override - public int getMutex() - { - return this.mutex; - } - - @Override - public int getPriority() - { - return this.priority; - } - - @Override - public void reset() - { - } - - @Override - public void run() - { - } - - @Override - public IAIRunnable setMutex(final int mutex) - { - this.mutex = mutex; - return this; - } - - @Override - public IAIRunnable setPriority(final int prior) - { - this.priority = prior; - return this; - } - - @Override - public boolean shouldRun() - { - return true; - } -} diff --git a/src/main/java/pokecube/adventures/ai/tasks/BaseTask.java b/src/main/java/pokecube/adventures/ai/tasks/BaseTask.java new file mode 100644 index 0000000000..f9507629ab --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/BaseTask.java @@ -0,0 +1,49 @@ +package pokecube.adventures.ai.tasks; + +import java.util.Map; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.task.Task; +import net.minecraft.world.server.ServerWorld; +import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; +import pokecube.adventures.capabilities.CapabilityNPCAIStates.IHasNPCAIStates; +import pokecube.adventures.capabilities.CapabilityNPCMessages.IHasMessages; +import pokecube.adventures.capabilities.TrainerCaps; + +public abstract class BaseTask extends Task +{ + protected ServerWorld world; + // The trainer Entity + protected final LivingEntity entity; + protected final IHasPokemobs trainer; + protected final IHasNPCAIStates aiTracker; + protected final IHasMessages messages; + protected final boolean valid; + + public BaseTask(final LivingEntity trainer, + final Map, MemoryModuleStatus> requiredMemoryStateIn) + { + super(requiredMemoryStateIn); + this.entity = trainer; + this.world = (ServerWorld) trainer.getEntityWorld(); + this.aiTracker = TrainerCaps.getNPCAIStates(trainer); + this.trainer = TrainerCaps.getHasPokemobs(trainer); + this.messages = TrainerCaps.getMessages(trainer); + this.valid = trainer != null && this.aiTracker != null && this.messages != null; + } + + protected boolean canTimeOut() + { + return false; + } + + @Override + protected boolean isTimedOut(final long gameTime) + { + if (!this.canTimeOut()) return false; + return super.isTimedOut(gameTime); + } + +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/Tasks.java b/src/main/java/pokecube/adventures/ai/tasks/Tasks.java new file mode 100644 index 0000000000..fc27812ee5 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/Tasks.java @@ -0,0 +1,84 @@ +package pokecube.adventures.ai.tasks; + +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.mojang.datafixers.util.Pair; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.Brain; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.schedule.Activity; +import net.minecraft.entity.ai.brain.sensor.DummySensor; +import net.minecraft.entity.ai.brain.sensor.SensorType; +import net.minecraft.entity.ai.brain.task.Task; +import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.ai.tasks.battle.ChooseAttacks; +import pokecube.adventures.ai.tasks.battle.ManageOutMob; +import pokecube.adventures.ai.tasks.battle.ManagePokemobTarget; +import pokecube.adventures.ai.tasks.battle.agro.BaseAgroTask; +import pokecube.adventures.ai.tasks.battle.agro.DeAgro; +import pokecube.adventures.ai.tasks.battle.agro.Retaliate; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.brain.MemoryModules; +import pokecube.core.ai.brain.Sensors; +import pokecube.core.ai.npc.Activities; + +public class Tasks +{ + public static final SensorType DUMMY = new SensorType<>(DummySensor::new); + + static + { + Tasks.DUMMY.setRegistryName(PokecubeAdv.MODID, "dummy_sensor"); + } + + public static final List> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, + SensorType.NEAREST_PLAYERS, SensorType.INTERACTABLE_DOORS, SensorType.HURT_BY, Sensors.VISIBLE_BLOCKS, + Sensors.VISIBLE_ITEMS, Sensors.INTERESTING_MOBS); + + public static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModules.ATTACKTARGET); + + @SuppressWarnings("unchecked") + public static void addBattleTasks(final LivingEntity mob, + final List>> tasks) + { + final Brain brain = mob.getBrain(); + + final List> senses = Lists.newArrayList(Tasks.DUMMY); + for (final SensorType type : Tasks.SENSOR_TYPES) + if (!brain.sensors.containsKey(type)) senses.add(type); + + BrainUtils.addToBrain(brain, Tasks.MEMORY_TYPES, senses); + + final List>> battle_list = Lists.newArrayList(); + final List>> other_list = Lists.newArrayList(); + for (final Pair> task_pair : tasks) + if (task_pair.getSecond() instanceof BaseAgroTask) other_list.add(task_pair); + else battle_list.add(task_pair); + + Task task = new DeAgro(mob); + battle_list.add(Pair.of(1, (Task) task)); + + task = new Retaliate(mob); + other_list.add(Pair.of(1, (Task) task)); + + task = new ChooseAttacks(mob); + battle_list.add(Pair.of(1, (Task) task)); + task = new ManageOutMob(mob); + battle_list.add(Pair.of(1, (Task) task)); + task = new ManagePokemobTarget(mob); + battle_list.add(Pair.of(1, (Task) task)); + + brain.registerActivity(Activities.BATTLE, ImmutableList.copyOf(battle_list), ImmutableSet.of(Pair.of( + MemoryModuleType.VISIBLE_MOBS, MemoryModuleStatus.VALUE_PRESENT))); + + BrainUtils.addToActivity(brain, Activity.CORE, other_list); + BrainUtils.addToActivity(brain, Activity.IDLE, other_list); + BrainUtils.addToActivity(brain, Activities.STATIONARY, other_list); + + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java b/src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java new file mode 100644 index 0000000000..475d58afe1 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java @@ -0,0 +1,45 @@ +package pokecube.adventures.ai.tasks.battle; + +import java.util.Map; + +import com.google.common.collect.Maps; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.world.server.ServerWorld; +import pokecube.adventures.ai.tasks.BaseTask; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.brain.MemoryModules; +import pokecube.core.ai.tasks.TaskBase; + +public abstract class BaseBattleTask extends BaseTask +{ + private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); + + static + { + BaseBattleTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_PRESENT); + } + + protected LivingEntity target; + + public BaseBattleTask(final LivingEntity trainer) + { + super(trainer, BaseBattleTask.MEMS); + } + + public BaseBattleTask(final LivingEntity trainer, final Map, MemoryModuleStatus> mems) + { + super(trainer, TaskBase.merge(BaseBattleTask.MEMS, mems)); + } + + @Override + protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) + { + if (!BrainUtils.hasAttackTarget(this.entity)) return false; + this.target = BrainUtils.getAttackTarget(this.entity); + return true; + } + +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/AICapture.java b/src/main/java/pokecube/adventures/ai/tasks/battle/CaptureMob.java similarity index 53% rename from src/main/java/pokecube/adventures/ai/tasks/AICapture.java rename to src/main/java/pokecube/adventures/ai/tasks/battle/CaptureMob.java index 8f9cd7182c..7031587f9f 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/AICapture.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/CaptureMob.java @@ -1,43 +1,42 @@ -package pokecube.adventures.ai.tasks; +package pokecube.adventures.ai.tasks.battle; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; +import net.minecraft.world.server.ServerWorld; import pokecube.core.PokecubeItems; import pokecube.core.interfaces.IPokecube; import pokecube.core.interfaces.IPokecube.PokecubeBehavior; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; -public class AICapture extends AITrainerBase +public class CaptureMob extends BaseBattleTask { public static int COOLDOWN = 100; - int cooldown = 0; + long lastTry = 0; - public AICapture(final LivingEntity trainer) + public CaptureMob(final LivingEntity trainer, final float chance) { super(trainer); } @Override - public boolean shouldRun() + protected void startExecuting(final ServerWorld worldIn, final LivingEntity entityIn, final long gameTimeIn) { - return this.trainer.getTarget() != null && this.trainer.countPokemon() < this.trainer.getMaxPokemobCount() / 2; - } - - @Override - public void run() - { - this.cooldown--; final IPokemob targ = CapabilityPokemob.getPokemobFor(this.trainer.getTarget()); - if (targ != null && targ.getOwnerId() == null && targ.getHealth() < targ.getMaxHealth() / 4 - && this.cooldown < 0) + if (targ != null && targ.getOwnerId() == null && gameTimeIn - this.lastTry > CaptureMob.COOLDOWN) { - this.cooldown = AICapture.COOLDOWN; + this.lastTry = gameTimeIn; final ItemStack itemStack = new ItemStack(PokecubeItems.getFilledCube(PokecubeBehavior.DEFAULTCUBE), 1); ((IPokecube) itemStack.getItem()).throwPokecubeAt(this.world, this.entity, itemStack, null, this.trainer .getTarget()); } } + @Override + protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) + { + if (!super.shouldExecute(worldIn, owner)) return false; + return this.trainer.countPokemon() < this.trainer.getMaxPokemobCount() / 2; + } } diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/ChooseAttacks.java b/src/main/java/pokecube/adventures/ai/tasks/battle/ChooseAttacks.java new file mode 100644 index 0000000000..7dd301a20c --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/ChooseAttacks.java @@ -0,0 +1,98 @@ +package pokecube.adventures.ai.tasks.battle; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.world.server.ServerWorld; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.Move_Base; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.moves.MovesUtils; +import pokecube.core.utils.PokeType; + +public class ChooseAttacks extends BaseBattleTask +{ + public ChooseAttacks(final LivingEntity trainer) + { + super(trainer); + } + + /** + * @param move + * - the attack to check + * @param user + * - the user of the sttack + * @param target + * - the target of the attack + * @return - the damage that will be dealt by the attack (before reduction + * due to armour) + */ + private int getPower(final String move, final IPokemob user, final Entity target) + { + final Move_Base attack = MovesUtils.getMoveFromName(move); + if (attack == null) return 0; + int pwr = attack.getPWR(user, target); + final IPokemob mob = CapabilityPokemob.getPokemobFor(target); + if (mob != null) pwr *= PokeType.getAttackEfficiency(attack.getType(user), mob.getType1(), mob.getType2()); + return pwr; + } + + /** + * Searches for pokemobs most damaging move against the target, and sets it + * as current attack + */ + private void setMostDamagingMove() + { + final IPokemob outMob = this.trainer.getOutMob(); + int index = outMob.getMoveIndex(); + int max = 0; + final Entity target = BrainUtils.getAttackTarget(outMob.getEntity()); + final String[] moves = outMob.getMoves(); + for (int i = 0; i < 4; i++) + { + final String s = moves[i]; + if (s != null) + { + final int temp = this.getPower(s, outMob, target); + if (temp > max) + { + index = i; + max = temp; + } + } + } + outMob.setMoveIndex(index); + } + + private void considerSwapMove() + { + // TODO choose between damaging/stats/status moves + this.setMostDamagingMove(); + } + + @Override + protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) + { + // If trainer has a living, real mob out, tell it to do stuff. + // Check if pokemob has a valid Pokemob as a target. + if (CapabilityPokemob.getPokemobFor(this.target) != null) + // using best move for target. + this.considerSwapMove(); + // Otherwise just pick whatever does most damage + else this.setMostDamagingMove(); + } + + @Override + protected boolean shouldContinueExecuting(final ServerWorld worldIn, final LivingEntity entityIn, + final long gameTimeIn) + { + return this.trainer.getOutMob() != null; + } + + @Override + protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) + { + if (!super.shouldExecute(worldIn, owner)) return false; + return this.trainer.getOutMob() != null; + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java b/src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java new file mode 100644 index 0000000000..c4d4ef1af3 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java @@ -0,0 +1,135 @@ +package pokecube.adventures.ai.tasks.battle; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.world.server.ServerWorld; +import pokecube.adventures.Config; +import pokecube.adventures.capabilities.CapabilityNPCAIStates.IHasNPCAIStates; +import pokecube.adventures.capabilities.utils.MessageState; +import pokecube.core.database.Database; +import pokecube.core.database.PokedexEntry; +import pokecube.core.handlers.events.PCEventsHandler; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.items.pokecubes.PokecubeManager; + +public class ManageOutMob extends BaseBattleTask +{ + public ManageOutMob(final LivingEntity trainer) + { + super(trainer); + } + + void doAggression() + { + // Check if maybe mob was sent out, but just not seen + final List mobs = PCEventsHandler.getOutMobs(this.entity, false); + if (!mobs.isEmpty()) + { + boolean found = false; + for (final Entity mob : mobs) + // Ones not added to chunk are in pokecubes, so wait for them to + // exit. + if (mob.isAddedToWorld()) + { + final IPokemob pokemob = CapabilityPokemob.getPokemobFor(mob); + if (pokemob != null && !found) + { + this.trainer.setOutMob(pokemob); + found = true; + } + } + return; + } + if (this.aiTracker.getAIState(IHasNPCAIStates.THROWING)) return; + + final int cooldown = this.trainer.getTarget() instanceof PlayerEntity ? this.trainer.getAttackCooldown() : 0; + + // If no mob was found, then it means trainer was not throwing cubes, as + // those are counted along with active pokemobs. + this.aiTracker.setAIState(IHasNPCAIStates.THROWING, false); + // If the trainer is on attack cooldown, then check if to send message + // about next pokemob, or to return early. + if (cooldown > 0) + { + // If no next pokemob, reset trainer and return early. + if (this.trainer.getNextPokemob().isEmpty()) + { + this.aiTracker.setAIState(IHasNPCAIStates.INBATTLE, false); + this.trainer.onLose(this.trainer.getTarget()); + return; + } + // If cooldown is at specific number, send the message for sending + // out next pokemob. + if (cooldown == Config.instance.trainerSendOutDelay / 2) + { + final ItemStack nextStack = this.trainer.getNextPokemob(); + if (!nextStack.isEmpty()) + { + IPokemob next = PokecubeManager.itemToPokemob(nextStack, this.world); + if (next != null) + { + // check if our mob should evolve, if so, do so + while (next.canEvolve(next.getHeldItem())) + { + next = next.evolve(false, false); + nextStack.setTag(PokecubeManager.pokemobToItem(next).getTag()); + } + this.messages.sendMessage(MessageState.ABOUTSEND, this.trainer.getTarget(), this.entity + .getDisplayName(), next.getDisplayName(), this.trainer.getTarget().getDisplayName()); + this.messages.doAction(MessageState.ABOUTSEND, this.trainer.getTarget(), this.entity); + } + } + } + return; + } + // Send next cube at the target. + this.trainer.throwCubeAt(this.trainer.getTarget()); + } + + private boolean considerSwapPokemob() + { + // TODO check if the target pokemob is bad matchup, consider swapping to + // better choice. + + // check if can mega evolve + final IPokemob out = this.trainer.getOutMob(); + if (this.trainer.canMegaEvolve() && out != null && out.getPokedexEntry().hasMegaForm) + { + final List formes = Database.getFormes(out.getPokedexEntry()); + if (!formes.isEmpty()) + { + final int start = this.entity.getRNG().nextInt(formes.size()); + for (int i = 0; i < formes.size(); i++) + { + final PokedexEntry mega = formes.get((i + start) % formes.size()); + if (mega.isMega) + { + out.megaEvolve(mega); + break; + } + } + } + } + return false; + } + + @Override + protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) + { + final boolean hasMob = this.trainer.getOutMob() != null; + if (hasMob) this.considerSwapPokemob(); + else this.doAggression(); + } + + @Override + protected boolean shouldContinueExecuting(final ServerWorld worldIn, final LivingEntity entityIn, + final long gameTimeIn) + { + return super.shouldExecute(worldIn, entityIn); + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java new file mode 100644 index 0000000000..3697d86dd9 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java @@ -0,0 +1,55 @@ +package pokecube.adventures.ai.tasks.battle; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.world.server.ServerWorld; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.interfaces.pokemob.ai.CombatStates; +import pokecube.core.utils.PokemobTracker; + +public class ManagePokemobTarget extends BaseBattleTask +{ + + public ManagePokemobTarget(final LivingEntity trainer) + { + super(trainer); + } + + @Override + protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) + { + final IPokemob mob = this.trainer.getOutMob(); + if (mob == null || this.target == null) return; + final LivingEntity mobTarget = BrainUtils.getAttackTarget(mob.getEntity()); + LivingEntity newTarget = this.target; + final IPokemob target = CapabilityPokemob.getPokemobFor(mobTarget); + // Try to send our mob after the target's nearest mob instead. + if (target == null) + { + final List alternates = PokemobTracker.getMobs(this.target, e -> e.getDistanceSq(this.entity) < 64 + && CapabilityPokemob.getPokemobFor(e) != null); + if (!alternates.isEmpty()) newTarget = (LivingEntity) alternates.get(0); + } + if (!mob.getCombatState(CombatStates.ANGRY)) mob.setCombatState(CombatStates.ANGRY, true); + // check if pokemob's target is same as trainers. + if (mobTarget != newTarget && newTarget != null) BrainUtils.initiateCombat(mob.getEntity(), newTarget); + } + + @Override + protected boolean shouldContinueExecuting(final ServerWorld worldIn, final LivingEntity entityIn, + final long gameTimeIn) + { + return super.shouldExecute(worldIn, entityIn); + } + + @Override + protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) + { + if (!super.shouldExecute(worldIn, owner)) return false; + return this.trainer.getOutMob() != null; + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java new file mode 100644 index 0000000000..2d9ff1f5de --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java @@ -0,0 +1,56 @@ +package pokecube.adventures.ai.tasks.battle.agro; + +import java.util.Map; +import java.util.function.Predicate; + +import com.google.common.collect.Maps; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.util.EntityPredicates; +import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.utils.TrainerTracker; +import pokecube.core.ai.brain.MemoryModules; +import thut.api.maths.Vector3; + +public class AgroTargets extends BaseAgroTask +{ + private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); + + static + { + AgroTargets.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_ABSENT); + } + + // Predicated to return true for invalid targets + final Predicate validTargets; + + // This is whether the ai should run for the current task holder + private Predicate shouldRun = e -> true; + + public AgroTargets(final LivingEntity trainer, final float agressionProbability, final int battleTime, + final Predicate validTargets) + { + super(trainer, agressionProbability, battleTime); + this.validTargets = validTargets; + } + + public AgroTargets setRunCondition(final Predicate shouldRun) + { + this.shouldRun = shouldRun; + return this; + } + + @Override + public boolean isValidTarget(final LivingEntity target) + { + if (!this.shouldRun.test(this.entity)) return false; + if (!EntityPredicates.CAN_AI_TARGET.test(target)) return false; + if (!this.trainer.canBattle(target, false).test()) return false; + final int dist = PokecubeAdv.config.trainer_crowding_radius; + final int num = PokecubeAdv.config.trainer_crowding_number; + if (TrainerTracker.countTrainers(this.world, Vector3.getNewVector().set(this.entity), dist) > num) return false; + return this.validTargets.test(target); + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java new file mode 100644 index 0000000000..b1c3c61a63 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java @@ -0,0 +1,121 @@ +package pokecube.adventures.ai.tasks.battle.agro; + +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +import com.google.common.collect.Maps; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.BrainUtil; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.server.ServerWorld; +import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.ai.tasks.BaseTask; +import pokecube.adventures.capabilities.CapabilityHasPokemobs.ITargetWatcher; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.brain.MemoryModules; +import thut.api.IOwnable; +import thut.api.OwnableCaps; + +public abstract class BaseAgroTask extends BaseTask implements ITargetWatcher +{ + private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); + + static + { + BaseAgroTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_ABSENT); + } + + private int timer = 0; + + private final int maxTimer; + + private final float chance; + + LivingEntity target = null; + + public BaseAgroTask(final LivingEntity trainer, final float agressionProbability, final int battleTime) + { + super(trainer, BaseAgroTask.MEMS); + this.trainer.addTargetWatcher(this); + this.maxTimer = battleTime; + this.chance = agressionProbability; + } + + @Override + protected boolean shouldContinueExecuting(final ServerWorld worldIn, final LivingEntity entityIn, + final long gameTimeIn) + { + if (!BrainUtils.hasAttackTarget(this.entity)) return false; + if (BrainUtils.getAttackTarget(this.entity) != this.target) + { + this.timer = 0; + this.target = BrainUtils.getAttackTarget(this.entity); + } + return this.maxTimer <= 0 || this.timer++ < this.maxTimer; + } + + @Override + protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) + { + this.timer++; + } + + @Override + protected void startExecuting(final ServerWorld worldIn, final LivingEntity entityIn, final long gameTimeIn) + { + if (this.trainer.getCooldown() > gameTimeIn) return; + if (worldIn.getRandom().nextDouble() > this.chance) return; + final List mobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); + + // Count tame mobs as their owners, rather than seperately mobs + final Predicate tameChecker = mob -> + { + final IOwnable owned = OwnableCaps.getOwnable(mob); + LivingEntity owner; + if (owned != null && (owner = owned.getOwner(worldIn)) != null) return this.isValidTarget(owner); + return true; + }; + final double s = this.trainer.getAgressDistance(); + final Vec3d start = entityIn.getEyePosition(1); + final Vec3d end = start.add(entityIn.getLook(1).mul(s, s, s)); + + for (LivingEntity mob : mobs) + if (this.isValidTarget(mob) && tameChecker.test(mob)) + { + final boolean lookingAt = mob.getBoundingBox().rayTrace(start, end).isPresent(); + if (!lookingAt) + { + BrainUtil.lookAt(this.entity, mob); + return; + } + final IOwnable owned = OwnableCaps.getOwnable(mob); + LivingEntity owner; + // Agro the owner of the mob, instead of the mob itself in this + // case. + if (owned != null && (owner = owned.getOwner(worldIn)) != null) mob = owner; + this.timer = 0; + this.target = mob; + this.trainer.onSetTarget(mob); + return; + } + } + + @Override + protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) + { + if (BrainUtils.hasAttackTarget(this.entity)) return false; + if (owner.ticksExisted % PokecubeAdv.config.trainerAgroRate != 0) return false; + return this.entity.getBrain().hasMemory(MemoryModuleType.VISIBLE_MOBS); + } + + @Override + protected void resetTask(final ServerWorld worldIn, final LivingEntity entityIn, final long gameTimeIn) + { + this.timer = 0; + this.target = null; + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java new file mode 100644 index 0000000000..d359a15aa3 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java @@ -0,0 +1,129 @@ +package pokecube.adventures.ai.tasks.battle.agro; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.Brain; +import net.minecraft.entity.ai.brain.BrainUtil; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.world.server.ServerWorld; +import pokecube.adventures.Config; +import pokecube.adventures.ai.tasks.battle.BaseBattleTask; +import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; +import pokecube.adventures.capabilities.TrainerCaps; +import pokecube.core.PokecubeCore; +import pokecube.core.handlers.events.PCEventsHandler; +import pokecube.core.interfaces.IPokemob; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; + +public class DeAgro extends BaseBattleTask +{ + int deagroTimer = 0; + int noSeeTicks = 0; + + public DeAgro(final LivingEntity trainer) + { + super(trainer); + } + + @Override + protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) + { + boolean deagro = false; + + boolean won = false; + + // Check if trainer has any pokemobs, if not, cancel agression, no + // reward. + if (this.trainer.getPokemob(0).isEmpty()) deagro = true; + + if (!deagro) + { + final double distance = this.entity.getDistanceSq(this.target); + if (distance > PokecubeCore.getConfig().chaseDistance * PokecubeCore.getConfig().chaseDistance) + deagro = true; + } + + if (!deagro && !BrainUtil.canSee(this.entity.getBrain(), this.target)) + { + final boolean timeout = this.noSeeTicks++ > Config.instance.trainerDeAgressTicks; + if (timeout) deagro = true; + else this.noSeeTicks = 0; + } + + final IHasPokemobs other = TrainerCaps.getHasPokemobs(this.target); + + final Brain brain = this.entity.getBrain(); + final LivingEntity lastHitBy = brain.hasMemory(MemoryModuleType.HURT_BY_ENTITY) ? brain.getMemory( + MemoryModuleType.HURT_BY_ENTITY).get() : null; + boolean hitUs = lastHitBy == this.target; + + hitUs = hitUs && this.entity.ticksExisted - this.entity.getLastAttackedEntityTime() > 20; + + if (!deagro && !hitUs && other != null && other.getNextPokemob().isEmpty()) + { + won = true; + if (other.getOutID() != null) + { + final IPokemob outMob = other.getOutMob(); + if (outMob != null && !outMob.getEntity().isAlive()) + { + other.setOutID(null); + other.setOutMob(null); + } + } + if (other.getOutID() == null) + { + final List mobs = PCEventsHandler.getOutMobs(this.target, false); + if (!mobs.isEmpty()) + { + boolean found = false; + for (final Entity mob : mobs) + if (mob.addedToChunk && mob.getDistanceSq(this.target) < 32 * 32) + { + final IPokemob pokemob = CapabilityPokemob.getPokemobFor(mob); + if (pokemob != null && !found) + { + other.setOutMob(pokemob); + found = true; + break; + } + } + if (found) this.deagroTimer = 20; + } + if (this.deagroTimer-- < 0) + { + System.out.println("Timeout"); + deagro = true; + } + } + } + + if (deagro) + { + if (won) + { + this.trainer.onWin(this.target); + if (other.getTarget() == this.entity) other.onLose(this.entity); + } + System.out.println("Deagroing"); + this.trainer.deAgro(this.trainer, TrainerCaps.getHasPokemobs(this.target)); + } + } + + @Override + protected boolean shouldContinueExecuting(final ServerWorld worldIn, final LivingEntity entityIn, + final long gameTimeIn) + { + return this.shouldExecute(worldIn, entityIn); + } + + @Override + protected void startExecuting(final ServerWorld worldIn, final LivingEntity entityIn, final long gameTimeIn) + { + this.deagroTimer = 20; + this.noSeeTicks = 0; + } + +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/Retaliate.java b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/Retaliate.java new file mode 100644 index 0000000000..189cc83acd --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/Retaliate.java @@ -0,0 +1,49 @@ +package pokecube.adventures.ai.tasks.battle.agro; + +import java.util.Map; + +import com.google.common.collect.Maps; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.Brain; +import net.minecraft.entity.ai.brain.BrainUtil; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.util.EntityPredicates; +import pokecube.core.ai.brain.MemoryModules; + +public class Retaliate extends BaseAgroTask +{ + private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); + + static + { + Retaliate.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_ABSENT); + } + + public Retaliate(final LivingEntity trainer) + { + super(trainer, 1, -1); + this.trainer.addTargetWatcher(this); + } + + @Override + public boolean ignoreHasBattled(final LivingEntity target) + { + final Brain brain = this.entity.getBrain(); + if (!brain.hasMemory(MemoryModuleType.HURT_BY_ENTITY)) return false; + return brain.getMemory(MemoryModuleType.HURT_BY_ENTITY).get() == target; + } + + @Override + public boolean isValidTarget(final LivingEntity target) + { + if (target == null) return false; + final Brain brain = this.entity.getBrain(); + if (!brain.hasMemory(MemoryModuleType.HURT_BY_ENTITY)) return false; + if (!(target.isAlive() && BrainUtil.canSee(brain, target))) return false; + if (!EntityPredicates.CAN_AI_TARGET.test(target)) return false; + return brain.getMemory(MemoryModuleType.HURT_BY_ENTITY).get() == target; + } + +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/idle/Mate.java b/src/main/java/pokecube/adventures/ai/tasks/idle/Mate.java new file mode 100644 index 0000000000..3adc09c28c --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/tasks/idle/Mate.java @@ -0,0 +1,19 @@ +package pokecube.adventures.ai.tasks.idle; + +import java.util.Map; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import pokecube.adventures.ai.tasks.BaseTask; + +public class Mate extends BaseTask +{ + + public Mate(final LivingEntity trainer, final Map, MemoryModuleStatus> requiredMemoryStateIn) + { + super(trainer, requiredMemoryStateIn); + // TODO Auto-generated constructor stub + } + +} diff --git a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java index 4fef737b0a..8500f5d021 100644 --- a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java @@ -10,6 +10,8 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.MobEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.ItemStack; @@ -34,10 +36,13 @@ import pokecube.adventures.entity.trainer.TrainerBase; import pokecube.adventures.network.PacketTrainer; import pokecube.core.PokecubeCore; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.npc.Activities; import pokecube.core.handlers.events.EventsHandler; import pokecube.core.interfaces.IPokecube; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.items.pokecubes.EntityPokecubeBase; import pokecube.core.items.pokecubes.PokecubeManager; import thut.api.maths.Vector3; import thut.api.world.mobs.data.DataSync; @@ -173,16 +178,17 @@ public ListNBT save() private int nextSlot; // Cooldown between sending out pokemobs private int attackCooldown = 0; + // Cooldown between agression - private long cooldown = 0; - private int sight = -1; - private TypeTrainer type; - protected LivingEntity target; - private UUID outID; - private boolean canMegaEvolve = false; - private IPokemob outMob; - private LevelMode levelmode = LevelMode.CONFIG; - private final Set watchers = Sets.newHashSet(); + private long cooldown = 0; + private int sight = -1; + private TypeTrainer type; + private UUID outID; + private boolean canMegaEvolve = false; + private IPokemob outMob; + private LevelMode levelmode = LevelMode.CONFIG; + + private final Set watchers = Sets.newHashSet(); public final DataParamHolder holder = new DataParamHolder(); private DataSync datasync; @@ -199,20 +205,30 @@ public void addTargetWatcher(final ITargetWatcher watcher) } @Override - public boolean canBattle(final LivingEntity target, final boolean checkWatcher) + public AllowedBattle canBattle(final LivingEntity target, final boolean checkWatcher) { + boolean ignoreBattled = false; + if (checkWatcher && target != null) for (final ITargetWatcher w : this.watchers) + ignoreBattled = ignoreBattled || w.ignoreHasBattled(target); + + // No battling if we have defeated or been defeated + if (!ignoreBattled) if (this.defeatedBy(target) || this.defeated(target)) return AllowedBattle.NOTNOW; + final IHasPokemobs trainer = TrainerCaps.getHasPokemobs(target); // No battling a target already battling something - if (trainer != null && trainer.getTarget() != null && trainer.getTarget() != target) return false; - // No battling if we have defeated or been defeated - if (this.defeatedBy(target) || this.defeated(target)) return false; + if (trainer != null) + { + if (trainer.getTarget() != null && trainer.getTarget() != this.getTrainer()) + return AllowedBattle.NOTNOW; + if (trainer.getTarget() == this.getTrainer()) return AllowedBattle.NOTNOW; + } // Not checking watchers, return true - if (!checkWatcher) return true; + if (!checkWatcher) return AllowedBattle.YES; // Valid if any watchers say so for (final ITargetWatcher w : this.watchers) - if (w.isValidTarget(target)) return true; + if (w.isValidTarget(target)) return AllowedBattle.YES; // Otherwise false. - return false; + return AllowedBattle.NO; } @Override @@ -355,7 +371,7 @@ public ItemStack getPokemob(final int slot) @Override public LivingEntity getTarget() { - return this.target; + return BrainUtils.getAttackTarget(this.getTrainer()); } @Override @@ -425,7 +441,7 @@ public void lowerCooldowns() else if (this.getOutMob() == null && !this.aiStates.getAIState(IHasNPCAIStates.THROWING)) this .setAttackCooldown(this.getAttackCooldown() - 1); if (this.aiStates.getAIState(IHasNPCAIStates.INBATTLE)) return; - if (!done && this.getTarget() != null) this.setTarget(null); + if (!done && this.getTarget() != null) this.onSetTarget(null); } @Override @@ -447,11 +463,7 @@ public void onWin(final Entity lost) { // Only store for players if (lost instanceof PlayerEntity) this.defeated.validate(lost); - if (lost == this.getTarget()) - { - this.setTarget(null); - this.resetPokemob(); - } + if (lost == this.getTarget()) this.onSetTarget(null); } @Override @@ -468,14 +480,12 @@ public void onLose(final Entity won) if (defeatingTrainer != null) { defeatingTrainer.onWin(this.user); - defeatingTrainer.setTarget(null); - defeatingTrainer.resetPokemob(); + defeatingTrainer.onSetTarget(null); } // Get this cleanup stuff done first. - this.setCooldown(this.user.getEntityWorld().getGameTime() + 10); - this.setTarget(null); - this.resetPokemob(); + this.setCooldown(this.user.getEntityWorld().getGameTime() + 100); + this.onSetTarget(null); // Then parse if rewards and actions should be dealt with. final boolean reward = !(this.defeatedBy(won) || !this.user.isAlive() || this.user.getHealth() <= 0); @@ -527,11 +537,8 @@ public void resetPokemob() this.setNextSlot(0); this.aiStates.setAIState(IHasNPCAIStates.THROWING, false); this.aiStates.setAIState(IHasNPCAIStates.INBATTLE, false); - if (this.getOutID() != null) - { - EventsHandler.recallAllPokemobs(this.user); - this.setOutMob(null); - } + EventsHandler.recallAllPokemobs(this.user); + this.setOutMob(null); } @Override @@ -626,25 +633,35 @@ public void setPokemob(final int slot, final ItemStack cube) } @Override - public void setTarget(final LivingEntity target) + public void onSetTarget(final LivingEntity target) { + final LivingEntity old = this.getTarget(); + if (old == target) return; + + if (target != null && !this.canBattle(target, true).test()) return; + final Set watchers = this.getTargetWatchers(); // No next pokemob, so we shouldn't have a target in this case. + if (target != null && this.getPokemob(0).isEmpty()) { - this.target = null; // Notify the watchers that a target was actually set. for (final ITargetWatcher watcher : watchers) watcher.onSet(null); this.aiStates.setAIState(IHasNPCAIStates.THROWING, false); this.aiStates.setAIState(IHasNPCAIStates.INBATTLE, false); + BrainUtils.deagro(this.getTrainer()); return; } - if (target != null && target != this.target && this.attackCooldown <= 0) + if (target != null && this.getAttackCooldown() <= 0) { - this.attackCooldown = Config.instance.trainerBattleDelay; + int cooldown = Config.instance.trainerBattleDelay; + final LivingEntity hitBy = this.user.getBrain().hasMemory(MemoryModuleType.HURT_BY_ENTITY) ? this.user + .getBrain().getMemory(MemoryModuleType.HURT_BY_ENTITY).get() : null; + final int hurtTimer = this.user.ticksExisted - this.user.getLastAttackedEntityTime(); // No cooldown if someone was punching is! - if (target == this.user.getAttackingEntity()) this.attackCooldown = 0; + if (hitBy == target && hurtTimer < 500) cooldown = 0; + this.setAttackCooldown(cooldown); this.messages.sendMessage(MessageState.AGRESS, target, this.user.getDisplayName(), target .getDisplayName()); this.messages.doAction(MessageState.AGRESS, target, this.user); @@ -652,19 +669,29 @@ public void setTarget(final LivingEntity target) } if (target == null) { - if (this.target != null && this.aiStates.getAIState(IHasNPCAIStates.INBATTLE)) + if (old != null && this.aiStates.getAIState(IHasNPCAIStates.INBATTLE)) { - this.messages.sendMessage(MessageState.DEAGRESS, this.target, this.user.getDisplayName(), - this.target.getDisplayName()); + this.messages.sendMessage(MessageState.DEAGRESS, old, this.user.getDisplayName(), old + .getDisplayName()); this.messages.doAction(MessageState.DEAGRESS, target, this.user); } this.aiStates.setAIState(IHasNPCAIStates.THROWING, false); this.aiStates.setAIState(IHasNPCAIStates.INBATTLE, false); } - this.target = target; // Notify the watchers that a target was actually set. for (final ITargetWatcher watcher : watchers) watcher.onSet(target); + + if (target == null) + { + BrainUtils.deagro(this.getTrainer()); + this.resetPokemob(); + } + else if (this.getTrainer() instanceof MobEntity) + { + BrainUtils.initiateCombat((MobEntity) this.getTrainer(), target); + this.getTrainer().getBrain().switchTo(Activities.BATTLE); + } } @Override @@ -689,13 +716,19 @@ public void throwCubeAt(final Entity target) final Vector3 t = Vector3.getNewVector().set(target); t.set(t.subtractFrom(here).scalarMultBy(0.5).addTo(here)); PokecubeManager.heal(i, target.getEntityWorld()); - cube.throwPokecubeAt(this.user.getEntityWorld(), this.user, i, t, null); - this.aiStates.setAIState(IHasNPCAIStates.THROWING, true); - this.attackCooldown = Config.instance.trainerSendOutDelay; - this.messages.sendMessage(MessageState.SENDOUT, target, this.user.getDisplayName(), i.getDisplayName(), - target.getDisplayName()); - if (target instanceof LivingEntity) this.messages.doAction(MessageState.SENDOUT, (LivingEntity) target, - this.user); + final EntityPokecubeBase thrown = cube.throwPokecubeAt(this.user.getEntityWorld(), this.user, i, t, + null); + if (thrown != null) + { + thrown.autoRelease = 20; + thrown.canBePickedUp = false; + this.aiStates.setAIState(IHasNPCAIStates.THROWING, true); + this.attackCooldown = Config.instance.trainerSendOutDelay; + this.messages.sendMessage(MessageState.SENDOUT, target, this.user.getDisplayName(), i + .getDisplayName(), target.getDisplayName()); + if (target instanceof LivingEntity) this.messages.doAction(MessageState.SENDOUT, + (LivingEntity) target, this.user); + } this.nextSlot++; if (this.nextSlot >= this.getMaxPokemobCount() || this.getNextPokemob() == null) this.nextSlot = -1; return; @@ -718,7 +751,7 @@ public LivingEntity getTrainer() @Override public LivingEntity getTargetRaw() { - return this.target; + return BrainUtils.getAttackTarget(this.getTrainer()); } @Override @@ -744,6 +777,16 @@ public static enum LevelMode CONFIG, YES, NO; } + public static enum AllowedBattle + { + YES, NOTNOW, NO; + + public boolean test() + { + return this == YES; + } + } + LivingEntity getTrainer(); /** Adds the pokemob back into the inventory, healing it as needed. */ @@ -814,13 +857,13 @@ default void addTargetWatcher(final ITargetWatcher watcher) } /** If we are agressive, is this a valid target? */ - default boolean canBattle(final LivingEntity target) + default AllowedBattle canBattle(final LivingEntity target) { return this.canBattle(target, false); } /** If we are agressive, is this a valid target? */ - boolean canBattle(final LivingEntity target, final boolean checkWatchers); + AllowedBattle canBattle(final LivingEntity target, final boolean checkWatchers); default boolean canLevel() { @@ -964,7 +1007,7 @@ default void removeTargetWatcher(final ITargetWatcher watcher) void setPokemob(int slot, ItemStack cube); - void setTarget(LivingEntity target); + void onSetTarget(LivingEntity target); void setType(TypeTrainer type); @@ -983,11 +1026,13 @@ default void deAgro(final IHasPokemobs us, final IHasPokemobs them) { us.getTrainer().setRevengeTarget(null); us.getTrainer().setLastAttackedEntity(null); + us.onSetTarget(null); } if (them != null) { them.getTrainer().setRevengeTarget(null); them.getTrainer().setLastAttackedEntity(null); + them.onSetTarget(null); } } } @@ -1004,6 +1049,11 @@ default void onRemoved(final IHasPokemobs pokemobs) boolean isValidTarget(LivingEntity target); + default boolean ignoreHasBattled(final LivingEntity target) + { + return false; + } + default void onSet(final LivingEntity target) { diff --git a/src/main/java/pokecube/adventures/capabilities/CapabilityNPCMessages.java b/src/main/java/pokecube/adventures/capabilities/CapabilityNPCMessages.java index d77dddc7ff..75bdd2978c 100644 --- a/src/main/java/pokecube/adventures/capabilities/CapabilityNPCMessages.java +++ b/src/main/java/pokecube/adventures/capabilities/CapabilityNPCMessages.java @@ -37,7 +37,8 @@ public DefaultMessager() this.messages.put(MessageState.DEFEAT, "pokecube.trainer.defeat"); this.messages.put(MessageState.DEAGRESS, "pokecube.trainer.forget"); this.messages.put(MessageState.GIVEITEM, "pokecube.trainer.drop"); - this.messages.put(MessageState.INTERACT_YESBATTLE, "pokecube.trainer.agress"); + this.messages.put(MessageState.INTERACT_YESBATTLE, "pokecube.trainer.agress_allowed"); + this.messages.put(MessageState.INTERACT_NOBATTLE, "pokecube.trainer.agress_request_denied"); this.actions.put(MessageState.INTERACT_YESBATTLE, new BattleAction()); } diff --git a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java index 910ec00889..fc8f24a41c 100644 --- a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java @@ -46,6 +46,7 @@ public static void register(final AttachCapabilitiesEvent event) } PlayerEntity player; + LivingEntity target = null; public PlayerPokemobs(final PlayerEntity player) { @@ -67,9 +68,9 @@ public boolean addPokemob(final ItemStack mob) } @Override - public boolean canBattle(final LivingEntity target) + public AllowedBattle canBattle(final LivingEntity target) { - return true; + return AllowedBattle.YES; } @Override @@ -119,11 +120,11 @@ public void deserializeNBT(final CompoundNBT nbt) } @Override - public void setTarget(LivingEntity target) + public void onSetTarget(LivingEntity target) { final IHasPokemobs oldBattle = TrainerCaps.getHasPokemobs(this.target); if (target != null && oldBattle != null && oldBattle.getTargetRaw() == this.player && oldBattle.canBattle( - this.player)) return; + this.player).test()) return; final IHasPokemobs targetmobs = TrainerCaps.getHasPokemobs(target); if (targetmobs == null && target != null || target == this.player) target = null; final Set watchers = this.getTargetWatchers(); @@ -146,6 +147,6 @@ public LivingEntity getTarget() public void resetPokemob() { // We do nothing here either. - this.setTarget(null); + this.onSetTarget(null); } } diff --git a/src/main/java/pokecube/adventures/capabilities/utils/BattleAction.java b/src/main/java/pokecube/adventures/capabilities/utils/BattleAction.java index 5440b657f5..9143244eb9 100644 --- a/src/main/java/pokecube/adventures/capabilities/utils/BattleAction.java +++ b/src/main/java/pokecube/adventures/capabilities/utils/BattleAction.java @@ -21,7 +21,7 @@ public void doAction(final PlayerEntity target, final Entity holder) if (trainer != null && target instanceof ServerPlayerEntity) { trainer.resetPokemob(); - trainer.setTarget(target); + trainer.onSetTarget(target); } } diff --git a/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java b/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java index 48f4e3a3c2..b6b2ced55d 100644 --- a/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java +++ b/src/main/java/pokecube/adventures/capabilities/utils/TypeTrainer.java @@ -11,6 +11,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.mojang.datafixers.util.Pair; import net.minecraft.client.Minecraft; import net.minecraft.entity.INPC; @@ -18,6 +19,7 @@ import net.minecraft.entity.MobEntity; import net.minecraft.entity.ai.brain.schedule.Activity; import net.minecraft.entity.ai.brain.schedule.Schedule; +import net.minecraft.entity.ai.brain.task.Task; import net.minecraft.entity.merchant.villager.VillagerEntity; import net.minecraft.entity.monster.ZombieEntity; import net.minecraft.entity.player.PlayerEntity; @@ -33,11 +35,9 @@ import net.minecraftforge.api.distmarker.OnlyIn; import pokecube.adventures.Config; import pokecube.adventures.PokecubeAdv; -import pokecube.adventures.ai.tasks.AIBattle; -import pokecube.adventures.ai.tasks.AICapture; -import pokecube.adventures.ai.tasks.AIMate; -import pokecube.adventures.ai.tasks.AIRetaliate; -import pokecube.adventures.ai.tasks.AITrainerAgro; +import pokecube.adventures.ai.tasks.Tasks; +import pokecube.adventures.ai.tasks.battle.CaptureMob; +import pokecube.adventures.ai.tasks.battle.agro.AgroTargets; import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; import pokecube.adventures.capabilities.TrainerCaps; import pokecube.adventures.entity.trainer.TrainerBase; @@ -52,7 +52,6 @@ import pokecube.core.database.SpawnBiomeMatcher; import pokecube.core.entity.npc.NpcMob; import pokecube.core.entity.npc.NpcType; -import pokecube.core.entity.pokemobs.EntityPokemob; import pokecube.core.events.pokemob.SpawnEvent.Variance; import pokecube.core.handlers.events.SpawnHandler; import pokecube.core.interfaces.IPokecube.PokecubeBehavior; @@ -61,9 +60,8 @@ import pokecube.core.items.pokecubes.PokecubeManager; import pokecube.core.utils.PokeType; import pokecube.core.utils.Tools; -import thut.api.entity.ai.GoalsWrapper; -import thut.api.entity.ai.IAIRunnable; +@SuppressWarnings("unchecked") public class TypeTrainer extends NpcType { @@ -81,7 +79,7 @@ public static interface ITypeMapper public static interface AIAdder { - void process(MobEntity mob); + List>> process(MobEntity mob); } private static final List mappers = Lists.newArrayList(); @@ -99,8 +97,10 @@ public static void registerAIAdder(final AIAdder adder) public static void addAI(final MobEntity mob) { + final List>> tasks = Lists.newArrayList(); for (final AIAdder adder : TypeTrainer.aiAdders) - adder.process(mob); + tasks.addAll(adder.process(mob)); + Tasks.addBattleTasks(mob, tasks); } public static TypeTrainer get(final LivingEntity mob, final boolean forSpawn) @@ -143,15 +143,6 @@ else if (mob instanceof VillagerEntity && Config.instance.npcsAreTrainers) TypeTrainer.registerAIAdder((npc) -> { - final List ais = Lists.newArrayList(); - // All can battle, but only trainers will path during battle. - ais.add(new AIBattle(npc, !(npc instanceof TrainerBase)).setPriority(0)); - - // All attack zombies. - ais.add(new AITrainerAgro(npc, ZombieEntity.class).setPriority(20)); - - // All retaliate - ais.add(new AIRetaliate(npc)); final Predicate noRunWhileRest = e -> { @@ -175,29 +166,46 @@ else if (mob instanceof VillagerEntity && Config.instance.npcsAreTrainers) } return true; }; + final Predicate onlyIfHasMobs = e -> + { + final IHasPokemobs other = TrainerCaps.getHasPokemobs(e); + if (other == null) return true; + final boolean hasMob = !other.getNextPokemob().isEmpty(); + if (hasMob) return true; + return other.getOutID() != null; + }; + + final List>> list = Lists.newArrayList(); + Task task = new AgroTargets(npc, 1, 0, z -> z instanceof ZombieEntity); + list.add(Pair.of(1, (Task) task)); + // Only trainers specifically target players. if (npc instanceof TrainerBase) { - ais.add(new AITrainerAgro(npc, PlayerEntity.class).setRunCondition(noRunWhileRest).setPriority(10)); - ais.add(new AIMate(npc, ((TrainerBase) npc).getClass())); + final Predicate validPlayer = onlyIfHasMobs.and(e -> e instanceof PlayerEntity); + task = new AgroTargets(npc, 1, 0, validPlayer).setRunCondition(noRunWhileRest); + list.add(Pair.of(1, (Task) task)); } // 5% chance of battling a random nearby pokemob if they see it. if (Config.instance.trainersBattlePokemobs) { - ais.add(new AITrainerAgro(npc, 0.05f, EntityPokemob.class).setRunCondition(noRunWhileRest).setPriority( - 20)); - ais.add(new AICapture(npc).setPriority(10)); + task = new AgroTargets(npc, 0.05f, 1200, z -> CapabilityPokemob.getPokemobFor(z) != null) + .setRunCondition(noRunWhileRest); + list.add(Pair.of(1, (Task) task)); + task = new CaptureMob(npc, 1); + list.add(Pair.of(1, (Task) task)); } // 1% chance of battling another of same class if seen // Also this will stop the battle after 1200 ticks. if (Config.instance.trainersBattleEachOther) { final Predicate shouldRun = noRunWhileMeet.and(noRunWhileRest); - ais.add(new AITrainerAgro(npc, 0.001f, 1200, npc.getClass()).setRunCondition(shouldRun).setPriority(20)); + task = new AgroTargets(npc, 0.05f, 1200, z -> z.getClass() == npc.getClass()).setRunCondition( + shouldRun); + list.add(Pair.of(1, (Task) task)); } - - npc.goalSelector.addGoal(0, new GoalsWrapper(npc, ais.toArray(new IAIRunnable[0]))); + return list; }); } diff --git a/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java b/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java index 903dfb9386..5a3d115900 100644 --- a/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java +++ b/src/main/java/pokecube/adventures/entity/trainer/TrainerBase.java @@ -5,7 +5,6 @@ import java.util.OptionalInt; import java.util.Random; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.container.MerchantContainer; @@ -34,7 +33,6 @@ import pokecube.core.handlers.events.EventsHandler; import pokecube.core.handlers.events.SpawnHandler; import pokecube.core.interfaces.IPokemob; -import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.utils.Tools; import thut.api.item.ItemList; import thut.api.maths.Vector3; @@ -101,7 +99,7 @@ else if (ItemList.is(TrainerBase.BRIBE, stack) && this.pokemobsCap.friendlyCoold { stack.split(1); player.setHeldItem(hand, stack); - this.pokemobsCap.setTarget(null); + this.pokemobsCap.onSetTarget(null); for (final IPokemob pokemob : this.currentPokemobs) pokemob.onRecall(false); this.pokemobsCap.friendlyCooldown = 2400; @@ -125,7 +123,7 @@ else if (this.canTrade(player)) else this.setCustomer(null); return true; } - else if (this.pokemobsCap.getCooldown() <= 0 && stack.getItem() == Items.STICK) this.pokemobsCap.setTarget( + else if (this.pokemobsCap.getCooldown() <= 0 && stack.getItem() == Items.STICK) this.pokemobsCap.onSetTarget( player); return false; @@ -169,18 +167,11 @@ public void livingTick() { super.livingTick(); if (!this.isServerWorld()) return; - if (this.pokemobsCap.getOutID() != null && this.pokemobsCap.getOutMob() == null) - { - final Entity mob = this.getServer().getWorld(this.dimension).getEntityByUuid(this.pokemobsCap.getOutID()); - final IPokemob pokemob = CapabilityPokemob.getPokemobFor(mob); - this.pokemobsCap.setOutMob(pokemob); - if (this.pokemobsCap.getOutMob() == null) this.pokemobsCap.setOutID(null); - } ItemStack cube = this.pokemobsCap.getNextPokemob(); ItemStack reward = this.rewardsCap.getRewards().isEmpty() ? ItemStack.EMPTY : this.rewardsCap.getRewards().get(0).stack; - if (this.pokemobsCap.getCooldown() > 0) + if (this.pokemobsCap.getCooldown() > this.world.getGameTime()) { cube = ItemStack.EMPTY; reward = ItemStack.EMPTY; diff --git a/src/main/java/pokecube/adventures/events/TrainerEventHandler.java b/src/main/java/pokecube/adventures/events/TrainerEventHandler.java index f58d7e1fbe..72b69cc7a4 100644 --- a/src/main/java/pokecube/adventures/events/TrainerEventHandler.java +++ b/src/main/java/pokecube/adventures/events/TrainerEventHandler.java @@ -31,8 +31,10 @@ import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import pokecube.adventures.Config; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.ai.tasks.Tasks; import pokecube.adventures.capabilities.CapabilityHasPokemobs.DefaultPokemobs; import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; +import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs.AllowedBattle; import pokecube.adventures.capabilities.CapabilityHasRewards.DefaultRewards; import pokecube.adventures.capabilities.CapabilityHasRewards.Reward; import pokecube.adventures.capabilities.CapabilityHasTrades.DefaultTrades; @@ -292,7 +294,7 @@ public static void livingHurtEvent(final LivingHurtEvent evt) .getDisplayName(), evt.getSource().getTrueSource().getDisplayName()); messages.doAction(MessageState.HURT, (LivingEntity) evt.getSource().getTrueSource(), evt.getEntity()); } - if (pokemobHolder != null && pokemobHolder.getTarget() == null) pokemobHolder.setTarget((LivingEntity) evt + if (pokemobHolder != null && pokemobHolder.getTarget() == null) pokemobHolder.onSetTarget((LivingEntity) evt .getSource().getTrueSource()); } } @@ -307,9 +309,6 @@ public static void livingHurtEvent(final LivingHurtEvent evt) public static void livingSetTargetEvent(final LivingSetAttackTargetEvent evt) { if (evt.getTarget() == null || !(evt.getEntity() instanceof LivingEntity)) return; - final IHasPokemobs pokemobHolder = TrainerCaps.getHasPokemobs(evt.getTarget()); - if (pokemobHolder != null && pokemobHolder.getTarget() == null) pokemobHolder.setTarget((LivingEntity) evt - .getEntity()); } @SubscribeEvent @@ -334,7 +333,19 @@ public static void onNpcSpawn(final NpcSpawn event) public static void onNpcTick(final LivingUpdateEvent event) { final IHasPokemobs pokemobHolder = TrainerCaps.getHasPokemobs(event.getEntityLiving()); - if (pokemobHolder != null) pokemobHolder.onTick(); + if (pokemobHolder != null) + { + final LivingEntity npc = event.getEntityLiving(); + // Add our task if the dummy not present, this can happen if the + // brain has reset before + if (npc instanceof MobEntity && !npc.getBrain().sensors.containsKey(Tasks.DUMMY) && npc + .getEntityWorld() instanceof ServerWorld) + { + TypeTrainer.addAI((MobEntity) npc); + PokecubeCore.LOGGER.debug("Added Tasks: " + npc); + } + pokemobHolder.onTick(); + } } private static void initTrainer(final LivingEntity npc, final SpawnReason reason) @@ -351,10 +362,6 @@ private static void initTrainer(final LivingEntity npc, final SpawnReason reason .getEntityWorld().getGameTime()) return; npc.getPersistentData().putLong("pokeadv_join", npc.getEntityWorld().getGameTime()); - // Wrap it as a fake vanilla AI - if (npc instanceof MobEntity) TypeTrainer.addAI((MobEntity) npc); - PokecubeCore.LOGGER.debug("Added Tasks: " + npc); - final TypeTrainer newType = TypeTrainer.get(npc, true); if (mobs.countPokemon() != 0) return; if (newType == null) return; @@ -394,8 +401,22 @@ public static void processInteract(final PlayerInteractEvent evt, final Entity t if (messages != null) { MessageState state = MessageState.INTERACT; - if (pokemobs != null) state = pokemobs.canBattle(evt.getPlayer(), true) ? MessageState.INTERACT_YESBATTLE - : MessageState.INTERACT_NOBATTLE; + final AllowedBattle test = pokemobs.canBattle(evt.getPlayer(), true); + switch (test) + { + case NO: + state = MessageState.INTERACT; + break; + case NOTNOW: + state = MessageState.INTERACT_NOBATTLE; + break; + case YES: + state = MessageState.INTERACT_YESBATTLE; + break; + default: + break; + + } messages.sendMessage(state, evt.getPlayer(), target.getDisplayName(), evt.getPlayer().getDisplayName()); messages.doAction(state, evt.getPlayer(), target); } diff --git a/src/main/java/pokecube/core/ai/brain/BrainUtils.java b/src/main/java/pokecube/core/ai/brain/BrainUtils.java index 30978fe54c..5cbc18b5f0 100644 --- a/src/main/java/pokecube/core/ai/brain/BrainUtils.java +++ b/src/main/java/pokecube/core/ai/brain/BrainUtils.java @@ -1,16 +1,23 @@ package pokecube.core.ai.brain; +import java.util.Collection; import java.util.List; import java.util.Optional; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.mojang.datafixers.util.Pair; + import net.minecraft.entity.AgeableEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; import net.minecraft.entity.ai.brain.Brain; import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.schedule.Activity; import net.minecraft.entity.ai.brain.sensor.Sensor; import net.minecraft.entity.ai.brain.sensor.SensorType; +import net.minecraft.entity.ai.brain.task.Task; import net.minecraft.entity.item.ItemEntity; import net.minecraft.util.math.IPosWrapper; import pokecube.core.ai.brain.sensors.NearBlocks.NearBlock; @@ -175,6 +182,23 @@ public static void addToBrain(final Brain brain, final List brain, final Activity act, + final Collection>> tasks) + { + tasks.forEach((pair) -> + { + final Integer prior = pair.getFirst(); + final Task task = pair.getSecond(); + brain.field_218232_c.computeIfAbsent(prior, (val) -> + { + return Maps.newHashMap(); + }).computeIfAbsent(act, (tmp) -> + { + return Sets.newLinkedHashSet(); + }).add(task); + }); + } + public static void initiateCombat(final MobEntity mob, final LivingEntity target) { // No target self diff --git a/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java b/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java index 4f1e67d17e..e7165896c7 100644 --- a/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java +++ b/src/main/java/pokecube/core/ai/logic/LogicMiscUpdate.java @@ -130,6 +130,7 @@ else if (!angry && this.reset) this.pokemob.getModifiers().outOfCombatReset(); this.pokemob.getMoveStats().reset(); } + this.pokemob.setCombatState(CombatStates.NOITEMUSE, false); } else /** Angry pokemobs shouldn't decide to walk around. */ this.pokemob.setRoutineState(AIRoutine.AIRBORNE, true); @@ -274,10 +275,10 @@ public void tick(final World world) // Everything below here is client side only! - if (id >= 0 && targ == null) BrainUtils.setAttackTarget(this.entity, (LivingEntity) PokecubeCore - .getEntityProvider().getEntity(world, id, false)); - if (id < 0 && targ != null) BrainUtils.setAttackTarget(this.entity, null); - if (targ != null && !targ.isAlive()) BrainUtils.setAttackTarget(this.entity, null); + if (id >= 0 && targ == null) this.entity.setAttackTarget((LivingEntity) PokecubeCore.getEntityProvider() + .getEntity(world, id, false)); + if (id < 0 && targ != null) this.entity.setAttackTarget(null); + if (targ != null && !targ.isAlive()) this.entity.setAttackTarget(null); // Sync the addition of this, as onAddedToWorld is called before this // value is synchronized diff --git a/src/main/java/pokecube/core/ai/npc/Schedules.java b/src/main/java/pokecube/core/ai/npc/Schedules.java index 6d49c7e1b0..6e7e055d3d 100644 --- a/src/main/java/pokecube/core/ai/npc/Schedules.java +++ b/src/main/java/pokecube/core/ai/npc/Schedules.java @@ -25,7 +25,6 @@ private static Schedule makeAdult() //@formatter:off .add(10, Activity.IDLE) .add(10, Activities.STATIONARY) - .add(10, Activities.BATTLE) .add(2000,Activity.WORK) .add(9000, Activity.MEET) .add(11000, Activity.IDLE) @@ -37,8 +36,8 @@ private static Schedule makeAdult() private static Schedule makeChild() { final ScheduleBuilder builder = new ScheduleBuilder(new Schedule()); - builder.add(10, Activity.IDLE).add(10, Activities.STATIONARY).add(10, Activities.BATTLE).add(3000, - Activity.PLAY).add(6000, Activity.IDLE).add(10000, Activity.PLAY).add(12000, Activity.REST); + builder.add(10, Activity.IDLE).add(10, Activities.STATIONARY).add(3000, Activity.PLAY).add(6000, Activity.IDLE) + .add(10000, Activity.PLAY).add(12000, Activity.REST); return builder.build(); } } diff --git a/src/main/java/pokecube/core/ai/tasks/AIFollowOwner.java b/src/main/java/pokecube/core/ai/tasks/AIFollowOwner.java index c6b0513d1b..49f7796e41 100644 --- a/src/main/java/pokecube/core/ai/tasks/AIFollowOwner.java +++ b/src/main/java/pokecube/core/ai/tasks/AIFollowOwner.java @@ -93,9 +93,8 @@ else if (!this.petPathfinder.noPath() && this.petPathfinder.getPath().getCurrent BrainUtils.lookAt(this.entity, x, y, z); } - double dl = this.v.set(this.theOwner).distToSq(this.ownerPos); - if (dl < 1 && !this.petPathfinder.noPath()) return; - dl = this.v.set(this.entity).distTo(this.ownerPos); + final double dl = this.v.set(this.entity).distTo(this.ownerPos); + this.ownerPos.set(this.theOwner); double ownerSpeed = this.theOwner.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue(); @@ -109,11 +108,12 @@ else if (!this.petPathfinder.noPath() && this.petPathfinder.getPath().getCurrent if (ownerSpeed == 0) ownerSpeed = this.pokemob.getMovementSpeed(); double dist_speed = ownerSpeed; - if (dl > 3) dist_speed *= 1 + (dl - 3) / 10; + if (dl > 3) dist_speed *= 1 + (dl - 3) / 20; + this.speed = dist_speed; this.speed *= AIFollowOwner.speedMult; this.speed = Math.max(this.pokemob.getMovementSpeed(), this.speed); - this.speed = Math.min(1.5, this.speed); + this.speed = Math.min(1.25, this.speed); this.setWalkTo(this.ownerPos, this.speed, 0); } diff --git a/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java b/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java index dd1b343620..c4e8609a82 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java @@ -1,13 +1,10 @@ package pokecube.core.ai.tasks.combat.management; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Predicate; -import org.apache.logging.log4j.Level; - import com.google.common.collect.ImmutableMap; import net.minecraft.entity.Entity; @@ -18,17 +15,13 @@ import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.entity.player.PlayerEntity; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.tasks.TaskBase; import pokecube.core.handlers.TeamManager; -import pokecube.core.handlers.events.PCEventsHandler; import pokecube.core.interfaces.IMoveConstants.AIRoutine; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.IPokemob.ITargetFinder; -import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.interfaces.pokemob.ai.GeneralStates; import pokecube.core.utils.AITools; @@ -36,7 +29,6 @@ import thut.api.OwnableCaps; import thut.api.entity.ai.IAICombat; import thut.api.maths.Vector3; -import thut.api.terrain.TerrainManager; /** This IAIRunnable is to find targets for the pokemob to try to kill. */ public class FindTargetsTask extends TaskBase implements IAICombat, ITargetFinder @@ -50,62 +42,6 @@ public class FindTargetsTask extends TaskBase implements IAICombat, I public static int DEAGROTIMER = 50; - @SubscribeEvent - public static void livingSetTargetEvent(final LivingSetAttackTargetEvent evt) - { - if (!FindTargetsTask.handleDamagedTargets || evt.getEntity().getEntityWorld().isRemote) return; - // Only handle attack target set, not revenge target set. - if (evt.getTarget() == ((LivingEntity) evt.getEntity()).getRevengeTarget()) return; - // Prevent mob from targetting self. - if (evt.getTarget() == evt.getEntity()) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.log(Level.WARN, evt.getTarget() - + " is targetting self again.", new IllegalArgumentException()); - return; - } - - // Attempt to divert the target over to one of our mobs. - final List outmobs = PCEventsHandler.getOutMobs(evt.getTarget(), true); - outmobs.removeIf(o -> o == evt.getEntityLiving() || !o.isAlive()); - if (!outmobs.isEmpty() && evt.getEntityLiving() instanceof MobEntity) - { - Collections.sort(outmobs, (o1, o2) -> - { - final double dist1 = o1.getDistanceSq(evt.getEntityLiving()); - final double dist2 = o2.getDistanceSq(evt.getEntityLiving()); - return (int) (dist1 - dist2); - }); - final Entity nearest = outmobs.get(0); - if (nearest.getDistanceSq(evt.getEntityLiving()) < 256 && nearest instanceof LivingEntity) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Diverting agro to owner!"); - BrainUtils.initiateCombat((MobEntity) evt.getEntityLiving(), (LivingEntity) nearest); - return; - } - } - - final IPokemob pokemob = CapabilityPokemob.getPokemobFor(evt.getEntity()); - if (pokemob != null) - { - if (evt.getTarget() != null && pokemob.getTargetID() == evt.getTarget().getEntityId()) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.debug("Already targetted!"); - return; - } - if (evt.getTarget() == null && pokemob.getTargetID() == -1) return; - - // Prevent pokemob from targetting its owner. - if (evt.getTarget() != null && evt.getTarget().getUniqueID().equals(pokemob.getOwnerId())) - { - if (PokecubeCore.getConfig().debug) PokecubeCore.LOGGER.log(Level.WARN, evt.getTarget() - + " is targetting owner.", new IllegalArgumentException()); - return; - } - final boolean force = evt.getTarget() != null && evt.getTarget().getLastAttackedEntity() == evt.getEntity(); - pokemob.onSetTarget(evt.getTarget(), force); - } - } - Vector3 v = Vector3.getNewVector(); Vector3 v1 = Vector3.getNewVector(); @@ -155,9 +91,6 @@ protected boolean checkGuard() this.pokemob.getHome()); else centre.set(this.pokemob.getOwner()); - if (!TerrainManager.isAreaLoaded(this.world, centre, PokecubeCore.getConfig().guardSearchDistance + 2)) - return false; - final List ret = new ArrayList<>(); final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); // Only allow valid guard targets. @@ -166,24 +99,10 @@ protected boolean checkGuard() ret.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); if (ret.isEmpty()) return false; - LivingEntity newtarget = null; - double closest = Integer.MAX_VALUE; - final Vector3 here = this.v1.set(this.entity, true); - - // Select closest visible guard target. - for (final LivingEntity e : ret) - { - final double dist = e.getDistanceSq(this.entity); - this.v.set(e, true); - if (dist < closest && here.isVisible(this.world, this.v)) - { - closest = dist; - newtarget = e; - } - } - + // This is already sorted by distance! + final LivingEntity newtarget = ret.get(0); // Agro the target. - if (newtarget != null && Vector3.isVisibleEntityFromEntity(this.entity, newtarget)) + if (newtarget != null) { this.setAttackTarget(this.entity, newtarget); return true; @@ -193,7 +112,7 @@ protected boolean checkGuard() protected void setAttackTarget(final MobEntity attacker, final LivingEntity target) { - if (target == null) + if (target == null || !AITools.validTargets.test(target)) { BrainUtils.deagro(attacker); this.clear(); @@ -214,8 +133,6 @@ protected boolean checkOwner() // Only apply if has owner. if (owner == null) return false; - // Only apply if owner is close. - if (this.entity.getDistanceSq(owner) > 64) return false; if (this.pokemob.getGeneralState(GeneralStates.STAYING)) return false; @@ -223,13 +140,11 @@ protected boolean checkOwner() // Disable via rate out of bounds, or not correct time in the rate. if (rate <= 0 || this.entity.ticksExisted % rate != 0) return false; - if (!TerrainManager.isAreaLoaded(this.world, this.entity.getPosition(), PokecubeCore - .getConfig().guardSearchDistance + 2)) return false; - final List list = new ArrayList<>(); final List pokemobs = this.entity.getBrain().getMemory(MemoryModuleType.VISIBLE_MOBS).get(); list.addAll(pokemobs); - list.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance); + list.removeIf(e -> e.getDistance(this.entity) > PokecubeCore.getConfig().guardSearchDistance + && AITools.validTargets.test(e)); if (list.isEmpty()) return false; final Entity old = BrainUtils.getAttackTarget(this.entity); @@ -240,8 +155,7 @@ protected boolean checkOwner() { if (oldOwner != null && entity == oldOwner) return false; final LivingEntity targ = BrainUtils.getAttackTarget(entity); - if (entity instanceof MobEntity && targ != null && targ.equals(owner) && Vector3.isVisibleEntityFromEntity( - entity, entity)) + if (entity instanceof MobEntity && targ != null && targ.equals(owner)) { this.setAttackTarget(this.entity, entity); return true; diff --git a/src/main/java/pokecube/core/ai/tasks/utility/StoreTask.java b/src/main/java/pokecube/core/ai/tasks/utility/StoreTask.java index 857779fca7..e8b1b2e497 100644 --- a/src/main/java/pokecube/core/ai/tasks/utility/StoreTask.java +++ b/src/main/java/pokecube/core/ai/tasks/utility/StoreTask.java @@ -376,7 +376,7 @@ private IItemHandlerModifiable getInventory(final IBlockReader world, final Bloc final TileEntity tile = world.getTileEntity(pos); if (tile == null) return null; IItemHandler handler; - if ((handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side).orElseGet( + if ((handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side).orElse( null)) instanceof IItemHandlerModifiable) return (IItemHandlerModifiable) handler; return null; } diff --git a/src/main/java/pokecube/core/handlers/Config.java b/src/main/java/pokecube/core/handlers/Config.java index 568e174025..bf43d63da6 100644 --- a/src/main/java/pokecube/core/handlers/Config.java +++ b/src/main/java/pokecube/core/handlers/Config.java @@ -26,6 +26,7 @@ import pokecube.core.items.pokecubes.Pokecube; import pokecube.core.items.pokecubes.PokecubeManager; import pokecube.core.items.pokemobeggs.ItemPokemobEgg; +import pokecube.core.utils.AITools; import pokecube.core.utils.PokecubeSerializer; import pokecube.core.world.terrain.PokecubeTerrainChecker; import thut.core.common.config.Config.ConfigData; @@ -274,15 +275,14 @@ private static SoundEvent getRegisteredSoundEvent(final String id) public boolean diveEnabled = true; @Configure(category = Config.mobAI) - public List dodgeSounds = Lists.newArrayList("entity.witch.throw"); + public List dodgeSounds = Lists.newArrayList("entity.witch.throw"); @Configure(category = Config.mobAI) - public List leapSounds = Lists.newArrayList("entity.witch.throw"); + public List leapSounds = Lists.newArrayList("entity.witch.throw"); @Configure(category = Config.mobAI) - public List guardBlacklistClass = Lists.newArrayList("net.minecraft.entity.IMerchant", - "net.minecraft.entity.INpc", "pokecube.core.items.pokemobeggs.EntityPokemobEgg", - "net.minecraft.entity.IProjectile"); + public List aggroBlacklistTags = Lists.newArrayList(); @Configure(category = Config.mobAI) - public List guardBlacklistId = Lists.newArrayList(); + public List aggroBlacklistIds = Lists.newArrayList("minecraft:villager", "minecraft:armor_stand", + "pokecube_adventures:trainer", "pokecube_adventures:leader"); @Configure(category = Config.mobAI) public double interactHungerScale = 1; @@ -695,6 +695,8 @@ public void onUpdated() SpawnHandler.MAXNUM = this.mobSpawnNumber; if (this.breedingDelay < 600) this.breedingDelay = 1000; + AITools.initIDs(); + SpawnHandler.doSpawns = this.pokemonSpawn; SpawnHandler.lvlCap = this.shouldCap; SpawnHandler.capLevel = this.levelCap; diff --git a/src/main/java/pokecube/core/interfaces/IPokecube.java b/src/main/java/pokecube/core/interfaces/IPokecube.java index c405edf735..fdcbc21fd7 100644 --- a/src/main/java/pokecube/core/interfaces/IPokecube.java +++ b/src/main/java/pokecube/core/interfaces/IPokecube.java @@ -15,6 +15,7 @@ import pokecube.core.events.pokemob.CaptureEvent.Post; import pokecube.core.events.pokemob.CaptureEvent.Pre; import pokecube.core.interfaces.capabilities.CapabilityPokemob; +import pokecube.core.items.pokecubes.EntityPokecubeBase; import thut.api.maths.Vector3; public interface IPokecube @@ -27,12 +28,12 @@ public abstract static class DefaultPokecubeBehavior extends PokecubeBehavior { @Override - public void onPostCapture(Post evt) + public void onPostCapture(final Post evt) { } @Override - public void onPreCapture(Pre evt) + public void onPreCapture(final Pre evt) { } } @@ -41,13 +42,13 @@ public static class NormalPokecubeBehavoir extends DefaultPokecubeBehavior { final double rate; - public NormalPokecubeBehavoir(double rate) + public NormalPokecubeBehavoir(final double rate) { this.rate = rate; } @Override - public double getCaptureModifier(IPokemob mob) + public double getCaptureModifier(final IPokemob mob) { return this.rate; } @@ -66,7 +67,7 @@ public static abstract class PokecubeBehavior extends ForgeRegistryEntry 0.5) if (this.here == null) this.here = Vector3.getNewVector(); this.here.set(this.getEntity()).addTo(0, this.getEntity().getEyeHeight(), 0); MovesUtils.useMove(move, this.getEntity(), target, this.here, targetLocation); + // clear this if we use a move. + this.setCombatState(CombatStates.NOITEMUSE, false); this.here.set(this.getEntity()); } diff --git a/src/main/java/pokecube/core/items/pokecubes/DispenserBehaviorPokecube.java b/src/main/java/pokecube/core/items/pokecubes/DispenserBehaviorPokecube.java index 8ed3520dfd..04110b8670 100644 --- a/src/main/java/pokecube/core/items/pokecubes/DispenserBehaviorPokecube.java +++ b/src/main/java/pokecube/core/items/pokecubes/DispenserBehaviorPokecube.java @@ -61,7 +61,7 @@ else if (stack.getItem() instanceof IPokecube) { final IPokecube cube = (IPokecube) stack.getItem(); final Vector3 direction = Vector3.getNewVector().set(dir); - if (cube.throwPokecube(source.getWorld(), player, stack, direction, 0.25f)) stack.split(1); + if (cube.throwPokecube(source.getWorld(), player, stack, direction, 0.25f) != null) stack.split(1); } return stack; } diff --git a/src/main/java/pokecube/core/items/pokecubes/Pokecube.java b/src/main/java/pokecube/core/items/pokecubes/Pokecube.java index c4da43a243..ea02c9e118 100644 --- a/src/main/java/pokecube/core/items/pokecubes/Pokecube.java +++ b/src/main/java/pokecube/core/items/pokecubes/Pokecube.java @@ -312,12 +312,12 @@ public void onPlayerStoppedUsing(final ItemStack stack, final World worldIn, fin boolean used = false; final boolean filledOrSneak = filled || player.isSneaking() || dt > 5; if (target != null && EntityPokecubeBase.SEEKING) used = this.throwPokecubeAt(worldIn, player, stack, - targetLocation, target); + targetLocation, target) != null; else if (filledOrSneak || !EntityPokecubeBase.SEEKING) { float power = (this.getUseDuration(stack) - timeLeft) / (float) 100; power = Math.min(1, power); - used = this.throwPokecube(worldIn, player, stack, direction, power); + used = this.throwPokecube(worldIn, player, stack, direction, power) != null; } else { @@ -360,12 +360,12 @@ public boolean showDurabilityBar(final ItemStack stack) } @Override - public boolean throwPokecube(final World world, final LivingEntity thrower, final ItemStack cube, + public EntityPokecubeBase throwPokecube(final World world, final LivingEntity thrower, final ItemStack cube, final Vector3 direction, final float power) { EntityPokecube entity = null; final ResourceLocation id = PokecubeItems.getCubeId(cube); - if (id == null || !IPokecube.BEHAVIORS.containsKey(id)) return false; + if (id == null || !IPokecube.BEHAVIORS.containsKey(id)) return null; final ItemStack stack = cube.copy(); final boolean hasMob = PokecubeManager.isFilled(stack); final Config config = PokecubeCore.getConfig(); @@ -377,9 +377,9 @@ public boolean throwPokecube(final World world, final LivingEntity thrower, fina final IPermissionHandler handler = PermissionAPI.getPermissionHandler(); final PlayerContext context = new PlayerContext(player); if (config.permsSendOut && !handler.hasPermission(player.getGameProfile(), Permissions.SENDOUTPOKEMOB, - context)) return false; + context)) return null; if (config.permsSendOutSpecific && !handler.hasPermission(player.getGameProfile(), - Permissions.SENDOUTSPECIFIC.get(entry), context)) return false; + Permissions.SENDOUTSPECIFIC.get(entry), context)) return null; } stack.setCount(1); entity = new EntityPokecube(EntityPokecube.TYPE, world); @@ -404,16 +404,16 @@ public boolean throwPokecube(final World world, final LivingEntity thrower, fina world.addEntity(entity); if (hasMob && thrower instanceof PlayerEntity) PlayerPokemobCache.UpdateCache(stack, false, false); } - return true; + return entity; } @Override - public boolean throwPokecubeAt(final World world, final LivingEntity thrower, final ItemStack cube, + public EntityPokecubeBase throwPokecubeAt(final World world, final LivingEntity thrower, final ItemStack cube, Vector3 targetLocation, Entity target) { EntityPokecube entity = null; final ResourceLocation id = PokecubeItems.getCubeId(cube); - if (id == null || !IPokecube.BEHAVIORS.containsKey(id)) return false; + if (id == null || !IPokecube.BEHAVIORS.containsKey(id)) return null; final ItemStack stack = cube.copy(); stack.setCount(1); entity = new EntityPokecube(EntityPokecube.TYPE, world); @@ -454,7 +454,7 @@ public boolean throwPokecubeAt(final World world, final LivingEntity thrower, fi stack, false, false); } } - else if (!rightclick) return false; - return true; + else if (!rightclick) return null; + return entity; } } diff --git a/src/main/java/pokecube/core/moves/MovesUtils.java b/src/main/java/pokecube/core/moves/MovesUtils.java index d724d31370..a105409f6a 100644 --- a/src/main/java/pokecube/core/moves/MovesUtils.java +++ b/src/main/java/pokecube/core/moves/MovesUtils.java @@ -18,6 +18,7 @@ import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import pokecube.core.PokecubeCore; @@ -74,7 +75,8 @@ public static void sendPairedMessages(final Entity target, final IPokemob attack { String key = baseKey + ".user"; final IPokemob attacked = CapabilityPokemob.getPokemobFor(target); - final ITextComponent targName = attacker != null ? attacker.getDisplayName() : target.getDisplayName(); + final ITextComponent targName = target != null ? target.getDisplayName() + : attacker != null ? attacker.getDisplayName() : new StringTextComponent("ERR PLS REPORT"); if (attacker != null) attacker.displayMessageToOwner(new TranslationTextComponent(key, targName)); key = baseKey + ".target"; if (target != attacker.getEntity() && target != null) diff --git a/src/main/java/pokecube/core/utils/AITools.java b/src/main/java/pokecube/core/utils/AITools.java index 8fbbf19dfa..bf48868135 100644 --- a/src/main/java/pokecube/core/utils/AITools.java +++ b/src/main/java/pokecube/core/utils/AITools.java @@ -7,6 +7,7 @@ import com.google.common.collect.Sets; import net.minecraft.entity.Entity; +import net.minecraft.entity.MobEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.util.DamageSource; import net.minecraft.util.ResourceLocation; @@ -15,7 +16,6 @@ import pokecube.core.PokecubeCore; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.pokemob.ai.GeneralStates; -import pokecube.core.items.pokecubes.EntityPokecubeBase; import pokecube.core.items.pokemobeggs.EntityPokemobEgg; import pokecube.core.moves.damage.IPokedamage; @@ -43,11 +43,12 @@ private static class ValidCheck implements Predicate @Override public boolean test(final Entity input) { + if (input == null) return true; final ResourceLocation eid = input.getType().getRegistryName(); if (AITools.invalidIDs.contains(eid)) return false; - // Then check if disabled via class - for (final Class clas : AITools.invalidClasses) - if (clas.isInstance(input)) return false; + for (final String tag : AITools.invalidTags) + if (input.getTags().contains(tag)) return false; + // Then check if is a valid player. if (input instanceof ServerPlayerEntity) { @@ -56,11 +57,11 @@ public boolean test(final Entity input) if (player.isCreative() || player.isSpectator()) return false; // Do not target any player on easy or peaceful if (player.getServerWorld().getDifficulty().getId() <= Difficulty.EASY.getId()) return false; + return true; } // Confirm is not an egg or a pokecube as well if (input instanceof EntityPokemobEgg) return false; - if (input instanceof EntityPokecubeBase) return false; - return true; + return input instanceof MobEntity; } } @@ -89,11 +90,12 @@ public boolean test(final DamageSource t) public static boolean handleDamagedTargets = true; - public static int DEAGROTIMER = 50; - public static Set> invalidClasses = Sets.newHashSet(); + public static int DEAGROTIMER = 50; public static Set invalidIDs = Sets.newHashSet(); + public static Set invalidTags = Sets.newHashSet(); + /** * Checks the blacklists set via configs, to see whether the target is a * valid choice. @@ -120,18 +122,8 @@ public boolean test(final DamageSource t) public static void initIDs() { - for (final String s : PokecubeCore.getConfig().guardBlacklistClass) - try - { - final Class c = Class.forName(s, false, PokecubeCore.getConfig().getClass().getClassLoader()); - AITools.invalidClasses.add(c); - } - catch (final ClassNotFoundException e) - { - e.printStackTrace(); - } final Set keys = ForgeRegistries.ENTITIES.getKeys(); - for (String s : PokecubeCore.getConfig().guardBlacklistId) + for (String s : PokecubeCore.getConfig().aggroBlacklistIds) if (s.endsWith("*")) { s = s.substring(0, s.length() - 1); @@ -139,6 +131,9 @@ public static void initIDs() if (res.toString().startsWith(s)) AITools.invalidIDs.add(res); } else AITools.invalidIDs.add(new ResourceLocation(s)); + + for (final String s : PokecubeCore.getConfig().aggroBlacklistTags) + AITools.invalidTags.add(s); } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 7be2f96779..e1b3eada50 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -19,8 +19,7 @@ protected net.minecraft.entity.merchant.villager.VillagerEntity func_213744_a(Ln public net.minecraft.world.server.ServerWorld field_217492_a # tickingEntities public net.minecraft.entity.ai.brain.Brain func_218217_d(Lnet/minecraft/entity/ai/brain/schedule/Activity;)Z # hasRequiredMemories -public net.minecraft.entity.ai.brain.Brain field_218230_a # memories -public net.minecraft.entity.ai.brain.Brain field_218231_b # sensors +public net.minecraft.entity.ai.brain.Brain * # everything public net.minecraft.pathfinding.PathNavigator func_225464_a(Ljava/util/Set;IZI)Lnet/minecraft/pathfinding/Path; # func_225464_a diff --git a/src/main/resources/assets/pokecube_adventures/lang/en_us.json b/src/main/resources/assets/pokecube_adventures/lang/en_us.json index afb3722080..00f87831db 100644 --- a/src/main/resources/assets/pokecube_adventures/lang/en_us.json +++ b/src/main/resources/assets/pokecube_adventures/lang/en_us.json @@ -214,6 +214,8 @@ "entity.pokecube_adventures.targetParticles": "Target", "pokecube.trainer.agress": "%1$s §cwants to battle!", + "pokecube.trainer.agress_request_allowed": "§aYou request a battle with §r%1$s§a!", + "pokecube.trainer.agress_request_denied": "%1$s §c does not want to battle you right now.", "pokecube.trainer.forget": "%1$s §cno longer wants to battle...", "pokecube.trainer.defeat": "%1$s §ahas been defeated!", "pokecube.trainer.toss": "%1$s §csent out %2$s!", From d540e952ca355f97534e726db48723bbc4e4bf3a Mon Sep 17 00:00:00 2001 From: Thutmose Date: Sat, 23 May 2020 20:44:14 -0400 Subject: [PATCH 22/27] Update ManagePokemobTarget.java this is handled by the pokemob itself --- .../adventures/ai/tasks/battle/ManagePokemobTarget.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java index 3697d86dd9..ebec80458d 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java @@ -8,7 +8,6 @@ import pokecube.core.ai.brain.BrainUtils; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; -import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.utils.PokemobTracker; public class ManagePokemobTarget extends BaseBattleTask @@ -34,7 +33,6 @@ protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, f && CapabilityPokemob.getPokemobFor(e) != null); if (!alternates.isEmpty()) newTarget = (LivingEntity) alternates.get(0); } - if (!mob.getCombatState(CombatStates.ANGRY)) mob.setCombatState(CombatStates.ANGRY, true); // check if pokemob's target is same as trainers. if (mobTarget != newTarget && newTarget != null) BrainUtils.initiateCombat(mob.getEntity(), newTarget); } From 84fd6f895e8ba394179986d919d7a2ca88fdeb08 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Sat, 23 May 2020 21:46:44 -0400 Subject: [PATCH 23/27] adjustments to some activity switching should prevent trainers getting stuck in "stationary" mode --- .../ai/tasks/battle/ManagePokemobTarget.java | 12 ++++++++++++ .../adventures/ai/tasks/battle/agro/DeAgro.java | 9 ++------- .../capabilities/CapabilityHasPokemobs.java | 2 ++ .../client/gui/items/editor/pages/Spawn.java | 10 +++++++++- .../adventures/events/TrainerEventHandler.java | 8 +++++++- .../pokecube/adventures/network/PacketTrainer.java | 11 +++++++---- src/main/java/pokecube/core/ai/routes/GuardTask.java | 4 +++- 7 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java index ebec80458d..9a839ca3b0 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java @@ -5,6 +5,8 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.world.server.ServerWorld; +import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; +import pokecube.adventures.capabilities.TrainerCaps; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.capabilities.CapabilityPokemob; @@ -29,12 +31,22 @@ protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, f // Try to send our mob after the target's nearest mob instead. if (target == null) { + newTarget = this.target; final List alternates = PokemobTracker.getMobs(this.target, e -> e.getDistanceSq(this.entity) < 64 && CapabilityPokemob.getPokemobFor(e) != null); if (!alternates.isEmpty()) newTarget = (LivingEntity) alternates.get(0); } + // check if pokemob's target is same as trainers. if (mobTarget != newTarget && newTarget != null) BrainUtils.initiateCombat(mob.getEntity(), newTarget); + + final IHasPokemobs other = TrainerCaps.getHasPokemobs(this.target); + if (other != null && other.getTarget() != this.entity) + { + this.target.setLastAttackedEntity(owner); + owner.setLastAttackedEntity(this.entity); + other.onSetTarget(this.entity); + } } @Override diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java index d359a15aa3..46c8a08d3b 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/DeAgro.java @@ -30,7 +30,7 @@ public DeAgro(final LivingEntity trainer) @Override protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) { - boolean deagro = false; + boolean deagro = !this.target.isAlive() || this.target.getHealth() <= 0; boolean won = false; @@ -92,11 +92,7 @@ protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, f } if (found) this.deagroTimer = 20; } - if (this.deagroTimer-- < 0) - { - System.out.println("Timeout"); - deagro = true; - } + if (this.deagroTimer-- < 0) deagro = true; } } @@ -107,7 +103,6 @@ protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, f this.trainer.onWin(this.target); if (other.getTarget() == this.entity) other.onLose(this.entity); } - System.out.println("Deagroing"); this.trainer.deAgro(this.trainer, TrainerCaps.getHasPokemobs(this.target)); } } diff --git a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java index 8500f5d021..58e3fec61e 100644 --- a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java @@ -12,6 +12,7 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraft.entity.ai.brain.schedule.Activity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.ItemStack; @@ -686,6 +687,7 @@ public void onSetTarget(final LivingEntity target) { BrainUtils.deagro(this.getTrainer()); this.resetPokemob(); + this.getTrainer().getBrain().switchTo(Activity.IDLE); } else if (this.getTrainer() instanceof MobEntity) { diff --git a/src/main/java/pokecube/adventures/client/gui/items/editor/pages/Spawn.java b/src/main/java/pokecube/adventures/client/gui/items/editor/pages/Spawn.java index ebe0aa1903..435d9f2702 100644 --- a/src/main/java/pokecube/adventures/client/gui/items/editor/pages/Spawn.java +++ b/src/main/java/pokecube/adventures/client/gui/items/editor/pages/Spawn.java @@ -20,6 +20,7 @@ public class Spawn extends Page int index = 0; boolean leader = false; + boolean stand = false; public Spawn(final EditorGui parent) { @@ -82,13 +83,20 @@ public void onPageOpened() else b.setMessage("trainer"); this.leader = b.getMessage().equals("leader"); })); - this.addButton(new Button(xOffset + 25, yOffset + 40, 40, 20, "spawn", b -> + this.addButton(new Button(xOffset - 5, yOffset + 40, 40, 20, "stands", b -> + { + if (b.getMessage().equals("wanders")) b.setMessage("stands"); + else b.setMessage("wanders"); + this.stand = b.getMessage().equals("stands"); + })); + this.addButton(new Button(xOffset + 35, yOffset + 40, 40, 20, "spawn", b -> { final PacketTrainer message = new PacketTrainer(PacketTrainer.SPAWN); message.data.putString("T", this.type.getText()); final int value = this.level.getText().isEmpty() ? 1 : Integer.parseInt(this.level.getText()); message.data.putInt("L", value); message.data.putBoolean("C", this.leader); + message.data.putBoolean("S", this.stand); PokecubeAdv.packets.sendToServer(message); })); } diff --git a/src/main/java/pokecube/adventures/events/TrainerEventHandler.java b/src/main/java/pokecube/adventures/events/TrainerEventHandler.java index 72b69cc7a4..732cba2ac1 100644 --- a/src/main/java/pokecube/adventures/events/TrainerEventHandler.java +++ b/src/main/java/pokecube/adventures/events/TrainerEventHandler.java @@ -10,6 +10,8 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; import net.minecraft.entity.SpawnReason; +import net.minecraft.entity.ai.brain.Brain; +import net.minecraft.entity.ai.brain.schedule.Activity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.ItemStack; @@ -54,6 +56,8 @@ import pokecube.adventures.network.PacketTrainer; import pokecube.adventures.utils.DBLoader; import pokecube.core.PokecubeCore; +import pokecube.core.ai.brain.BrainUtils; +import pokecube.core.ai.npc.Activities; import pokecube.core.ai.routes.IGuardAICapability; import pokecube.core.database.Database; import pokecube.core.database.PokedexEntryLoader; @@ -336,9 +340,11 @@ public static void onNpcTick(final LivingUpdateEvent event) if (pokemobHolder != null) { final LivingEntity npc = event.getEntityLiving(); + final Brain brain = npc.getBrain(); + if (!BrainUtils.hasAttackTarget(npc) && brain.hasActivity(Activities.BATTLE)) brain.switchTo(Activity.IDLE); // Add our task if the dummy not present, this can happen if the // brain has reset before - if (npc instanceof MobEntity && !npc.getBrain().sensors.containsKey(Tasks.DUMMY) && npc + if (npc instanceof MobEntity && !brain.sensors.containsKey(Tasks.DUMMY) && npc .getEntityWorld() instanceof ServerWorld) { TypeTrainer.addAI((MobEntity) npc); diff --git a/src/main/java/pokecube/adventures/network/PacketTrainer.java b/src/main/java/pokecube/adventures/network/PacketTrainer.java index e018546387..c9af90253d 100644 --- a/src/main/java/pokecube/adventures/network/PacketTrainer.java +++ b/src/main/java/pokecube/adventures/network/PacketTrainer.java @@ -176,10 +176,13 @@ public void handleServer(final ServerPlayerEntity player) final JsonObject thing = new JsonObject(); thing.addProperty("level", level); thing.addProperty("trainerType", type); - final GuardInfo info = new GuardInfo(); - info.time = "day"; - info.roam = 2; - thing.add("guard", PokedexEntryLoader.gson.toJsonTree(info)); + if (this.data.getBoolean("S")) + { + final GuardInfo info = new GuardInfo(); + info.time = "day"; + info.roam = 2; + thing.add("guard", PokedexEntryLoader.gson.toJsonTree(info)); + } final String var = PokedexEntryLoader.gson.toJson(thing); args = args + var; final StructureEvent.ReadTag event = new ReadTag(args, vec.getPos(), player.getEntityWorld(), player diff --git a/src/main/java/pokecube/core/ai/routes/GuardTask.java b/src/main/java/pokecube/core/ai/routes/GuardTask.java index 3fe6e7d702..532dd0308a 100644 --- a/src/main/java/pokecube/core/ai/routes/GuardTask.java +++ b/src/main/java/pokecube/core/ai/routes/GuardTask.java @@ -28,7 +28,9 @@ protected boolean shouldContinueExecuting(final ServerWorld worldIn, final Livin @Override protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) { - return this.goal.shouldExecute(); + final boolean valid = this.goal.shouldExecute(); + if (!valid && owner.getBrain().hasActivity(Activities.STATIONARY)) owner.getBrain().switchTo(Activity.IDLE); + return valid; } @Override From 4c6c6e553c2cdafe78879da9f94954e7bde7846b Mon Sep 17 00:00:00 2001 From: Thutmose Date: Sat, 23 May 2020 23:07:02 -0400 Subject: [PATCH 24/27] another pass at adjustments to trainer code --- .../java/pokecube/adventures/PokecubeAdv.java | 8 ++++ .../adventures/ai/brain/MemoryTypes.java | 18 ++++++++ .../pokecube/adventures/ai/tasks/Tasks.java | 4 +- .../ai/tasks/battle/BaseBattleTask.java | 11 ++--- .../ai/tasks/battle/ManageOutMob.java | 4 ++ .../ai/tasks/battle/ManagePokemobTarget.java | 10 ++--- .../ai/tasks/battle/agro/AgroTargets.java | 13 ------ .../ai/tasks/battle/agro/BaseAgroTask.java | 17 ++++---- .../capabilities/CapabilityHasPokemobs.java | 41 +++++++++++++------ .../capabilities/player/PlayerPokemobs.java | 20 ++++----- .../events/TrainerEventHandler.java | 5 ++- .../combat/management/FindTargetsTask.java | 25 +++++++++++ 12 files changed, 119 insertions(+), 57 deletions(-) create mode 100644 src/main/java/pokecube/adventures/ai/brain/MemoryTypes.java diff --git a/src/main/java/pokecube/adventures/PokecubeAdv.java b/src/main/java/pokecube/adventures/PokecubeAdv.java index 7b6538fb90..02fd719da7 100644 --- a/src/main/java/pokecube/adventures/PokecubeAdv.java +++ b/src/main/java/pokecube/adventures/PokecubeAdv.java @@ -8,6 +8,7 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.EntityType; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.entity.merchant.villager.VillagerProfession; import net.minecraft.inventory.container.ContainerType; import net.minecraft.item.BlockItem; @@ -27,6 +28,7 @@ import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import pokecube.adventures.advancements.Triggers; +import pokecube.adventures.ai.brain.MemoryTypes; import pokecube.adventures.ai.poi.PointsOfInterest; import pokecube.adventures.ai.poi.Professions; import pokecube.adventures.blocks.BlockEventHandler; @@ -116,6 +118,12 @@ public static void registerEntities(final RegistryEvent.Register> event.getRegistry().register(LeaderNpc.TYPE.setRegistryName(PokecubeAdv.MODID, "leader")); } + @SubscribeEvent + public static void registerMemories(final RegistryEvent.Register> event) + { + MemoryTypes.register(event); + } + @SubscribeEvent public static void registerItems(final RegistryEvent.Register event) { diff --git a/src/main/java/pokecube/adventures/ai/brain/MemoryTypes.java b/src/main/java/pokecube/adventures/ai/brain/MemoryTypes.java new file mode 100644 index 0000000000..7dc0780733 --- /dev/null +++ b/src/main/java/pokecube/adventures/ai/brain/MemoryTypes.java @@ -0,0 +1,18 @@ +package pokecube.adventures.ai.brain; + +import java.util.Optional; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.memory.MemoryModuleType; +import net.minecraftforge.event.RegistryEvent.Register; +import pokecube.adventures.PokecubeAdv; + +public class MemoryTypes +{ + public static final MemoryModuleType BATTLETARGET = new MemoryModuleType<>(Optional.empty()); + + public static void register(final Register> event) + { + event.getRegistry().register(MemoryTypes.BATTLETARGET.setRegistryName(PokecubeAdv.MODID, "battle_target")); + } +} diff --git a/src/main/java/pokecube/adventures/ai/tasks/Tasks.java b/src/main/java/pokecube/adventures/ai/tasks/Tasks.java index fc27812ee5..733c81ef1e 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/Tasks.java +++ b/src/main/java/pokecube/adventures/ai/tasks/Tasks.java @@ -16,6 +16,7 @@ import net.minecraft.entity.ai.brain.sensor.SensorType; import net.minecraft.entity.ai.brain.task.Task; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.ai.brain.MemoryTypes; import pokecube.adventures.ai.tasks.battle.ChooseAttacks; import pokecube.adventures.ai.tasks.battle.ManageOutMob; import pokecube.adventures.ai.tasks.battle.ManagePokemobTarget; @@ -40,7 +41,8 @@ public class Tasks SensorType.NEAREST_PLAYERS, SensorType.INTERACTABLE_DOORS, SensorType.HURT_BY, Sensors.VISIBLE_BLOCKS, Sensors.VISIBLE_ITEMS, Sensors.INTERESTING_MOBS); - public static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModules.ATTACKTARGET); + public static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModules.ATTACKTARGET, + MemoryTypes.BATTLETARGET); @SuppressWarnings("unchecked") public static void addBattleTasks(final LivingEntity mob, diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java b/src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java index 475d58afe1..2b9d6fafb2 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/BaseBattleTask.java @@ -5,12 +5,12 @@ import com.google.common.collect.Maps; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.Brain; import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.world.server.ServerWorld; +import pokecube.adventures.ai.brain.MemoryTypes; import pokecube.adventures.ai.tasks.BaseTask; -import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.brain.MemoryModules; import pokecube.core.ai.tasks.TaskBase; public abstract class BaseBattleTask extends BaseTask @@ -19,7 +19,7 @@ public abstract class BaseBattleTask extends BaseTask static { - BaseBattleTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_PRESENT); + BaseBattleTask.MEMS.put(MemoryTypes.BATTLETARGET, MemoryModuleStatus.VALUE_PRESENT); } protected LivingEntity target; @@ -37,8 +37,9 @@ public BaseBattleTask(final LivingEntity trainer, final Map, @Override protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) { - if (!BrainUtils.hasAttackTarget(this.entity)) return false; - this.target = BrainUtils.getAttackTarget(this.entity); + final Brain brain = owner.getBrain(); + if (!brain.hasMemory(MemoryTypes.BATTLETARGET)) return false; + this.target = brain.getMemory(MemoryTypes.BATTLETARGET).get(); return true; } diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java b/src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java index c4d4ef1af3..e8de7e08d8 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/ManageOutMob.java @@ -4,6 +4,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.BrainUtil; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.world.server.ServerWorld; @@ -122,6 +123,9 @@ private boolean considerSwapPokemob() protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) { final boolean hasMob = this.trainer.getOutMob() != null; + + BrainUtil.lookAt(this.entity, this.target); + if (hasMob) this.considerSwapPokemob(); else this.doAggression(); } diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java index 9a839ca3b0..9f27970f47 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/ManagePokemobTarget.java @@ -23,6 +23,9 @@ public ManagePokemobTarget(final LivingEntity trainer) @Override protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, final long gameTime) { + final IHasPokemobs other = TrainerCaps.getHasPokemobs(this.target); + if (other != null) other.onSetTarget(this.entity, true); + final IPokemob mob = this.trainer.getOutMob(); if (mob == null || this.target == null) return; final LivingEntity mobTarget = BrainUtils.getAttackTarget(mob.getEntity()); @@ -40,13 +43,6 @@ protected void updateTask(final ServerWorld worldIn, final LivingEntity owner, f // check if pokemob's target is same as trainers. if (mobTarget != newTarget && newTarget != null) BrainUtils.initiateCombat(mob.getEntity(), newTarget); - final IHasPokemobs other = TrainerCaps.getHasPokemobs(this.target); - if (other != null && other.getTarget() != this.entity) - { - this.target.setLastAttackedEntity(owner); - owner.setLastAttackedEntity(this.entity); - other.onSetTarget(this.entity); - } } @Override diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java index 2d9ff1f5de..b961e292a8 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/AgroTargets.java @@ -1,28 +1,15 @@ package pokecube.adventures.ai.tasks.battle.agro; -import java.util.Map; import java.util.function.Predicate; -import com.google.common.collect.Maps; - import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; -import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.util.EntityPredicates; import pokecube.adventures.PokecubeAdv; import pokecube.adventures.utils.TrainerTracker; -import pokecube.core.ai.brain.MemoryModules; import thut.api.maths.Vector3; public class AgroTargets extends BaseAgroTask { - private static final Map, MemoryModuleStatus> MEMS = Maps.newHashMap(); - - static - { - AgroTargets.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_ABSENT); - } - // Predicated to return true for invalid targets final Predicate validTargets; diff --git a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java index b1c3c61a63..77169d511b 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java +++ b/src/main/java/pokecube/adventures/ai/tasks/battle/agro/BaseAgroTask.java @@ -7,16 +7,16 @@ import com.google.common.collect.Maps; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.Brain; import net.minecraft.entity.ai.brain.BrainUtil; import net.minecraft.entity.ai.brain.memory.MemoryModuleStatus; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.util.math.Vec3d; import net.minecraft.world.server.ServerWorld; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.ai.brain.MemoryTypes; import pokecube.adventures.ai.tasks.BaseTask; import pokecube.adventures.capabilities.CapabilityHasPokemobs.ITargetWatcher; -import pokecube.core.ai.brain.BrainUtils; -import pokecube.core.ai.brain.MemoryModules; import thut.api.IOwnable; import thut.api.OwnableCaps; @@ -26,7 +26,7 @@ public abstract class BaseAgroTask extends BaseTask implements ITargetWatcher static { - BaseAgroTask.MEMS.put(MemoryModules.ATTACKTARGET, MemoryModuleStatus.VALUE_ABSENT); + BaseAgroTask.MEMS.put(MemoryTypes.BATTLETARGET, MemoryModuleStatus.VALUE_ABSENT); } private int timer = 0; @@ -49,11 +49,13 @@ public BaseAgroTask(final LivingEntity trainer, final float agressionProbability protected boolean shouldContinueExecuting(final ServerWorld worldIn, final LivingEntity entityIn, final long gameTimeIn) { - if (!BrainUtils.hasAttackTarget(this.entity)) return false; - if (BrainUtils.getAttackTarget(this.entity) != this.target) + final Brain brain = this.entity.getBrain(); + if (!brain.hasMemory(MemoryTypes.BATTLETARGET)) return false; + final LivingEntity targ = brain.getMemory(MemoryTypes.BATTLETARGET).get(); + if (targ != this.target) { this.timer = 0; - this.target = BrainUtils.getAttackTarget(this.entity); + this.target = targ; } return this.maxTimer <= 0 || this.timer++ < this.maxTimer; } @@ -107,7 +109,8 @@ protected void startExecuting(final ServerWorld worldIn, final LivingEntity enti @Override protected boolean shouldExecute(final ServerWorld worldIn, final LivingEntity owner) { - if (BrainUtils.hasAttackTarget(this.entity)) return false; + final Brain brain = owner.getBrain(); + if (brain.hasMemory(MemoryTypes.BATTLETARGET)) return false; if (owner.ticksExisted % PokecubeAdv.config.trainerAgroRate != 0) return false; return this.entity.getBrain().hasMemory(MemoryModuleType.VISIBLE_MOBS); } diff --git a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java index 58e3fec61e..7df08604bc 100644 --- a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java @@ -11,6 +11,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; +import net.minecraft.entity.ai.brain.Brain; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.entity.ai.brain.schedule.Activity; import net.minecraft.entity.player.PlayerEntity; @@ -28,6 +29,7 @@ import pokecube.adventures.Config; import pokecube.adventures.PokecubeAdv; import pokecube.adventures.advancements.Triggers; +import pokecube.adventures.ai.brain.MemoryTypes; import pokecube.adventures.capabilities.CapabilityHasRewards.IHasRewards; import pokecube.adventures.capabilities.CapabilityNPCAIStates.IHasNPCAIStates; import pokecube.adventures.capabilities.CapabilityNPCMessages.IHasMessages; @@ -217,12 +219,7 @@ public AllowedBattle canBattle(final LivingEntity target, final boolean checkWat final IHasPokemobs trainer = TrainerCaps.getHasPokemobs(target); // No battling a target already battling something - if (trainer != null) - { - if (trainer.getTarget() != null && trainer.getTarget() != this.getTrainer()) - return AllowedBattle.NOTNOW; - if (trainer.getTarget() == this.getTrainer()) return AllowedBattle.NOTNOW; - } + if (trainer != null && trainer.getTarget() != null) return AllowedBattle.NOTNOW; // Not checking watchers, return true if (!checkWatcher) return AllowedBattle.YES; // Valid if any watchers say so @@ -372,7 +369,9 @@ public ItemStack getPokemob(final int slot) @Override public LivingEntity getTarget() { - return BrainUtils.getAttackTarget(this.getTrainer()); + final Brain brain = this.user.getBrain(); + if (!brain.hasMemory(MemoryTypes.BATTLETARGET)) return null; + return brain.getMemory(MemoryTypes.BATTLETARGET).get(); } @Override @@ -634,16 +633,19 @@ public void setPokemob(final int slot, final ItemStack cube) } @Override - public void onSetTarget(final LivingEntity target) + public void onSetTarget(final LivingEntity target, final boolean ignoreCanBattle) { final LivingEntity old = this.getTarget(); if (old == target) return; - if (target != null && !this.canBattle(target, true).test()) return; + if (!ignoreCanBattle && target != null && !this.canBattle(target, true).test()) return; final Set watchers = this.getTargetWatchers(); // No next pokemob, so we shouldn't have a target in this case. + final IHasPokemobs oldOther = TrainerCaps.getHasPokemobs(old); + if (oldOther != null) oldOther.onSetTarget(null); + if (target != null && this.getPokemob(0).isEmpty()) { // Notify the watchers that a target was actually set. @@ -652,8 +654,15 @@ public void onSetTarget(final LivingEntity target) this.aiStates.setAIState(IHasNPCAIStates.THROWING, false); this.aiStates.setAIState(IHasNPCAIStates.INBATTLE, false); BrainUtils.deagro(this.getTrainer()); + this.getTrainer().getBrain().removeMemory(MemoryTypes.BATTLETARGET); + this.getTrainer().getBrain().switchTo(Activity.IDLE); return; } + + final IHasPokemobs other = TrainerCaps.getHasPokemobs(target); + System.out.println(other + " " + this.getTrainer().getDisplayName().getFormattedText()); + if (other != null) other.onSetTarget(this.getTrainer(), true); + if (target != null && this.getAttackCooldown() <= 0) { int cooldown = Config.instance.trainerBattleDelay; @@ -687,11 +696,12 @@ public void onSetTarget(final LivingEntity target) { BrainUtils.deagro(this.getTrainer()); this.resetPokemob(); + this.getTrainer().getBrain().removeMemory(MemoryTypes.BATTLETARGET); this.getTrainer().getBrain().switchTo(Activity.IDLE); } else if (this.getTrainer() instanceof MobEntity) { - BrainUtils.initiateCombat((MobEntity) this.getTrainer(), target); + this.getTrainer().getBrain().setMemory(MemoryTypes.BATTLETARGET, target); this.getTrainer().getBrain().switchTo(Activities.BATTLE); } } @@ -753,7 +763,9 @@ public LivingEntity getTrainer() @Override public LivingEntity getTargetRaw() { - return BrainUtils.getAttackTarget(this.getTrainer()); + final Brain brain = this.user.getBrain(); + if (!brain.hasMemory(MemoryTypes.BATTLETARGET)) return null; + return brain.getMemory(MemoryTypes.BATTLETARGET).get(); } @Override @@ -1009,7 +1021,12 @@ default void removeTargetWatcher(final ITargetWatcher watcher) void setPokemob(int slot, ItemStack cube); - void onSetTarget(LivingEntity target); + default void onSetTarget(final LivingEntity target) + { + this.onSetTarget(target, false); + } + + void onSetTarget(LivingEntity target, boolean ignoreCanBattle); void setType(TypeTrainer type); diff --git a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java index fc8f24a41c..3a57a86c2f 100644 --- a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java @@ -16,7 +16,6 @@ import pokecube.adventures.capabilities.CapabilityHasRewards.DefaultRewards; import pokecube.adventures.capabilities.CapabilityNPCAIStates.DefaultAIStates; import pokecube.adventures.capabilities.CapabilityNPCMessages.DefaultMessager; -import pokecube.adventures.capabilities.TrainerCaps; import pokecube.adventures.capabilities.utils.TypeTrainer; import pokecube.adventures.events.TrainerEventHandler; import pokecube.core.items.pokecubes.PokecubeManager; @@ -70,6 +69,7 @@ public boolean addPokemob(final ItemStack mob) @Override public AllowedBattle canBattle(final LivingEntity target) { + if (this.target != null && target != this.target) return AllowedBattle.NOTNOW; return AllowedBattle.YES; } @@ -120,13 +120,10 @@ public void deserializeNBT(final CompoundNBT nbt) } @Override - public void onSetTarget(LivingEntity target) + public void onSetTarget(final LivingEntity target) { - final IHasPokemobs oldBattle = TrainerCaps.getHasPokemobs(this.target); - if (target != null && oldBattle != null && oldBattle.getTargetRaw() == this.player && oldBattle.canBattle( - this.player).test()) return; - final IHasPokemobs targetmobs = TrainerCaps.getHasPokemobs(target); - if (targetmobs == null && target != null || target == this.player) target = null; + System.out.println(target); + if (target == this.target) return; final Set watchers = this.getTargetWatchers(); this.target = target; // Notify the watchers that a target was actually set. @@ -134,12 +131,15 @@ public void onSetTarget(LivingEntity target) watcher.onSet(target); } + @Override + public void onSetTarget(final LivingEntity target, final boolean ignoreCanBattle) + { + this.onSetTarget(target); + } + @Override public LivingEntity getTarget() { - final IHasPokemobs oldBattle = TrainerCaps.getHasPokemobs(this.target); - if (this.target != null && !this.target.isAlive()) this.target = null; - if (oldBattle != null && oldBattle != this && oldBattle.getTargetRaw() != this.player) this.target = null; return this.target; } diff --git a/src/main/java/pokecube/adventures/events/TrainerEventHandler.java b/src/main/java/pokecube/adventures/events/TrainerEventHandler.java index 732cba2ac1..5613d618b5 100644 --- a/src/main/java/pokecube/adventures/events/TrainerEventHandler.java +++ b/src/main/java/pokecube/adventures/events/TrainerEventHandler.java @@ -33,6 +33,7 @@ import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import pokecube.adventures.Config; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.ai.brain.MemoryTypes; import pokecube.adventures.ai.tasks.Tasks; import pokecube.adventures.capabilities.CapabilityHasPokemobs.DefaultPokemobs; import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; @@ -56,7 +57,6 @@ import pokecube.adventures.network.PacketTrainer; import pokecube.adventures.utils.DBLoader; import pokecube.core.PokecubeCore; -import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.npc.Activities; import pokecube.core.ai.routes.IGuardAICapability; import pokecube.core.database.Database; @@ -341,7 +341,8 @@ public static void onNpcTick(final LivingUpdateEvent event) { final LivingEntity npc = event.getEntityLiving(); final Brain brain = npc.getBrain(); - if (!BrainUtils.hasAttackTarget(npc) && brain.hasActivity(Activities.BATTLE)) brain.switchTo(Activity.IDLE); + if (!brain.hasMemory(MemoryTypes.BATTLETARGET) && brain.hasActivity(Activities.BATTLE)) brain.switchTo( + Activity.IDLE); // Add our task if the dummy not present, this can happen if the // brain has reset before if (npc instanceof MobEntity && !brain.sensors.containsKey(Tasks.DUMMY) && npc diff --git a/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java b/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java index c4e8609a82..702eeec58f 100644 --- a/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java +++ b/src/main/java/pokecube/core/ai/tasks/combat/management/FindTargetsTask.java @@ -15,6 +15,8 @@ import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.entity.player.PlayerEntity; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; import pokecube.core.PokecubeCore; import pokecube.core.ai.brain.BrainUtils; import pokecube.core.ai.tasks.TaskBase; @@ -22,9 +24,11 @@ import pokecube.core.interfaces.IMoveConstants.AIRoutine; import pokecube.core.interfaces.IPokemob; import pokecube.core.interfaces.IPokemob.ITargetFinder; +import pokecube.core.interfaces.capabilities.CapabilityPokemob; import pokecube.core.interfaces.pokemob.ai.CombatStates; import pokecube.core.interfaces.pokemob.ai.GeneralStates; import pokecube.core.utils.AITools; +import pokecube.core.utils.PokemobTracker; import thut.api.IOwnable; import thut.api.OwnableCaps; import thut.api.entity.ai.IAICombat; @@ -40,6 +44,27 @@ public class FindTargetsTask extends TaskBase implements IAICombat, I MinecraftForge.EVENT_BUS.register(FindTargetsTask.class); } + @SubscribeEvent + public static void livingSetTarget(final LivingSetAttackTargetEvent event) + { + // Don't manage this. + if (event.getTarget() == null) return; + List mobs = PokemobTracker.getMobs(event.getTarget(), e -> CapabilityPokemob.getPokemobFor(e) != null + && e.getDistanceSq(event.getTarget()) < 64); + final boolean targetHasMobs = !mobs.isEmpty(); + if (targetHasMobs) + { + mobs.sort((o1, o2) -> (int) (o1.getDistanceSq(event.getEntityLiving()) - o2.getDistanceSq(event + .getEntityLiving()))); + final Entity mob = mobs.get(0); + mobs = PokemobTracker.getMobs(mob, e -> true); + // No loop diverting + if (!mobs.isEmpty()) return; + // Divert the target over. + BrainUtils.setAttackTarget(event.getEntityLiving(), (LivingEntity) mob); + } + } + public static int DEAGROTIMER = 50; Vector3 v = Vector3.getNewVector(); From 69ff9c6887b23b45a78f03e8a770cd467378c2b9 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Sat, 23 May 2020 23:20:18 -0400 Subject: [PATCH 25/27] Update PlayerPokemobs.java removes a debug print --- .../pokecube/adventures/capabilities/player/PlayerPokemobs.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java index 3a57a86c2f..df5af27be4 100644 --- a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java @@ -122,7 +122,6 @@ public void deserializeNBT(final CompoundNBT nbt) @Override public void onSetTarget(final LivingEntity target) { - System.out.println(target); if (target == this.target) return; final Set watchers = this.getTargetWatchers(); this.target = target; From d08fdf599fa1c426d71867d66ca58b2f60e7d502 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Sat, 23 May 2020 23:26:22 -0400 Subject: [PATCH 26/27] Update CapabilityHasPokemobs.java fixes a possible loop here --- .../adventures/capabilities/CapabilityHasPokemobs.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java index 7df08604bc..a1a0d8c0cb 100644 --- a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java @@ -636,7 +636,10 @@ public void setPokemob(final int slot, final ItemStack cube) public void onSetTarget(final LivingEntity target, final boolean ignoreCanBattle) { final LivingEntity old = this.getTarget(); + // No calling this if we already have that target. if (old == target) return; + // No calling this if we are the target. + if (target == this.getTrainer()) return; if (!ignoreCanBattle && target != null && !this.canBattle(target, true).test()) return; @@ -660,7 +663,6 @@ public void onSetTarget(final LivingEntity target, final boolean ignoreCanBattle } final IHasPokemobs other = TrainerCaps.getHasPokemobs(target); - System.out.println(other + " " + this.getTrainer().getDisplayName().getFormattedText()); if (other != null) other.onSetTarget(this.getTrainer(), true); if (target != null && this.getAttackCooldown() <= 0) From 74abdcbe8f8959b9f8b5b05002cae5ea56c64019 Mon Sep 17 00:00:00 2001 From: Thutmose Date: Sun, 24 May 2020 00:08:03 -0400 Subject: [PATCH 27/27] adjustments to trainer target forgetting --- .../java/pokecube/adventures/ai/tasks/Tasks.java | 2 +- .../capabilities/CapabilityHasPokemobs.java | 12 +++++------- .../capabilities/player/PlayerPokemobs.java | 7 +++++++ .../java/pokecube/adventures/proxy/CommonProxy.java | 2 ++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/pokecube/adventures/ai/tasks/Tasks.java b/src/main/java/pokecube/adventures/ai/tasks/Tasks.java index 733c81ef1e..cf831f9699 100644 --- a/src/main/java/pokecube/adventures/ai/tasks/Tasks.java +++ b/src/main/java/pokecube/adventures/ai/tasks/Tasks.java @@ -32,7 +32,7 @@ public class Tasks { public static final SensorType DUMMY = new SensorType<>(DummySensor::new); - static + public static void init() { Tasks.DUMMY.setRegistryName(PokecubeAdv.MODID, "dummy_sensor"); } diff --git a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java index a1a0d8c0cb..a5a792c923 100644 --- a/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/CapabilityHasPokemobs.java @@ -10,7 +10,6 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.MobEntity; import net.minecraft.entity.ai.brain.Brain; import net.minecraft.entity.ai.brain.memory.MemoryModuleType; import net.minecraft.entity.ai.brain.schedule.Activity; @@ -646,6 +645,10 @@ public void onSetTarget(final LivingEntity target, final boolean ignoreCanBattle final Set watchers = this.getTargetWatchers(); // No next pokemob, so we shouldn't have a target in this case. + // Set this here, before trying to validate other's target below. + this.getTrainer().getBrain().removeMemory(MemoryTypes.BATTLETARGET); + if (target != null) this.getTrainer().getBrain().setMemory(MemoryTypes.BATTLETARGET, target); + final IHasPokemobs oldOther = TrainerCaps.getHasPokemobs(old); if (oldOther != null) oldOther.onSetTarget(null); @@ -698,14 +701,9 @@ public void onSetTarget(final LivingEntity target, final boolean ignoreCanBattle { BrainUtils.deagro(this.getTrainer()); this.resetPokemob(); - this.getTrainer().getBrain().removeMemory(MemoryTypes.BATTLETARGET); this.getTrainer().getBrain().switchTo(Activity.IDLE); } - else if (this.getTrainer() instanceof MobEntity) - { - this.getTrainer().getBrain().setMemory(MemoryTypes.BATTLETARGET, target); - this.getTrainer().getBrain().switchTo(Activities.BATTLE); - } + else this.getTrainer().getBrain().switchTo(Activities.BATTLE); } @Override diff --git a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java index df5af27be4..1b5b22c9ef 100644 --- a/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java +++ b/src/main/java/pokecube/adventures/capabilities/player/PlayerPokemobs.java @@ -9,6 +9,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.world.dimension.DimensionType; import net.minecraftforge.event.AttachCapabilitiesEvent; import pokecube.adventures.capabilities.CapabilityHasPokemobs.DefaultPokemobs; import pokecube.adventures.capabilities.CapabilityHasPokemobs.IHasPokemobs; @@ -47,6 +48,8 @@ public static void register(final AttachCapabilitiesEvent event) PlayerEntity player; LivingEntity target = null; + long setTargetTime = 0; + public PlayerPokemobs(final PlayerEntity player) { this.player = player; @@ -122,6 +125,8 @@ public void deserializeNBT(final CompoundNBT nbt) @Override public void onSetTarget(final LivingEntity target) { + if (target != null && target.getServer() != null) this.setTargetTime = target.getServer().getWorld( + DimensionType.OVERWORLD).getGameTime(); if (target == this.target) return; final Set watchers = this.getTargetWatchers(); this.target = target; @@ -139,6 +144,8 @@ public void onSetTarget(final LivingEntity target, final boolean ignoreCanBattle @Override public LivingEntity getTarget() { + if (this.target != null && this.target.getServer() != null) if (this.target.getServer().getWorld( + DimensionType.OVERWORLD).getGameTime() - this.setTargetTime > 50) this.target = null; return this.target; } diff --git a/src/main/java/pokecube/adventures/proxy/CommonProxy.java b/src/main/java/pokecube/adventures/proxy/CommonProxy.java index ed14ebc995..d33168d903 100644 --- a/src/main/java/pokecube/adventures/proxy/CommonProxy.java +++ b/src/main/java/pokecube/adventures/proxy/CommonProxy.java @@ -11,6 +11,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import pokecube.adventures.PokecubeAdv; +import pokecube.adventures.ai.tasks.Tasks; import pokecube.adventures.blocks.afa.AfaTile; import pokecube.adventures.blocks.warppad.WarppadTile; import pokecube.adventures.capabilities.CapabilityHasPokemobs; @@ -97,6 +98,7 @@ public void setup(final FMLCommonSetupEvent event) OwnableCaps.TILES.add(WarppadTile.class); PacketTrainer.register(); + Tasks.init(); } @Override