package com.bergerkiller.bukkit.common.events; import java.util.ArrayList; import java.util.List; import net.minecraft.server.BiomeMeta; import net.minecraft.server.Entity; import org.bukkit.World; import org.bukkit.entity.EntityType; import com.bergerkiller.bukkit.common.collections.InstanceBuffer; import com.bergerkiller.bukkit.common.entity.CommonEntityType; import com.bergerkiller.bukkit.common.internal.CommonNMS; import com.bergerkiller.bukkit.common.reflection.FieldAccessor; import com.bergerkiller.bukkit.common.reflection.SafeField; import com.bergerkiller.bukkit.common.utils.CommonUtil; import com.bergerkiller.bukkit.common.utils.LogicUtil; import com.bergerkiller.bukkit.common.utils.WorldUtil; /** * Processes server happenings and raises events accordingly */ public class CommonEventFactory { private final EntityMoveEvent entityMoveEvent = new EntityMoveEvent(); private final List<Entity> entityMoveEntities = new ArrayList<Entity>(); private final CreaturePreSpawnEvent creaturePreSpawnEvent = new CreaturePreSpawnEvent(); private final FieldAccessor<Integer> biomeMetaChance = new SafeField<Integer>(BiomeMeta.class, "a"); private final InstanceBuffer<BiomeMeta> creaturePreSpawnMobs = new InstanceBuffer<BiomeMeta>() { @Override public BiomeMeta createElement() { return new BiomeMeta(null, 0, 0, 0); } }; /** * Fires Entity Move events for all entities that moved on the server */ public void handleEntityMove() { if (!CommonUtil.hasHandlers(EntityMoveEvent.getHandlerList())) { return; } for (World world : WorldUtil.getWorlds()) { entityMoveEntities.addAll(CommonNMS.getEntities(world)); } for (Entity entity : entityMoveEntities) { if (entity.locX != entity.lastX || entity.locY != entity.lastY || entity.locZ != entity.lastZ || entity.yaw != entity.lastYaw || entity.pitch != entity.lastPitch) { entityMoveEvent.setEntity(entity); CommonUtil.callEvent(entityMoveEvent); } } entityMoveEntities.clear(); } /** * Handles the spawning of creatures on the server * * @param world * @param x * @param y * @param z * @param inputTypes to process and fire events for * @return a list of mobs to spawn */ public List<BiomeMeta> handleCreaturePreSpawn(World world, int x, int y, int z, List<BiomeMeta> inputTypes) { // Shortcuts if (LogicUtil.nullOrEmpty(inputTypes) || !CommonUtil.hasHandlers(CreaturePreSpawnEvent.getHandlerList())) { return inputTypes; } // Start processing the elements creaturePreSpawnMobs.clear(); for (BiomeMeta inputMeta : inputTypes) { final EntityType oldEntityType = CommonEntityType.byNMSEntityClass(inputMeta.b).entityType; // Set up the event creaturePreSpawnEvent.cancelled = false; creaturePreSpawnEvent.spawnLocation.setWorld(world); creaturePreSpawnEvent.spawnLocation.setX(x); creaturePreSpawnEvent.spawnLocation.setY(y); creaturePreSpawnEvent.spawnLocation.setZ(z); creaturePreSpawnEvent.spawnLocation.setYaw(0.0f); creaturePreSpawnEvent.spawnLocation.setPitch(0.0f); creaturePreSpawnEvent.entityType = oldEntityType; creaturePreSpawnEvent.minSpawnCount = inputMeta.c; creaturePreSpawnEvent.maxSpawnCount = inputMeta.d; // Raise it and handle spawn cancel if (CommonUtil.callEvent(creaturePreSpawnEvent).isCancelled() || (creaturePreSpawnEvent.minSpawnCount == 0 && creaturePreSpawnEvent.maxSpawnCount == 0)) { continue; } // Handle a possibly changed entity type final Class<?> entityClass; if (oldEntityType == creaturePreSpawnEvent.entityType) { entityClass = inputMeta.b; } else { entityClass = CommonEntityType.byEntityType(creaturePreSpawnEvent.entityType).nmsType.getType(); // Unknown or unsupported Entity Type - ignore spawning if (entityClass == null) { continue; } } // Add element to buffer final BiomeMeta outputMeta = creaturePreSpawnMobs.add(); outputMeta.b = entityClass; outputMeta.c = creaturePreSpawnEvent.minSpawnCount; outputMeta.d = creaturePreSpawnEvent.maxSpawnCount; biomeMetaChance.transfer(inputMeta, outputMeta); } return creaturePreSpawnMobs; } }