@Override public void onInteract(Entity entity, Action type) { super.onInteract(entity, type); if (type == Action.RIGHT_CLICK && entity.has(HeadComponent.class)) { BlockIterator iterator = entity.get(HeadComponent.class).getBlockView(); if (iterator == null || !iterator.hasNext()) { return; } Block block = iterator.next().translate(BlockFace.TOP); if (this.canPlace(block, (short) 0)) { Cause<Entity> cause; if (entity instanceof Player) { cause = new PlayerBreakCause((Player) entity, block); } else { cause = new EntityCause(entity); } this.onPlacement(block, (short) 0, cause); // TODO Subtract from inventory component // Subtract item if (!entity.getData().get(VanillaData.GAMEMODE).equals(GameMode.SURVIVAL)) { return; } PlayerQuickbar inv = entity.get(PlayerInventory.class).getQuickbar(); if (inv != null) { inv.addAmount(inv.getCurrentSlot(), -1); } } } }
@Override public void onInteract(Entity entity, Action type) { super.onInteract(entity, type); if (type == Action.RIGHT_CLICK && entity.getController() instanceof VanillaPlayerController) { this.open((VanillaPlayerController) entity.getController()); } }
@EventHandler(order = Order.EARLIEST) public void onPlayerJoin(PlayerJoinEvent event) { plugin.getGame().broadcastMessage(event.getPlayer().getName() + " has joined the game"); // Set the player's controller // For now, only create Survival Players Entity playerEntity = event.getPlayer().getEntity(); playerEntity.setController(new SurvivalPlayer(event.getPlayer())); event .getPlayer() .setNetworkSynchronizer(new VanillaNetworkSynchronizer(event.getPlayer(), playerEntity)); /*Point point = playerEntity.getLiveTransform().getPosition(); float pitch = playerEntity.getLiveTransform().getRotation().getAxisAngles().getZ(); float yaw = playerEntity.getLiveTransform().getRotation().getAxisAngles().getY(); //Inform existing players of the new player Message update = new SpawnPlayerMessage(playerEntity.getId(), event.getPlayer().getName(), (int)(point.getX() * 32), (int)(point.getY() * 32), (int)(point.getZ() * 32), (int)(yaw * 256.0F / 360.0F), (int)(pitch * 256.0F / 360.0F), 0); for (Player p : plugin.getGame().getOnlinePlayers()) { if (!p.equals(event.getPlayer())) p.getSession().send(update); }*/ plugin .getGame() .getScheduler() .scheduleSyncDelayedTask(plugin, new LoginRunnable(event.getPlayer()), 1L); }
/** Spawns an entity into the world. Fires off a cancellable EntitySpawnEvent */ @Override public void spawnEntity(Entity e) { if (e.isSpawned()) { throw new IllegalArgumentException("Cannot spawn an entity that is already spawned!"); } SpoutRegion region = (SpoutRegion) e.getRegion(); region.addEntity(e); }
@Override @SuppressWarnings("unchecked") public Minecart spawnEntity(Point position) { Class<? extends Minecart> component = this.getSpawnedComponent(); Entity spawned = position .getWorld() .createAndSpawnEntity(position, LoadOption.NO_LOAD, component, getMinecartType()); return spawned.add(component); }
@Override public Entity getEntity(UUID uid) { for (Region region : regions) { for (Entity e : region.getAll()) { if (e.getUID().equals(uid)) { return e; } } } return null; }
@Override public void onUpdate(BlockMaterial oldMaterial, Block block) { super.onUpdate(oldMaterial, block); if (!block.translate(BlockFace.BOTTOM).getMaterial().isPlacementObstacle()) { // turn this block into a mobile block Entity e = block .getWorld() .createAndSpawnEntity(block.getPosition(), FallingBlock.class, LoadOption.NO_LOAD); e.add(FallingBlock.class).setMaterial(this); block.setMaterial(VanillaMaterials.AIR); } }
@Override public Message[] getUpdateMessage(Entity entity) { List<Parameter<?>> params = this.getSpawnParameters(entity.getController()); if (params != null && params.size() > 0) { Message[] toSend = super.getUpdateMessage(entity); List<Message> msgs = new ArrayList<Message>(Arrays.asList(toSend != null ? toSend : new Message[0])); msgs.add(new EntityMetadataMessage(entity.getId(), params)); return msgs.toArray(new Message[msgs.size()]); } else { return super.getUpdateMessage(entity); } }
public void onDrink(Entity entity, Slot slot) { if (this.effect != null) { entity .add(EffectsComponent.class) .addEffect(new StatusEffectContainer(effect, this.getTime(), this.getTier())); } slot.addAmount(-1); entity .get(PlayerInventory.class) .getMain() .add(new ItemStack(VanillaMaterials.GLASS_BOTTLE, 1)); }
@Override public Message getSpawnMessage(Entity entity) { Controller c = entity.getController(); if (c == null) { return null; } int id = entity.getId(); int x = (int) (entity.getPosition().getX() * 32); int y = (int) (entity.getPosition().getY() * 32); int z = (int) (entity.getPosition().getZ() * 32); // FIXME: Store vehicle type in entity (VehicleEntity implementing?) class instead return new SpawnVehicleMessage(id, this.getSpawnedVehicleType(), x, y, z); }
@EventHandler public Message onExperienceChange(ExperienceChangeEvent event) { Entity entity = event.getEntity(); LevelComponent level = entity.get(LevelComponent.class); if (!(entity instanceof Player)) { return null; } if (level == null) { return null; } return new PlayerExperienceMessage(level.getProgress(), level.getLevel(), event.getNewExp()); }
@Override public Entity getNearestEntity(Point position, Entity ignore, int range) { Entity best = null; double bestDistance = range * range; for (Entity entity : getEntitiesNearRegion(position, range)) { if (entity != null && entity != ignore) { double distance = position.distanceSquared(entity.getScene().getPosition()); if (distance < bestDistance) { bestDistance = distance; best = entity; } } } return best; }
@Override public void onInteract(Entity entity, Block block, Action type, BlockFace clickedface) { super.onInteract(entity, block, type, clickedface); if (type == Action.RIGHT_CLICK) { BlockMaterial clickedmat = block.getMaterial(); if (clickedmat.equals(VanillaMaterials.TNT)) { // Detonate TntBlock VanillaMaterials.TNT.onIgnite(block); return; } else { // Default fire creation Block target = block.translate(clickedface); // Default fire placement clickedface = clickedface.getOpposite(); if (VanillaMaterials.FIRE.canPlace(target, (short) 0)) { if (VanillaMaterials.FIRE.onPlacement(target, (short) 0)) { PlayerQuickbar inv = entity.get(Human.class).getInventory().getQuickbar(); inv.addData(inv.getCurrentSlot(), 1); } } // Handle the creation of portals if (VanillaMaterials.PORTAL.createPortal(target.translate(BlockFace.BOTTOM))) { return; } } } }
@Override public List<Entity> getNearbyEntities(Point position, Entity ignore, int range) { ArrayList<Entity> foundEntities = new ArrayList<Entity>(); final int RANGE_SQUARED = range * range; for (Entity entity : getEntitiesNearRegion(position, range)) { if (entity != null && entity != ignore) { double distance = position.distanceSquared(entity.getScene().getPosition()); if (distance < RANGE_SQUARED) { foundEntities.add(entity); } } } return Collections.unmodifiableList(foundEntities); }
@Override public void setAttachedFace(Block block, BlockFace attachedFace, Cause<?> cause) { if (attachedFace == BlockFace.BOTTOM) { short data = 0; if (cause instanceof EntityCause) { Entity entity = ((EntityCause) cause).getSource(); float yaw = entity.getTransform().getYaw() * -1.0f; float rotation = (yaw + 180F) * 16F / 360F; data = (short) (rotation + 0.5F); data &= 15; } block.setMaterial(VanillaMaterials.SIGN_POST, data, cause); } else { // get the data for this face short data = (short) (BlockFaces.WESN.indexOf(attachedFace, 0) + 2); block.setMaterial(VanillaMaterials.WALL_SIGN, data, cause); } }
/** * Gets the absolute closest player from the specified point within a specified range. * * @param position to search from * @param ignore to ignore while searching * @param range to search * @return nearest player */ @Override @LiveRead @Threadsafe public Player getNearestPlayer(Point position, Player ignore, int range) { Entity best = null; double bestDistance = range * range; for (Entity entity : getEntitiesNearRegion(position, range)) { if (entity != null && entity instanceof Player && entity != ignore) { double distance = position.distanceSquared(entity.getScene().getPosition()); if (distance < bestDistance) { bestDistance = distance; best = entity; } } } return (Player) best; }
@Override public Message[] getSpawnMessage(Entity entity) { Controller c = entity.getController(); if (c != null) { int id = entity.getId(); Vector3 pos = entity.getPosition().multiply(32).floor(); int r = (int) (entity.getYaw() * 32); int p = (int) (entity.getPitch() * 32); int headyaw = 0; if (c instanceof Living) { headyaw = ((Living) c).getHeadYaw(); } List<Parameter<?>> parameters = this.getSpawnParameters(c); return new Message[] { new SpawnMobMessage(id, this.getSpawnID(), pos, r, p, headyaw, parameters) }; } else { return null; } }
/** Spawns an entity into the world. Fires off a cancellable EntitySpawnEvent */ public void spawnEntity(Entity e, int entityID) { if (e.isSpawned()) { throw new IllegalArgumentException("Cannot spawn an entity that is already spawned!"); } SpoutRegion region = (SpoutRegion) e.getRegion(); if (region == null) { throw new IllegalStateException("Cannot spawn an entity that has a null region!"); } if (region.getEntityManager().isSpawnable((SpoutEntity) e)) { if (entityID > -1) { if (getEngine().getPlatform() == Platform.CLIENT) { ((SpoutEntity) e).setId(entityID); } else { throw new IllegalArgumentException("Can not set entity id's manually"); } } EntitySpawnEvent event = getEngine() .getEventManager() .callEvent(new EntitySpawnEvent(e, e.getScene().getPosition())); if (event.isCancelled()) { return; } region.getEntityManager().addEntity((SpoutEntity) e); // Alert world components that an entity entered for (Component component : values()) { if (component instanceof WorldComponent) { ((WorldComponent) component).onSpawn(event); } } // Alert entity components that their owner spawned for (Component component : e.values()) { if (component instanceof EntityComponent) { ((EntityComponent) component).onSpawned(event); } } } else { throw new IllegalStateException("Cannot spawn an entity that already has an id!"); } }
@Override public WorldState generateState() { ArrayList<Entity> entities = new ArrayList<Entity>(); for (Entity entity : agent.getEntity().getWorld().getNearbyEntities(agent.getEntity(), radius)) { boolean hasClass = false; for (Class clazz : classes) { if (entity.get(clazz) != null) { hasClass = true; break; } } if (!hasClass) { continue; } entities.add(entity); } boolean found = entities.size() > 0; state.put("hasNearbyEntities", found); state.put("entities", found ? entities : Collections.emptyList()); return state; }
@Override public void syncEntity( Entity e, Transform liveTransform, boolean spawn, boolean destroy, boolean update) { super.syncEntity(e, liveTransform, spawn, destroy, update); EntityProtocol ep = e.getNetwork().getEntityProtocol(VanillaPlugin.VANILLA_PROTOCOL_ID); if (ep != null) { List<Message> messages = new ArrayList<Message>(); // Sync using vanilla protocol if (destroy) { messages.addAll(ep.getDestroyMessages(e)); } if (spawn) { messages.addAll(ep.getSpawnMessages(e, getRepositionManager())); } if (update) { boolean force = shouldForce(e.getId()); messages.addAll(ep.getUpdateMessages(e, liveTransform, getRepositionManager(), force)); } for (Message message : messages) { this.session.send(false, message); } } }
@Override public void onInteract(Entity entity, Block block, Action type, BlockFace clickedface) { super.onInteract(entity, block, type, clickedface); Block target = block.translate(clickedface); if (target.getMaterial().equals(VanillaMaterials.AIR)) { clickedface = clickedface.getOpposite(); if (VanillaMaterials.FIRE.canPlace(target, (short) 0, clickedface, false)) { if (VanillaMaterials.FIRE.onPlacement(target, (short) 0, clickedface, false)) { Inventory inv = entity.getInventory(); inv.addCurrentItemData(1); } } } }
public int getDamageBonus(Entity damaged, ItemStack heldItem) { // These enchantments conflict with each other, so only one is possible per item int damage = 0; if (Enchantment.hasEnchantment(heldItem, Enchantments.BANE_OF_ARTHROPODS)) { if (damaged.has(Spider.class) || damaged.has(Silverfish.class)) { damage = rand.nextInt( Enchantment.getEnchantmentLevel(heldItem, Enchantments.BANE_OF_ARTHROPODS) * 4); } } else if (Enchantment.hasEnchantment(heldItem, Enchantments.SHARPNESS)) { damage = rand.nextInt(Enchantment.getEnchantmentLevel(heldItem, Enchantments.SHARPNESS) * 3); } else if (Enchantment.hasEnchantment(heldItem, Enchantments.SMITE)) { if (damaged.has(Skeleton.class) || damaged.has(Zombie.class)) { damage = rand.nextInt(Enchantment.getEnchantmentLevel(heldItem, Enchantments.SMITE) * 4); } } // These enchantments must give at least one health point of extra damage if (damage == 0) { damage = 1; } return damage; }
@Override public void syncEntity(Entity e) { if (e == null) { return; } Controller c = e.getController(); if (c != null) { EntityProtocol ep = c.getType().getEntityProtocol(VanillaPlugin.VANILLA_PROTOCOL_ID); if (ep != null) { Message[] sync = ep.getUpdateMessage(e); if (sync != null) { session.sendAll(false, sync); } } } super.syncEntity(e); }
@Override public void destroyEntity(Entity e) { if (e == null) { return; } Controller c = e.getController(); if (c != null) { EntityProtocol ep = c.getType().getEntityProtocol(VanillaPlugin.VANILLA_PROTOCOL_ID); if (ep != null) { Message[] death = ep.getDestroyMessage(e); if (death != null) { session.sendAll(false, death); } } } super.destroyEntity(e); }
@Override public void syncEntity(Entity e, boolean spawn, boolean destroy, boolean update) { EntityProtocol ep = e.getNetwork().getEntityProtocol(VanillaPlugin.VANILLA_PROTOCOL_ID); if (ep != null) { List<Message> messages = new ArrayList<Message>(3); // Sync using vanilla protocol if (destroy) { messages.addAll(ep.getDestroyMessages(e)); } if (spawn) { messages.addAll(ep.getSpawnMessages(e)); } if (update) { messages.addAll(ep.getUpdateMessages(e)); } for (Message message : messages) { this.session.send(false, message); } } }
@Override public List<Message> getSpawnMessages(Entity entity, RepositionManager rm) { FallingBlock block = entity.get(FallingBlock.class); if (block != null) { VanillaBlockMaterial material = block.getMaterial(); int messageData = material.getMinecraftId() | (material.getMinecraftData(material.getData()) >> 16); List<Message> messages = new ArrayList<Message>(); final double p = 32d; Point pos = entity.getScene().getPosition(); int x = (int) Math.floor(pos.getX() * p); int y = (int) Math.floor(pos.getY() * p); int z = (int) Math.floor(pos.getZ() * p); byte yaw = (byte) ChannelBufferUtils.protocolifyYaw(entity.getScene().getRotation().getYaw()); byte pitch = (byte) ChannelBufferUtils.protocolifyPitch(entity.getScene().getRotation().getPitch()); short fallSpeed = (short) (block.getFallingSpeed() * 8000d); messages.add( new EntityObjectMessage( entity.getId(), (byte) typeId, x, y, z, messageData, (short) 0, fallSpeed, (short) 0, yaw, pitch, rm)); messages.add(new EntityMetadataMessage(entity.getId(), getSpawnParameters(entity))); return messages; } else { return Collections.emptyList(); } }
@Override public boolean shouldRun(Entity entity, VanillaActionController controller) { BlockMaterial block = entity.getWorld().getBlock(entity.getPosition()).getMaterial(); return !block.isSolid(); }
@Override public List<Message> getUpdateMessages( Entity entity, Transform liveTransform, RepositionManager rm, boolean force) { // Movement final Transform prevTransform = rm.convert(entity.getScene().getTransform()); final Transform newTransform = rm.convert(liveTransform); final boolean looked = entity.getScene().isRotationDirty(); final int lastX = protocolifyPosition(prevTransform.getPosition().getX()); final int lastY = protocolifyPosition(prevTransform.getPosition().getY()); final int lastZ = protocolifyPosition(prevTransform.getPosition().getZ()); final int lastYaw = protocolifyYaw(prevTransform.getRotation().getYaw()); final int lastPitch = protocolifyPitch(prevTransform.getRotation().getPitch()); final int newX = protocolifyPosition(newTransform.getPosition().getX()); final int newY = protocolifyPosition(newTransform.getPosition().getY()); final int newZ = protocolifyPosition(newTransform.getPosition().getZ()); final int newYaw = protocolifyYaw(newTransform.getRotation().getYaw()); final int newPitch = protocolifyPitch(newTransform.getRotation().getPitch()); final int deltaX = newX - lastX; final int deltaY = newY - lastY; final int deltaZ = newZ - lastZ; final int deltaYaw = newYaw - lastYaw; final int deltaPitch = newPitch - lastPitch; final List<Message> messages = new ArrayList<Message>(); /* * Two scenarios: * - The entity moves more than 4 blocks and maybe changes rotation. * - The entity moves less than 4 blocks and maybe changes rotation. */ if (force || deltaX > 128 || deltaX < -128 || deltaY > 128 || deltaY < -128 || deltaZ > 128 || deltaZ < -128) { messages.add(new EntityTeleportMessage(entity.getId(), newX, newY, newZ, newYaw, newPitch)); if (force || looked) { messages.add(new EntityYawMessage(entity.getId(), newYaw, newPitch)); } } else if (deltaX != 0 || deltaY != 0 || deltaZ != 0 || deltaYaw != 0 || deltaPitch != 0) { if (looked) { messages.add( new EntityRelativePositionYawMessage( entity.getId(), deltaX, deltaY, deltaZ, newYaw, newPitch)); } else if (!prevTransform.getPosition().equals(newTransform.getPosition())) { messages.add(new EntityRelativePositionMessage(entity.getId(), deltaX, deltaY, deltaZ)); } } // Head movement HeadComponent head = entity.get(HeadComponent.class); if (head != null && head.isDirty()) { final int headYawProt = ChannelBufferUtils.protocolifyYaw(head.getRotation().getYaw()); messages.add(new EntityHeadYawMessage(entity.getId(), headYawProt)); } // Physics // TODO: Actually not used? /*if (physics != null && physics.isLinearVelocityDirty()) { messages.add(new EntityVelocityMessage(entity.getId(), new Vector3(0, 0, 0))); }*/ // Extra metadata List<Parameter<?>> params = getUpdateParameters(entity); if (lastMeta == null || !lastMeta.equals(params)) { messages.add(new EntityMetadataMessage(entity.getId(), params)); lastMeta = params; } return messages; }
@Override public final List<Message> getDestroyMessages(Entity entity) { return Arrays.<Message>asList(new EntityDestroyMessage(new int[] {entity.getId()})); }
/** * Gets the absolute closest player from the specified point within a specified range. * * @param entity to search from * @param range to search * @return nearest player */ @Override @LiveRead @Threadsafe public Player getNearestPlayer(Entity entity, int range) { return getNearestPlayer(entity.getScene().getPosition(), range); }