private boolean isNearWater(GlowBlock block) { // check around for some water blocks final GlowWorld world = block.getWorld(); for (int x = block.getX() - 4; x <= block.getX() + 4; x++) { for (int z = block.getZ() - 4; z <= block.getZ() + 4; z++) { for (int y = block.getY(); y <= block.getY() + 1; y++) { final Material type = world.getBlockAt(x, y, z).getType(); if (type == Material.WATER || type == Material.STATIONARY_WATER) { return true; } } } } return false; }
private boolean hasNearVineBlocks(GlowBlock block) { GlowWorld world = block.getWorld(); int vineCount = 0; for (int x = 0; x < 9; x++) { for (int z = 0; z < 9; z++) { for (int y = 0; y < 3; y++) { if (world.getBlockAt(block.getLocation().add(x - 4, y - 1, z - 4)).getType() == Material.VINE) { if (++vineCount >= 5) { return true; } } } } } return false; }
public void writeWorldData() throws IOException { Map<String, Tag> out = new HashMap<String, Tag>(); File uuidFile = new File(dir, "uid.dat"); if (!uuidFile.exists()) { try { uuidFile.createNewFile(); } catch (IOException e) { handleWorldException("uid.dat", e); } } else { UUID uuid = world.getUID(); DataOutputStream str = new DataOutputStream(new FileOutputStream(uuidFile)); str.writeLong(uuid.getLeastSignificantBits()); str.writeLong(uuid.getMostSignificantBits()); str.close(); } out.putAll(unknownTags); unknownTags.clear(); // Normal level data out.put("thundering", new ByteTag("thundering", (byte) (world.isThundering() ? 1 : 0))); out.put("RandomSeed", new LongTag("RandomSeed", world.getSeed())); out.put("Time", new LongTag("Time", world.getTime())); out.put("raining", new ByteTag("raining", (byte) (world.hasStorm() ? 1 : 0))); out.put("thunderTime", new IntTag("thunderTime", world.getThunderDuration())); out.put("rainTime", new IntTag("rainTime", world.getWeatherDuration())); Location loc = world.getSpawnLocation(); out.put("SpawnX", new IntTag("SpawnX", loc.getBlockX())); out.put("SpawnY", new IntTag("SpawnY", loc.getBlockY())); out.put("SpawnZ", new IntTag("SpawnZ", loc.getBlockZ())); // Format-specific out.put("LevelName", new StringTag("LevelName", world.getName())); out.put("LastPlayed", new LongTag("LastPlayed", Calendar.getInstance().getTimeInMillis())); out.put("version", new IntTag("version", 19132)); if (!out.containsKey("SizeOnDisk")) out.put( "SizeOnDisk", new LongTag("SizeOnDisk", 0)); // Not sure how to calculate this, so ignoring for now try { NBTOutputStream nbtOut = new NBTOutputStream(new FileOutputStream(new File(dir, "level.dat"))); nbtOut.writeTag(new CompoundTag("Data", out)); nbtOut.close(); } catch (IOException e) { handleWorldException("level.dat", e); } }
@Override public void blockDestroy(GlowPlayer player, GlowBlock block, BlockFace face) { // vanilla set leaf decay check in a 9x9x9 neighboring when a log block is removed final GlowWorld world = block.getWorld(); for (int x = 0; x < 9; x++) { for (int z = 0; z < 9; z++) { for (int y = 0; y < 9; y++) { final GlowBlock b = world.getBlockAt(block.getLocation().add(x - 4, y - 4, z - 4)); if (b.getType() == Material.LEAVES || b.getType() == Material.LEAVES_2) { final GlowBlockState state = b.getState(); if ((state.getRawData() & 0x08) == 0 && (state.getRawData() & 0x04) == 0) { // check decay is off and decay is on // set decay check on for this leaves block state.setRawData((byte) (state.getRawData() | 0x08)); state.update(true); } } } } } }
public void readPlayerData(GlowPlayer player) { Map<String, Tag> playerData = new HashMap<String, Tag>(); CompoundTag playerTag = null; // Map<PlayerData, Object> ret = new HashMap<PlayerData, Object>(); File playerDir = new File(world.getName(), "players"); if (!playerDir.exists()) playerDir.mkdirs(); File playerFile = new File(playerDir, player.getName() + ".dat"); if (!playerFile.exists()) { try { playerFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } else { try { NBTInputStream in = new NBTInputStream(new FileInputStream(playerFile)); playerTag = (CompoundTag) in.readTag(); in.close(); if (playerTag != null) playerData.putAll(playerTag.getValue()); } catch (EOFException e) { } catch (IOException e) { player.kickPlayer("Failed to read " + player.getName() + ".dat!"); server .getLogger() .severe( "Failed to read player.dat for player " + player.getName() + " in world " + world.getName() + "!"); e.printStackTrace(); } } if (playerTag == null) playerTag = new CompoundTag("", new HashMap<String, Tag>()); EntityStoreLookupService.find(GlowPlayer.class).load(player, playerTag); }
public void writePlayerData(GlowPlayer player) { File playerDir = new File(world.getName(), "players"); if (!playerDir.exists()) playerDir.mkdirs(); File playerFile = new File(playerDir, player.getName() + ".dat"); if (!playerFile.exists()) try { playerFile.createNewFile(); } catch (IOException e) { player.getSession().disconnect("Failed to access player.dat"); server .getLogger() .severe( "Failed to access player.dat for player " + player.getName() + " in world " + world.getName() + "!"); } Map<String, Tag> out = EntityStoreLookupService.find(GlowPlayer.class).save(player); try { NBTOutputStream outStream = new NBTOutputStream(new FileOutputStream(playerFile)); outStream.writeTag(new CompoundTag("", out)); outStream.close(); } catch (IOException e) { player.getSession().disconnect("Failed to write player.dat", true); server .getLogger() .severe( "Failed to write player.dat for player " + player.getName() + " in world " + world.getName() + "!"); } }
public WorldFinalValues readWorldData() throws IOException { Map<String, Tag> level = new HashMap<String, Tag>(); File levelFile = new File(dir, "level.dat"); if (!levelFile.exists()) { try { levelFile.createNewFile(); } catch (IOException e) { handleWorldException("level.dat", e); } } else { try { NBTInputStream in = new NBTInputStream(new FileInputStream(levelFile)); CompoundTag levelTag = (CompoundTag) in.readTag(); in.close(); if (levelTag != null) level.putAll(levelTag.getValue()); } catch (EOFException e) { } catch (IOException e) { handleWorldException("level.dat", e); } } UUID uid = null; File uuidFile = new File(dir, "uid.dat"); if (!uuidFile.exists()) { try { uuidFile.createNewFile(); } catch (IOException e) { handleWorldException("uid.dat", e); } } else { DataInputStream str = null; try { str = new DataInputStream(new FileInputStream(uuidFile)); uid = new UUID(str.readLong(), str.readLong()); } catch (EOFException e) { } finally { if (str != null) { str.close(); } } } long seed = 0L; if (level.containsKey("thundering")) { ByteTag thunderTag = (ByteTag) level.remove("thundering"); world.setThundering(thunderTag.getValue() == 1); } if (level.containsKey("raining")) { ByteTag rainTag = (ByteTag) level.remove("raining"); world.setStorm(rainTag.getValue() == 1); } if (level.containsKey("thunderTime")) { IntTag thunderTimeTag = (IntTag) level.remove("thunderTime"); world.setThunderDuration(thunderTimeTag.getValue()); } if (level.containsKey("rainTime")) { IntTag rainTimeTag = (IntTag) level.remove("rainTime"); world.setWeatherDuration(rainTimeTag.getValue()); } if (level.containsKey("RandomSeed")) { LongTag seedTag = (LongTag) level.remove("RandomSeed"); seed = seedTag.getValue(); } if (level.containsKey("Time")) { LongTag timeTag = (LongTag) level.remove("Time"); world.setTime(timeTag.getValue()); } if (level.containsKey("SpawnX") && level.containsKey("SpawnY") && level.containsKey("SpawnZ")) { IntTag spawnXTag = (IntTag) level.remove("SpawnX"); IntTag spawnYTag = (IntTag) level.remove("SpawnY"); IntTag spawnZTag = (IntTag) level.remove("SpawnZ"); world.setSpawnLocation(spawnXTag.getValue(), spawnYTag.getValue(), spawnZTag.getValue()); } unknownTags.putAll(level); if (uid == null) uid = UUID.randomUUID(); return new WorldFinalValues(seed, uid); }
private void handleWorldException(String file, IOException e) { server.unloadWorld(world, false); server.getLogger().severe("Unable to access " + file + " for world " + world.getName()); e.printStackTrace(); }
@Override public void handle(GlowSession session, DiggingMessage message) { // Todo: Implement SHOOT_ARROW_FINISH_EATING // Todo: Implement SWAP_ITEM_IN_HAND GlowPlayer player = session.getPlayer(); GlowWorld world = player.getWorld(); GlowBlock block = world.getBlockAt(message.getX(), message.getY(), message.getZ()); BlockFace face = BlockPlacementHandler.convertFace(message.getFace()); ItemStack holding = player.getItemInHand(); if (block.getRelative(face).getType() == Material.FIRE) { block.getRelative(face).breakNaturally(); return; // returns to avoid breaking block in creative } boolean blockBroken = false; boolean revert = false; if (message.getState() == DiggingMessage.START_DIGGING || player.getDigging() == null) { // call interact event Action action = Action.LEFT_CLICK_BLOCK; Block eventBlock = block; if (player.getLocation().distanceSquared(block.getLocation()) > 36 || block.getTypeId() == 0) { action = Action.LEFT_CLICK_AIR; eventBlock = null; } PlayerInteractEvent interactEvent = EventFactory.onPlayerInteract(player, action, eventBlock, face); // blocks don't get interacted with on left click, so ignore that // attempt to use item in hand, that is, dig up the block if (!BlockPlacementHandler.selectResult(interactEvent.useItemInHand(), true)) { // the event was cancelled, get out of here revert = true; } else if (player.getGameMode() != GameMode.SPECTATOR) { player.setDigging(null); // emit damage event - cancel by default if holding a sword boolean instaBreak = player.getGameMode() == GameMode.CREATIVE || block.getMaterialValues().getHardness() == 0; BlockDamageEvent damageEvent = new BlockDamageEvent(player, block, player.getItemInHand(), instaBreak); if (player.getGameMode() == GameMode.CREATIVE && holding != null && EnchantmentTarget.WEAPON.includes(holding.getType())) { damageEvent.setCancelled(true); } EventFactory.callEvent(damageEvent); // follow orders if (damageEvent.isCancelled()) { revert = true; } else { // in creative, break even if denied in the event, or the block // can never be broken (client does not send DONE_DIGGING). blockBroken = damageEvent.getInstaBreak(); if (!blockBroken) { /// TODO: add a delay here based on hardness player.setDigging(block); } } } } else if (message.getState() == DiggingMessage.FINISH_DIGGING) { // shouldn't happen in creative mode // todo: verification against malicious clients blockBroken = block.equals(player.getDigging()); if (blockBroken && holding.getType() != Material.AIR && holding.getDurability() != holding.getType().getMaxDurability()) { switch (block.getType()) { case GRASS: case DIRT: case SAND: case GRAVEL: case MYCEL: case SOUL_SAND: switch (holding.getType()) { case WOOD_SPADE: case STONE_SPADE: case IRON_SPADE: case GOLD_SPADE: case DIAMOND_SPADE: holding.setDurability((short) (holding.getDurability() + 1)); break; default: holding.setDurability((short) (holding.getDurability() + 2)); break; } break; case LOG: case LOG_2: case WOOD: case CHEST: switch (holding.getType()) { case WOOD_AXE: case STONE_AXE: case IRON_AXE: case GOLD_AXE: case DIAMOND_AXE: holding.setDurability((short) (holding.getDurability() + 1)); break; default: holding.setDurability((short) (holding.getDurability() + 2)); break; } break; case STONE: case COBBLESTONE: break; default: holding.setDurability((short) (holding.getDurability() + 2)); break; } if (holding.getDurability() >= holding.getType().getMaxDurability()) { player.getInventory().remove(holding); // player.getItemInHand().setType(Material.AIR); } } player.setDigging(null); } else if (message.getState() == DiggingMessage.STATE_DROP_ITEM) { player.dropItemInHand(false); return; } else if (message.getState() == DiggingMessage.STATE_DROP_ITEMSTACK) { player.dropItemInHand(true); return; } else if (message.getState() == DiggingMessage.STATE_SHOT_ARROW_FINISH_EATING && player.getUsageItem() != null) { if (player.getUsageItem().equals(holding)) { ItemType type = ItemTable.instance().getItem(player.getUsageItem().getType()); ((ItemTimedUsage) type).endUse(player, player.getUsageItem()); } else { // todo: verification against malicious clients // todo: inform player their item is wrong } return; } else { return; } if (blockBroken && !revert) { // fire the block break event BlockBreakEvent breakEvent = EventFactory.callEvent(new BlockBreakEvent(block, player)); if (breakEvent.isCancelled()) { BlockPlacementHandler.revert(player, block); return; } BlockType blockType = ItemTable.instance().getBlock(block.getType()); if (blockType != null) { blockType.blockDestroy(player, block, face); } // destroy the block if (!block.isEmpty() && !block.isLiquid() && player.getGameMode() != GameMode.CREATIVE && world.getGameRuleMap().getBoolean("doTileDrops")) { for (ItemStack drop : block.getDrops(holding)) { GlowItem item = world.dropItemNaturally(block.getLocation(), drop); item.setPickupDelay(30); item.setBias(player); } } player.addExhaustion(0.025f); // STEP_SOUND actually is the block break particles world.playEffectExceptTo( block.getLocation(), Effect.STEP_SOUND, block.getTypeId(), 64, player); GlowBlockState state = block.getState(); block.setType(Material.AIR); if (blockType != null) { blockType.afterDestroy(player, block, face, state); } } else if (revert) { // replace the block that wasn't really dug BlockPlacementHandler.revert(player, block); } else if (block.getType() != Material.AIR) { BlockType blockType = ItemTable.instance().getBlock(block.getType()); blockType.leftClickBlock(player, block, holding); } }