package jas.spawner.legacy.spawner.creature.handler; import jas.common.JASLog; import jas.spawner.legacy.EntityProperties; import jas.spawner.legacy.TAGProfile; import jas.spawner.legacy.spawner.creature.entry.SpawnListEntry; import jas.spawner.legacy.spawner.creature.handler.parsing.keys.Key; import jas.spawner.legacy.spawner.creature.handler.parsing.settings.OptionalSettingsDespawning; import jas.spawner.legacy.spawner.creature.handler.parsing.settings.OptionalSettingsPostSpawning; import jas.spawner.legacy.spawner.creature.handler.parsing.settings.OptionalSettingsSpawning; import jas.spawner.legacy.spawner.creature.handler.parsing.settings.OptionalSettings.Operand; import jas.spawner.legacy.spawner.creature.type.CreatureTypeRegistry; import jas.spawner.modern.DefaultProps; import java.io.File; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.MathHelper; import net.minecraftforge.event.ForgeEventFactory; import org.apache.logging.log4j.Level; import cpw.mods.fml.common.eventhandler.Event.Result; public class LivingHandler { public static final String LivingHandlerCategoryComment = "Editable Format: CreatureType" + DefaultProps.DELIMETER + "ShouldSpawn" + "{TAG1:PARAM1,value:PARAM2,value}{TAG2:PARAM1,value:PARAM2,value}"; public final String groupID; public final String creatureTypeID; public final boolean shouldSpawn; public final String optionalParameters; public final CreatureTypeRegistry creatureTypeRegistry; protected OptionalSettingsSpawning spawning; protected OptionalSettingsDespawning despawning; protected OptionalSettingsPostSpawning postspawning; public OptionalSettingsDespawning getDespawning() { return despawning; } public LivingHandler(CreatureTypeRegistry creatureTypeRegistry, LivingHandlerBuilder builder) { this.creatureTypeRegistry = creatureTypeRegistry; this.groupID = builder.getHandlerId(); this.creatureTypeID = creatureTypeRegistry.getCreatureType(builder.getCreatureTypeId()) != null ? builder .getCreatureTypeId() : CreatureTypeRegistry.NONE; this.shouldSpawn = builder.getShouldSpawn(); this.optionalParameters = builder.getOptionalParameters(); for (String string : optionalParameters.split("\\{")) { String parsed = string.replace("}", ""); String titletag = parsed.split("\\:", 2)[0].toLowerCase(); if (Key.spawn.keyParser.isMatch(titletag)) { spawning = new OptionalSettingsSpawning(parsed); } else if (Key.despawn.keyParser.isMatch(titletag)) { despawning = new OptionalSettingsDespawning(parsed); } else if (Key.postspawn.keyParser.isMatch(titletag)) { postspawning = new OptionalSettingsPostSpawning(parsed); } } spawning = spawning == null ? new OptionalSettingsSpawning("") : spawning; despawning = despawning == null ? new OptionalSettingsDespawning("") : despawning; postspawning = postspawning == null ? new OptionalSettingsPostSpawning("") : postspawning; } @Deprecated public LivingHandler(CreatureTypeRegistry creatureTypeRegistry, String livingGroupID, String creatureTypeID, boolean shouldSpawn, String optionalParameters) { this.creatureTypeRegistry = creatureTypeRegistry; this.groupID = livingGroupID; this.creatureTypeID = creatureTypeRegistry.getCreatureType(creatureTypeID) != null ? creatureTypeID : CreatureTypeRegistry.NONE; this.shouldSpawn = shouldSpawn; this.optionalParameters = optionalParameters; for (String string : optionalParameters.split("\\{")) { String parsed = string.replace("}", ""); String titletag = parsed.split("\\:", 2)[0].toLowerCase(); if (Key.spawn.keyParser.isMatch(titletag)) { spawning = new OptionalSettingsSpawning(parsed); } else if (Key.despawn.keyParser.isMatch(titletag)) { despawning = new OptionalSettingsDespawning(parsed); } else if (Key.postspawn.keyParser.isMatch(titletag)) { postspawning = new OptionalSettingsPostSpawning(parsed); } } spawning = spawning == null ? new OptionalSettingsSpawning("") : spawning; despawning = despawning == null ? new OptionalSettingsDespawning("") : despawning; postspawning = postspawning == null ? new OptionalSettingsPostSpawning("") : postspawning; } @Deprecated public final LivingHandler toCreatureTypeID(String creatureTypeID) { return constructInstance(groupID, creatureTypeID, shouldSpawn, optionalParameters); } @Deprecated public final LivingHandler toShouldSpawn(boolean shouldSpawn) { return constructInstance(groupID, creatureTypeID, shouldSpawn, optionalParameters); } @Deprecated public final LivingHandler toOptionalParameters(String optionalParameters) { return constructInstance(groupID, creatureTypeID, shouldSpawn, optionalParameters); } /** * Used internally to create a new Instance of LivingHandler. MUST be Overriden by Subclasses so that they are not * replaced with Parent. Used to Allow subclasses to Include their own Logic, but maintain same data structure. * * Should create a new instance of class using parameters provided in the constructor. * * @param typeID * @param maxNumberOfCreature * @param spawnMedium * @param spawnRate * @param chunkSpawning */ @Deprecated protected LivingHandler constructInstance(String livingGroupID, String creatureTypeID, boolean shouldSpawn, String optionalParameters) { return new LivingHandler(creatureTypeRegistry, livingGroupID, creatureTypeID, shouldSpawn, optionalParameters); } public final int getLivingCap() { Integer cap = spawning.getEntityCap(); return cap != null ? cap : 0; } /** * Replacement Method for EntitySpecific getCanSpawnHere(). Allows Handler to Override Creature functionality. This * both ensures that a Modder can implement their own logic indepenently of the modded creature and that end users * are allowed to customize their experience * * @param entity Entity being Spawned * @param spawnListEntry SpawnListEntry the Entity belongs to * @return True if location is valid For entity to spawn, false otherwise */ public final boolean getCanSpawnHere(EntityLiving entity, SpawnListEntry spawnListEntry) { boolean canLivingSpawn = isValidLiving(entity); boolean canSpawnListSpawn = isValidSpawnList(entity, spawnListEntry); Result canSpawn = ForgeEventFactory.canEntitySpawn(entity, entity.worldObj, (int) entity.posX, (int) entity.posY, (int) entity.posZ); if ((canSpawn == Result.ALLOW || canSpawn == Result.DENY) && !(spawning.isOptionalEnabled() || spawnListEntry.getOptionalSpawning().isOptionalEnabled())) { return canSpawn == Result.ALLOW; } else { if (spawning.getOperand() == Operand.AND || spawnListEntry.getOptionalSpawning().getOperand() == Operand.AND) { return canLivingSpawn && canSpawnListSpawn; } else { return canLivingSpawn || canSpawnListSpawn; } } } /** * Evaluates if this Entity in its current location / state would be capable of despawning eventually */ public final boolean canDespawn(EntityLiving entity) { if (!getDespawning().isOptionalEnabled()) { return LivingHelper.canDespawn(entity); } EntityPlayer entityplayer = entity.worldObj.getClosestPlayerToEntity(entity, -1.0D); int xCoord = MathHelper.floor_double(entity.posX); int yCoord = MathHelper.floor_double(entity.boundingBox.minY); int zCoord = MathHelper.floor_double(entity.posZ); if (entityplayer != null) { double d0 = entityplayer.posX - entity.posX; double d1 = entityplayer.posY - entity.posY; double d2 = entityplayer.posZ - entity.posZ; double d3 = d0 * d0 + d1 * d1 + d2 * d2; boolean canDespawn = !despawning.isInverted(); if (!despawning.isValidLocation(entity.worldObj, entity, xCoord, yCoord, zCoord)) { canDespawn = despawning.isInverted(); } if (canDespawn == false) { return false; } boolean instantDespawn = despawning.isMaxDistance((int) d3, TAGProfile.worldSettings() .worldProperties().getGlobal().maxDespawnDist); if (instantDespawn) { return true; } else { return true; } } return false; } /** * Called by Despawn to Manually Attempt to Despawn Entity * * @param entity */ public final void despawnEntity(EntityLiving entity) { EntityPlayer entityplayer = entity.worldObj.getClosestPlayerToEntity(entity, -1.0D); int xCoord = MathHelper.floor_double(entity.posX); int yCoord = MathHelper.floor_double(entity.boundingBox.minY); int zCoord = MathHelper.floor_double(entity.posZ); LivingHelper.setPersistenceRequired(entity, true); if (entityplayer != null) { double d0 = entityplayer.posX - entity.posX; double d1 = entityplayer.posY - entity.posY; double d2 = entityplayer.posZ - entity.posZ; double d3 = d0 * d0 + d1 * d1 + d2 * d2; EntityProperties entityProps = (EntityProperties) entity .getExtendedProperties(EntityProperties.JAS_PROPERTIES); entityProps.incrementAge(60); boolean canDespawn = !despawning.isInverted(); if (!despawning.isValidLocation(entity.worldObj, entity, xCoord, yCoord, zCoord)) { canDespawn = despawning.isInverted(); } if (canDespawn == false) { entityProps.resetAge(); return; } boolean validDistance = despawning.isMidDistance((int) d3, TAGProfile.worldSettings() .worldProperties().getGlobal().despawnDist); boolean isOfAge = despawning.isValidAge(entityProps.getAge(), TAGProfile.worldSettings() .worldProperties().getGlobal().minDespawnTime); boolean instantDespawn = despawning.isMaxDistance((int) d3, TAGProfile.worldSettings() .worldProperties().getGlobal().maxDespawnDist); if (instantDespawn) { entity.setDead(); } else if (isOfAge && entity.worldObj.rand.nextInt(1 + despawning.getRate() / 3) == 0 && validDistance) { JASLog.log().debug(Level.INFO, "Entity %s is DEAD At Age %s rate %s", entity.getCommandSenderName(), entityProps.getAge(), despawning.getRate()); entity.setDead(); } else if (!validDistance) { entityProps.resetAge(); } } } /** * Represents the 'Modders Choice' for Creature SpawnLocation. * * @param entity * @param spawnType * @return */ protected boolean isValidLocation(EntityLiving entity) { return entity.getCanSpawnHere(); } public final boolean isValidLiving(EntityLiving entity) { if (!spawning.isOptionalEnabled()) { return isValidLocation(entity); } int xCoord = MathHelper.floor_double(entity.posX); int yCoord = MathHelper.floor_double(entity.boundingBox.minY); int zCoord = MathHelper.floor_double(entity.posZ); boolean canLivingSpawn = !spawning.isInverted(); if (!spawning.isValidLocation(entity.worldObj, entity, xCoord, yCoord, zCoord)) { canLivingSpawn = spawning.isInverted(); } return canLivingSpawn && entity.worldObj.checkNoEntityCollision(entity.boundingBox) && entity.worldObj.getCollidingBoundingBoxes(entity, entity.boundingBox).isEmpty(); } public final boolean isValidSpawnList(EntityLiving entity, SpawnListEntry spawnListEntry) { if (!spawnListEntry.getOptionalSpawning().isOptionalEnabled()) { return false; } int xCoord = MathHelper.floor_double(entity.posX); int yCoord = MathHelper.floor_double(entity.boundingBox.minY); int zCoord = MathHelper.floor_double(entity.posZ); boolean canSpawnListSpawn = !spawnListEntry.getOptionalSpawning().isInverted(); if (!spawnListEntry.getOptionalSpawning().isValidLocation(entity.worldObj, entity, xCoord, yCoord, zCoord)) { canSpawnListSpawn = spawnListEntry.getOptionalSpawning().isInverted(); } return canSpawnListSpawn && entity.worldObj.checkNoEntityCollision(entity.boundingBox) && entity.worldObj.getCollidingBoundingBoxes(entity, entity.boundingBox).isEmpty(); } public final void postSpawnEntity(EntityLiving entity, SpawnListEntry spawnListEntry) { if (postspawning.isOptionalEnabled()) { int xCoord = MathHelper.floor_double(entity.posX); int yCoord = MathHelper.floor_double(entity.boundingBox.minY); int zCoord = MathHelper.floor_double(entity.posZ); postspawning.isValidLocation(entity.worldObj, entity, xCoord, yCoord, zCoord); } if (spawnListEntry.getOptionalPostSpawning().isOptionalEnabled()) { int xCoord = MathHelper.floor_double(entity.posX); int yCoord = MathHelper.floor_double(entity.boundingBox.minY); int zCoord = MathHelper.floor_double(entity.posZ); spawnListEntry.getOptionalPostSpawning().isValidLocation(entity.worldObj, entity, xCoord, yCoord, zCoord); } } public static File getFile(File configDirectory, String saveName, String fileName) { String filePath = DefaultProps.MODDIR + DefaultProps.WORLDSETTINGSDIR + saveName + "/" + DefaultProps.ENTITYHANDLERDIR; if (fileName != null && !fileName.equals("")) { filePath = filePath.concat(fileName).concat(".cfg"); } return new File(configDirectory, filePath); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } LivingHandler other = (LivingHandler) obj; return groupID.equals(other.groupID); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((groupID == null) ? 0 : groupID.hashCode()); return result; } }