Added schematic loading and pasting.

Player can create an island using /island create
Only the default island is supported right now. No GUI.
Uses NMS to paste. Only supported on 1.12.
This commit is contained in:
tastybento 2017-06-10 16:08:21 -07:00
parent 2a9ddd6579
commit dcda604e6c
51 changed files with 6391 additions and 498 deletions

1
lib/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/spigot-1.12.jar

View File

@ -8,4 +8,20 @@ depend: [Vault]
softdepend: [Herochat, DeluxeChat, PlaceholderAPI, MVdWPlaceholderAPI] softdepend: [Herochat, DeluxeChat, PlaceholderAPI, MVdWPlaceholderAPI]
load: startup load: startup
loadbefore: [Multiverse-Core] loadbefore: [Multiverse-Core]
commands:
island:
description: Main player command
aliases: [is, island]
usage: |
/island help
asadmin:
description: Admin commands
usage: |
/asadmin
asc:
description: Game challenges
aliases: [c, challenge, aschallenge, challenges]
usage: |
/challenge

View File

@ -9,6 +9,7 @@
<description>The next generation of ASkyBlock</description> <description>The next generation of ASkyBlock</description>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<server.jars>${project.basedir}/lib</server.jars>
</properties> </properties>
<build> <build>
<defaultGoal>clean package install</defaultGoal> <defaultGoal>clean package install</defaultGoal>
@ -72,6 +73,13 @@
<artifactId>VaultAPI</artifactId> <artifactId>VaultAPI</artifactId>
<version>LATEST</version> <version>LATEST</version>
</dependency> </dependency>
<dependency>
<groupId>spigotmc.org</groupId>
<artifactId>spigot-1.12</artifactId>
<scope>system</scope>
<systemPath>${server.jars}/spigot-1.12.jar</systemPath>
<version>1.12</version>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>
<repository> <repository>

BIN
schematics/double.schematic Normal file

Binary file not shown.

BIN
schematics/harder.schematic Normal file

Binary file not shown.

BIN
schematics/island.schematic Normal file

Binary file not shown.

BIN
schematics/nether.schematic Normal file

Binary file not shown.

View File

@ -3,10 +3,13 @@ package us.tastybento.bskyblock;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import us.tastybento.bskyblock.commands.IslandCommand;
import us.tastybento.bskyblock.config.BSBLocale; import us.tastybento.bskyblock.config.BSBLocale;
import us.tastybento.bskyblock.config.PluginConfig; import us.tastybento.bskyblock.config.PluginConfig;
import us.tastybento.bskyblock.config.Settings; import us.tastybento.bskyblock.config.Settings;
@ -15,6 +18,7 @@ import us.tastybento.bskyblock.database.managers.IslandsManager;
import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages; import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages;
import us.tastybento.bskyblock.database.managers.PlayersManager; import us.tastybento.bskyblock.database.managers.PlayersManager;
import us.tastybento.bskyblock.generators.IslandWorld; import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.schematics.SchematicsMgr;
import us.tastybento.bskyblock.util.VaultHelper; import us.tastybento.bskyblock.util.VaultHelper;
/** /**
@ -31,6 +35,9 @@ public class BSkyBlock extends JavaPlugin{
private PlayersManager playersManager; private PlayersManager playersManager;
private IslandsManager islandsManager; private IslandsManager islandsManager;
private OfflineHistoryMessages offlineHistoryMessages; private OfflineHistoryMessages offlineHistoryMessages;
// Schematics
private SchematicsMgr schematicsManager;
// Metrics // Metrics
private Metrics metrics; private Metrics metrics;
@ -67,6 +74,8 @@ public class BSkyBlock extends JavaPlugin{
getLogger().warning("Could not set up economy! - Running without an economy."); getLogger().warning("Could not set up economy! - Running without an economy.");
Settings.useEconomy = false; Settings.useEconomy = false;
} }
VaultHelper.setupPermissions();
// These items have to be loaded when the server has done 1 tick. // These items have to be loaded when the server has done 1 tick.
// Note Worlds are not loaded this early, so any Locations or World reference will be null // Note Worlds are not loaded this early, so any Locations or World reference will be null
@ -117,6 +126,12 @@ public class BSkyBlock extends JavaPlugin{
playersManager.load(); playersManager.load();
islandsManager.load(); islandsManager.load();
// Load schematics
Settings.chestItems = new ItemStack[] {new ItemStack(Material.LAVA_BUCKET,1)};
schematicsManager = new SchematicsMgr(plugin);
getCommand("island").setExecutor(new IslandCommand(plugin));
/* /*
*DEBUG CODE *DEBUG CODE
Island loadedIsland = islandsManager.getIsland(owner); Island loadedIsland = islandsManager.getIsland(owner);
@ -260,4 +275,16 @@ public class BSkyBlock extends JavaPlugin{
public IslandsManager getIslands(){ public IslandsManager getIslands(){
return islandsManager; return islandsManager;
} }
public static BSkyBlock getPlugin() {
return plugin;
}
/**
* @return the schematics
*/
public SchematicsMgr getSchematics() {
return schematicsManager;
}
} }

View File

@ -3,6 +3,7 @@ package us.tastybento.bskyblock.config;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import org.bukkit.block.Biome;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -18,7 +19,36 @@ import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages.HistoryM
public class Settings { public class Settings {
/* The settings variables should follow the config order */ /* The settings variables should follow the config order */
public static final String PERMPREFIX = "bskyblock.";
// Constants
// Game Type BSKYBLOCK or ACIDISLAND
public enum GameType {
BSKYBLOCK, ACIDISLAND
}
/*
public final static GameType GAMETYPE = GameType.ACIDISLAND;
// The spawn command (Essentials spawn for example)
public final static String SPAWNCOMMAND = "spawn";
// Permission prefix
public final static String PERMPREFIX = "acidisland.";
// The island command
public final static String ISLANDCOMMAND = "ai";
// The challenge command
public static final String CHALLENGECOMMAND = "aic";
// Admin command
public static final String ADMINCOMMAND = "acid";
*/
public final static GameType GAMETYPE = GameType.BSKYBLOCK;
// Permission prefix
public final static String PERMPREFIX = "bskyblock.";
// The island command
public final static String ISLANDCOMMAND = "island";
// The challenge command
public static final String CHALLENGECOMMAND = "asc";
// The spawn command (Essentials spawn for example)
public final static String SPAWNCOMMAND = "spawn";
// Admin command
public static final String ADMINCOMMAND = "asadmin";
/* GENERAL */ /* GENERAL */
public static boolean metrics; public static boolean metrics;
@ -149,9 +179,13 @@ public class Settings {
public static boolean acidFullArmorProtection; public static boolean acidFullArmorProtection;
/* SCHEMATICS */ /* SCHEMATICS */
public static EntityType companionType;
public static List<String> companionNames; public static List<String> companionNames;
public static List<ItemStack> chestItems; public static ItemStack[] chestItems;
public static Biome defaultBiome;
public static boolean usePhysics;
public static EntityType companionType;
public static boolean useSchematicPanel;
public static boolean chooseIslandRandomly;
// TODO added this just to avoid compilation errors, but will be changed in the future // TODO added this just to avoid compilation errors, but will be changed in the future
public static List<HistoryMessageType> historyMessagesTypes; public static List<HistoryMessageType> historyMessagesTypes;
@ -173,4 +207,11 @@ public class Settings {
public static boolean createEnd; public static boolean createEnd;
public static boolean islandEnd; public static boolean islandEnd;
public static boolean resetMoney;
public static double acidDamage;
public static int islandXOffset;
public static int islandStartX;
public static int islandZOffset;
public static int islandStartZ;
} }

View File

@ -1,6 +1,5 @@
package us.tastybento.bskyblock.database.managers; package us.tastybento.bskyblock.database.managers;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -8,12 +7,31 @@ import java.util.TreeMap;
import java.util.UUID; import java.util.UUID;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.material.SimpleAttachableMaterialData;
import org.bukkit.material.TrapDoor;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.util.Vector;
import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings; import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.BSBDatabase; import us.tastybento.bskyblock.database.BSBDatabase;
import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.schematics.Schematic;
import us.tastybento.bskyblock.schematics.Schematic.PasteReason;
import us.tastybento.bskyblock.util.SafeSpotTeleport;
import us.tastybento.bskyblock.util.Util;
/** /**
* The job of this class is manage all island related data. * The job of this class is manage all island related data.
@ -40,6 +58,7 @@ public class IslandsManager {
// Metrics data // Metrics data
private int metrics_createdcount = 0; private int metrics_createdcount = 0;
private AbstractDatabaseHandler<Island> handler; private AbstractDatabaseHandler<Island> handler;
private Location last;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public IslandsManager(BSkyBlock plugin){ public IslandsManager(BSkyBlock plugin){
@ -352,4 +371,512 @@ public class IslandsManager {
} }
return false; return false;
} }
/**
* This teleports player to their island. If not safe place can be found
* then the player is sent to spawn via /spawn command
*
* @param player
* @return true if the home teleport is successful
*/
public boolean homeTeleport(final Player player) {
return homeTeleport(player, 1);
}
/**
* Teleport player to a home location. If one cannot be found a search is done to
* find a safe place.
* @param player
* @param number - home location to do to
* @return true if successful, false if not
*/
public boolean homeTeleport(final Player player, int number) {
Location home = null;
//plugin.getLogger().info("home teleport called for #" + number);
home = getSafeHomeLocation(player.getUniqueId(), number);
//plugin.getLogger().info("home get safe loc = " + home);
// Check if the player is a passenger in a boat
if (player.isInsideVehicle()) {
Entity boat = player.getVehicle();
if (boat instanceof Boat) {
player.leaveVehicle();
// Remove the boat so they don't lie around everywhere
boat.remove();
player.getInventory().addItem(new ItemStack(Material.BOAT, 1));
player.updateInventory();
}
}
if (home == null) {
//plugin.getLogger().info("Fixing home location using safe spot teleport");
// Try to fix this teleport location and teleport the player if possible
new SafeSpotTeleport(plugin, player, plugin.getPlayers().getHomeLocation(player.getUniqueId(), number), number);
return true;
}
//plugin.getLogger().info("DEBUG: home loc = " + home + " teleporting");
//home.getChunk().load();
player.teleport(home);
//player.sendBlockChange(home, Material.GLOWSTONE, (byte)0);
if (number ==1 ) {
Util.sendMessage(player, ChatColor.GREEN + "Teleported");
} else {
Util.sendMessage(player, ChatColor.GREEN + "teleported to #" + number);
}
return true;
}
/**
* Determines a safe teleport spot on player's island or the team island
* they belong to.
*
* @param playerUUID UUID of player
* @param number - starting home location e.g., 1
* @return Location of a safe teleport spot or null if one cannot be found
*/
public Location getSafeHomeLocation(final UUID playerUUID, int number) {
// Try the numbered home location first
Location l = plugin.getPlayers().getHomeLocation(playerUUID, number);
if (l == null) {
// Get the default home, which may be null too, but that's okay
number = 1;
l = plugin.getPlayers().getHomeLocation(playerUUID, number);
}
// Check if it is safe
//plugin.getLogger().info("DEBUG: Home location " + l);
if (l != null) {
// Homes are stored as integers and need correcting to be more central
if (isSafeLocation(l)) {
return l.clone().add(new Vector(0.5D,0,0.5D));
}
// To cover slabs, stairs and other half blocks, try one block above
Location lPlusOne = l.clone();
lPlusOne.add(new Vector(0, 1, 0));
if (lPlusOne != null) {
if (isSafeLocation(lPlusOne)) {
// Adjust the home location accordingly
plugin.getPlayers().setHomeLocation(playerUUID, lPlusOne, number);
return lPlusOne.clone().add(new Vector(0.5D,0,0.5D));
}
}
}
//plugin.getLogger().info("DEBUG: Home location either isn't safe, or does not exist so try the island");
// Home location either isn't safe, or does not exist so try the island
// location
if (plugin.getPlayers().inTeam(playerUUID)) {
l = plugin.getIslands().getIslandLocation(playerUUID);
if (isSafeLocation(l)) {
plugin.getPlayers().setHomeLocation(playerUUID, l, number);
return l.clone().add(new Vector(0.5D,0,0.5D));
} else {
// try team leader's home
Location tlh = plugin.getPlayers().getHomeLocation(plugin.getIslands().getTeamLeader(playerUUID));
if (tlh != null) {
if (isSafeLocation(tlh)) {
plugin.getPlayers().setHomeLocation(playerUUID, tlh, number);
return tlh.clone().add(new Vector(0.5D,0,0.5D));
}
}
}
} else {
l = plugin.getIslands().getIslandLocation(playerUUID);
if (isSafeLocation(l)) {
plugin.getPlayers().setHomeLocation(playerUUID, l, number);
return l.clone().add(new Vector(0.5D,0,0.5D));
}
}
if (l == null) {
plugin.getLogger().warning(plugin.getPlayers().getName(playerUUID) + " player has no island!");
return null;
}
//plugin.getLogger().info("DEBUG: If these island locations are not safe, then we need to get creative");
// If these island locations are not safe, then we need to get creative
// Try the default location
//plugin.getLogger().info("DEBUG: default");
Location dl = new Location(l.getWorld(), l.getX() + 0.5D, l.getY() + 5D, l.getZ() + 2.5D, 0F, 30F);
if (isSafeLocation(dl)) {
plugin.getPlayers().setHomeLocation(playerUUID, dl, number);
return dl;
}
// Try just above the bedrock
//plugin.getLogger().info("DEBUG: above bedrock");
dl = new Location(l.getWorld(), l.getX() + 0.5D, l.getY() + 5D, l.getZ() + 0.5D, 0F, 30F);
if (isSafeLocation(dl)) {
plugin.getPlayers().setHomeLocation(playerUUID, dl, number);
return dl;
}
// Try all the way up to the sky
//plugin.getLogger().info("DEBUG: try all the way to the sky");
for (int y = l.getBlockY(); y < 255; y++) {
final Location n = new Location(l.getWorld(), l.getX() + 0.5D, y, l.getZ() + 0.5D);
if (isSafeLocation(n)) {
plugin.getPlayers().setHomeLocation(playerUUID, n, number);
return n;
}
}
//plugin.getLogger().info("DEBUG: unsuccessful");
// Unsuccessful
return null;
}
/**
* This is a generic scan that can work in the overworld or the nether
* @param l - location around which to scan
* @param i - the range to scan for a location < 0 means the full island.
* @return - safe location, or null if none can be found
*/
public Location bigScan(Location l, int i) {
final int height;
final int depth;
if (i > 0) {
height = i;
depth = i;
} else {
Island island = getIslandAt(l);
if (island == null) {
return null;
}
i = island.getProtectionRange();
height = l.getWorld().getMaxHeight() - l.getBlockY();
depth = l.getBlockY();
}
//plugin.getLogger().info("DEBUG: ranges i = " + i);
//plugin.getLogger().info(" " + minX + "," + minZ + " " + maxX + " " + maxZ);
//plugin.getLogger().info("DEBUG: height = " + height);
//plugin.getLogger().info("DEBUG: depth = " + depth);
//plugin.getLogger().info("DEBUG: trying to find a safe spot at " + l.toString());
// Work outwards from l until the closest safe location is found.
int minXradius = 0;
int maxXradius = 0;
int minZradius = 0;
int maxZradius = 0;
int minYradius = 0;
int maxYradius = 0;
do {
int minX = l.getBlockX()-minXradius;
int minZ = l.getBlockZ()-minZradius;
int minY = l.getBlockY()-minYradius;
int maxX = l.getBlockX()+maxXradius;
int maxZ = l.getBlockZ()+maxZradius;
int maxY = l.getBlockY()+maxYradius;
for (int x = minX; x<= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
if (!((x > minX && x < maxX) && (z > minZ && z < maxZ) && (y > minY && y < maxY))) {
//plugin.getLogger().info("DEBUG: checking " + x + "," + y + "," + z);
Location ultimate = new Location(l.getWorld(), x + 0.5D, y, z + 0.5D);
if (isSafeLocation(ultimate)) {
//plugin.getLogger().info("DEBUG: Found! " + ultimate);
return ultimate;
}
}
}
}
}
if (minXradius < i) {
minXradius++;
}
if (maxXradius < i) {
maxXradius++;
}
if (minZradius < i) {
minZradius++;
}
if (maxZradius < i) {
maxZradius++;
}
if (minYradius < depth) {
minYradius++;
}
if (maxYradius < height) {
maxYradius++;
}
//plugin.getLogger().info("DEBUG: Radii " + minXradius + "," + minYradius + "," + minZradius +
// "," + maxXradius + "," + maxYradius + "," + maxZradius);
} while (minXradius < i || maxXradius < i || minZradius < i || maxZradius < i || minYradius < depth
|| maxYradius < height);
// Nothing worked
return null;
}
/**
* Checks if this location is safe for a player to teleport to. Used by
* warps and boat exits Unsafe is any liquid or air and also if there's no
* space
*
* @param l
* - Location to be checked
* @return true if safe, otherwise false
*/
public static boolean isSafeLocation(final Location l) {
if (l == null) {
return false;
}
// TODO: improve the safe location finding.
//Bukkit.getLogger().info("DEBUG: " + l.toString());
final Block ground = l.getBlock().getRelative(BlockFace.DOWN);
final Block space1 = l.getBlock();
final Block space2 = l.getBlock().getRelative(BlockFace.UP);
//Bukkit.getLogger().info("DEBUG: ground = " + ground.getType());
//Bukkit.getLogger().info("DEBUG: space 1 = " + space1.getType());
//Bukkit.getLogger().info("DEBUG: space 2 = " + space2.getType());
// Portals are not "safe"
if (space1.getType() == Material.PORTAL || ground.getType() == Material.PORTAL || space2.getType() == Material.PORTAL
|| space1.getType() == Material.ENDER_PORTAL || ground.getType() == Material.ENDER_PORTAL || space2.getType() == Material.ENDER_PORTAL) {
return false;
}
// If ground is AIR, then this is either not good, or they are on slab,
// stair, etc.
if (ground.getType() == Material.AIR) {
// Bukkit.getLogger().info("DEBUG: air");
return false;
}
// In BSkyBlock, liquid may be unsafe
if (ground.isLiquid() || space1.isLiquid() || space2.isLiquid()) {
// Check if acid has no damage
if (Settings.acidDamage > 0D) {
// Bukkit.getLogger().info("DEBUG: acid");
return false;
} else if (ground.getType().equals(Material.STATIONARY_LAVA) || ground.getType().equals(Material.LAVA)
|| space1.getType().equals(Material.STATIONARY_LAVA) || space1.getType().equals(Material.LAVA)
|| space2.getType().equals(Material.STATIONARY_LAVA) || space2.getType().equals(Material.LAVA)) {
// Lava check only
// Bukkit.getLogger().info("DEBUG: lava");
return false;
}
}
MaterialData md = ground.getState().getData();
if (md instanceof SimpleAttachableMaterialData) {
//Bukkit.getLogger().info("DEBUG: trapdoor/button/tripwire hook etc.");
if (md instanceof TrapDoor) {
TrapDoor trapDoor = (TrapDoor)md;
if (trapDoor.isOpen()) {
//Bukkit.getLogger().info("DEBUG: trapdoor open");
return false;
}
} else {
return false;
}
//Bukkit.getLogger().info("DEBUG: trapdoor closed");
}
if (ground.getType().equals(Material.CACTUS) || ground.getType().equals(Material.BOAT) || ground.getType().equals(Material.FENCE)
|| ground.getType().equals(Material.NETHER_FENCE) || ground.getType().equals(Material.SIGN_POST) || ground.getType().equals(Material.WALL_SIGN)) {
// Bukkit.getLogger().info("DEBUG: cactus");
return false;
}
// Check that the space is not solid
// The isSolid function is not fully accurate (yet) so we have to
// check
// a few other items
// isSolid thinks that PLATEs and SIGNS are solid, but they are not
if (space1.getType().isSolid() && !space1.getType().equals(Material.SIGN_POST) && !space1.getType().equals(Material.WALL_SIGN)) {
return false;
}
if (space2.getType().isSolid()&& !space2.getType().equals(Material.SIGN_POST) && !space2.getType().equals(Material.WALL_SIGN)) {
return false;
}
// Safe
//Bukkit.getLogger().info("DEBUG: safe!");
return true;
}
/**
* Makes an island using schematic. No permission checks are made. They have to be decided
* before this method is called.
* @param player
* @param schematic
*/
public void newIsland(final Player player, final Schematic schematic) {
//long time = System.nanoTime();
final UUID playerUUID = player.getUniqueId();
boolean firstTime = false;
if (!plugin.getPlayers().hasIsland(playerUUID)) {
firstTime = true;
}
//plugin.getLogger().info("DEBUG: finding island location");
Location next = getNextIsland(player.getUniqueId());
//plugin.getLogger().info("DEBUG: found " + next);
// Clear any old home locations (they should be clear, but just in case)
plugin.getPlayers().clearHomeLocations(playerUUID);
// Set the biome
//BiomesPanel.setIslandBiome(next, schematic.getBiome());
// Teleport to the new home
if (schematic.isPlayerSpawn()) {
// Set home and teleport
plugin.getPlayers().setHomeLocation(playerUUID, schematic.getPlayerSpawn(next), 1);
}
// Create island based on schematic
if (schematic != null) {
//plugin.getLogger().info("DEBUG: pasting schematic " + schematic.getName() + " " + schematic.getPerm());
//plugin.getLogger().info("DEBUG: nether world is " + BSkyBlock.getNetherWorld());
// Paste the starting island. If it is a HELL biome, then we start in the Nether
if (Settings.createNether && schematic.isInNether() && Settings.islandNether && IslandWorld.getNetherWorld() != null) {
// Nether start
// Paste the overworld if it exists
if (!schematic.getPartnerName().isEmpty()) {
// A partner schematic is available
pastePartner(plugin.getSchematics().getSchematic(schematic.getPartnerName()),next, player);
}
// Switch home location to the Nether
next = next.toVector().toLocation(IslandWorld.getNetherWorld());
// Set the player's island location to this new spot
//plugin.getPlayers().setIslandLocation(playerUUID, next);
schematic.pasteSchematic(next, player, true, firstTime ? PasteReason.NEW_ISLAND: PasteReason.RESET);
} else {
// Over world start
//plugin.getLogger().info("DEBUG: pasting");
//long timer = System.nanoTime();
// Paste the island and teleport the player home
schematic.pasteSchematic(next, player, true, firstTime ? PasteReason.NEW_ISLAND: PasteReason.RESET);
//double diff = (System.nanoTime() - timer)/1000000;
//plugin.getLogger().info("DEBUG: nano time = " + diff + " ms");
//plugin.getLogger().info("DEBUG: pasted overworld");
if (Settings.createNether && Settings.islandNether && IslandWorld.getNetherWorld() != null) {
// Paste the other world schematic
final Location netherLoc = next.toVector().toLocation(IslandWorld.getNetherWorld());
if (schematic.getPartnerName().isEmpty()) {
// This will paste the over world schematic again
//plugin.getLogger().info("DEBUG: pasting nether");
pastePartner(schematic, netherLoc, player);
//plugin.getLogger().info("DEBUG: pasted nether");
} else {
if (plugin.getSchematics().getAll().containsKey(schematic.getPartnerName())) {
//plugin.getLogger().info("DEBUG: pasting partner");
// A partner schematic is available
pastePartner(plugin.getSchematics().getAll().get(schematic.getPartnerName()),netherLoc, player);
} else {
plugin.getLogger().severe("Partner schematic heading '" + schematic.getPartnerName() + "' does not exist");
}
}
}
}
}
// Add to the grid
Island myIsland = plugin.getIslands().createIsland(next, playerUUID);
myIsland.setLevelHandicap(schematic.getLevelHandicap());
// Save the player so that if the server is reset weird things won't happen
plugin.getPlayers().save(true);
// Start the reset cooldown
//if (!firstTime) {
// setResetWaitTime(player);
//}
// Set the custom protection range if appropriate
// Dynamic island range sizes with permissions
int range = Settings.islandProtectionRange;
for (PermissionAttachmentInfo perms : player.getEffectivePermissions()) {
if (perms.getPermission().startsWith(Settings.PERMPREFIX + "island.range.")) {
if (perms.getPermission().contains(Settings.PERMPREFIX + "island.range.*")) {
range = Settings.islandProtectionRange;
break;
} else {
String[] spl = perms.getPermission().split(Settings.PERMPREFIX + "island.range.");
if (spl.length > 1) {
if (!NumberUtils.isDigits(spl[1])) {
plugin.getLogger().severe("Player " + player.getName() + " has permission: " + perms.getPermission() + " <-- the last part MUST be a number! Ignoring...");
} else {
range = Math.max(range, Integer.valueOf(spl[1]));
}
}
}
}
}
// Do some sanity checking
if (range % 2 != 0) {
range--;
plugin.getLogger().warning("Protection range must be even, using " + range + " for " + player.getName());
}
if (range > Settings.islandDistance) {
plugin.getLogger().warning("Player has " + Settings.PERMPREFIX + "island.range." + range);
range = Settings.islandDistance;
plugin.getLogger().warning(
"Island protection range must be " + Settings.islandDistance + " or less. Setting to: " + range);
}
myIsland.setProtectionRange(range);
// Save grid just in case there's a crash
plugin.getIslands().save(true);
// Done - fire event
//final IslandNewEvent event = new IslandNewEvent(player,schematic, myIsland);
//plugin.getServer().getPluginManager().callEvent(event);
//plugin.getLogger().info("DEBUG: Done! " + (System.nanoTime()- time) * 0.000001);
}
/**
* Does a delayed pasting of the partner island
* @param schematic
* @param player
*/
private void pastePartner(final Schematic schematic, final Location loc, final Player player) {
plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
schematic.pasteSchematic(loc, player, false, PasteReason.PARTNER);
}}, 60L);
}
/**
* Get the location of next free island spot
* @param playerUUID
* @return Location of island spot
*/
private Location getNextIsland(UUID playerUUID) {
// Find the next free spot
if (last == null) {
last = new Location(IslandWorld.getIslandWorld(), Settings.islandXOffset + Settings.islandStartX, Settings.islandHeight, Settings.islandZOffset + Settings.islandStartZ);
}
Location next = last.clone();
while (plugin.getIslands().isIsland(next)) {
next = nextGridLocation(next);
}
// Make the last next, last
last = next.clone();
return next;
}
/**
* Finds the next free island spot based off the last known island Uses
* island_distance setting from the config file Builds up in a grid fashion
*
* @param lastIsland
* @return Location of next free island
*/
private Location nextGridLocation(final Location lastIsland) {
// plugin.getLogger().info("DEBUG nextIslandLocation");
final int x = lastIsland.getBlockX();
final int z = lastIsland.getBlockZ();
final Location nextPos = lastIsland;
if (x < z) {
if (-1 * x < z) {
nextPos.setX(nextPos.getX() + Settings.islandDistance);
return nextPos;
}
nextPos.setZ(nextPos.getZ() + Settings.islandDistance);
return nextPos;
}
if (x > z) {
if (-1 * x >= z) {
nextPos.setX(nextPos.getX() - Settings.islandDistance);
return nextPos;
}
nextPos.setZ(nextPos.getZ() - Settings.islandDistance);
return nextPos;
}
if (x <= 0) {
nextPos.setZ(nextPos.getZ() + Settings.islandDistance);
return nextPos;
}
nextPos.setZ(nextPos.getZ() - Settings.islandDistance);
return nextPos;
}
} }

View File

@ -1,6 +1,8 @@
package us.tastybento.bskyblock.database.managers; package us.tastybento.bskyblock.database.managers;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Location; import org.bukkit.Location;
@ -19,6 +21,7 @@ public class PlayersManager{
private BSBDatabase database; private BSBDatabase database;
private HashMap<UUID, Players> playerCache; private HashMap<UUID, Players> playerCache;
private Set<UUID> inTeleport;
/** /**
* Provides a memory cache of online player information * Provides a memory cache of online player information
@ -31,6 +34,7 @@ public class PlayersManager{
this.plugin = plugin; this.plugin = plugin;
database = BSBDatabase.getDatabase(); database = BSBDatabase.getDatabase();
playerCache = new HashMap<UUID, Players>(); playerCache = new HashMap<UUID, Players>();
inTeleport = new HashSet<UUID>();
} }
public void load(){ public void load(){
@ -488,4 +492,38 @@ public class PlayersManager{
return playerCache.get(playerUUID).getDeaths(); return playerCache.get(playerUUID).getDeaths();
} }
/**
* Sets if a player is mid-teleport or not
* @param uniqueId
*/
public void setInTeleport(UUID uniqueId) {
inTeleport.add(uniqueId);
}
/**
* Removes player from in-teleport
* @param uniqueId
*/
public void removeInTeleport(UUID uniqueId) {
inTeleport.remove(uniqueId);
}
/**
* @param uniqueId
* @return true if a player is mid-teleport
*/
public boolean isInTeleport(UUID uniqueId) {
return inTeleport.contains(uniqueId);
}
/**
* Resets everything to do with a player that needs to be reset
* @param player
*/
public void resetPlayer(Player player) {
// TODO Auto-generated method stub
}
} }

View File

@ -349,6 +349,8 @@ public class Island extends DataObject {
//// Protection //// //// Protection ////
private HashMap<SettingsFlag, Boolean> flags = new HashMap<SettingsFlag, Boolean>(); private HashMap<SettingsFlag, Boolean> flags = new HashMap<SettingsFlag, Boolean>();
private int levelHandicap;
public Island() {}; public Island() {};
public Island(Location location, UUID owner, int protectionRange) { public Island(Location location, UUID owner, int protectionRange) {
@ -817,4 +819,18 @@ public class Island extends DataObject {
} }
} }
/**
* @return the levelHandicap
*/
public int getLevelHandicap() {
return levelHandicap;
}
/**
* @param levelHandicap the levelHandicap to set
*/
public void setLevelHandicap(int levelHandicap) {
this.levelHandicap = levelHandicap;
}
} }

View File

@ -0,0 +1,156 @@
/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ASkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.schematics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.DyeColor;
import org.bukkit.block.Banner;
import org.bukkit.block.Block;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import us.tastybento.org.jnbt.CompoundTag;
import us.tastybento.org.jnbt.IntTag;
import us.tastybento.org.jnbt.ListTag;
import us.tastybento.org.jnbt.StringTag;
import us.tastybento.org.jnbt.Tag;
/**
* This class describes banners and is used in schematic importing
*
* @author tastybento
*
*/
public class BannerBlock {
private DyeColor bannerBaseColor;
private List<Pattern> bannerPattern;
private static HashMap<String, PatternType> patternKey;
// bs, mc, cr, drs, dls, hhb, mr, hh, sc, gru, ss, gra, ts, ms, tt
// bts, tr, tts, sku, cre, tl, vhr, vh, bo, cbo, bri
// ss, tt
static {
patternKey = new HashMap<String, PatternType>();
patternKey.put("", PatternType.BASE);
patternKey.put("bo", PatternType.BORDER);
patternKey.put("bri", PatternType.BRICKS);
patternKey.put("mc", PatternType.CIRCLE_MIDDLE);
patternKey.put("cre", PatternType.CREEPER);
patternKey.put("cr", PatternType.CROSS);
patternKey.put("cbo", PatternType.CURLY_BORDER);
patternKey.put("ld", PatternType.DIAGONAL_LEFT);
patternKey.put("lud", PatternType.DIAGONAL_LEFT_MIRROR);
patternKey.put("rd", PatternType.DIAGONAL_RIGHT);
patternKey.put("rud", PatternType.DIAGONAL_RIGHT_MIRROR);
patternKey.put("flo", PatternType.FLOWER);
patternKey.put("gra", PatternType.GRADIENT);
patternKey.put("gru", PatternType.GRADIENT_UP);
patternKey.put("hh", PatternType.HALF_HORIZONTAL);
patternKey.put("hhb", PatternType.HALF_HORIZONTAL_MIRROR);
patternKey.put("vh", PatternType.HALF_VERTICAL);
patternKey.put("vhr", PatternType.HALF_VERTICAL_MIRROR);
patternKey.put("moj", PatternType.MOJANG);
patternKey.put("mr", PatternType.RHOMBUS_MIDDLE);
patternKey.put("sku", PatternType.SKULL);
patternKey.put("bl", PatternType.SQUARE_BOTTOM_LEFT);
patternKey.put("br", PatternType.SQUARE_BOTTOM_RIGHT);
patternKey.put("tl", PatternType.SQUARE_TOP_LEFT);
patternKey.put("tr", PatternType.SQUARE_TOP_RIGHT);
patternKey.put("sc", PatternType.STRAIGHT_CROSS);
patternKey.put("bs", PatternType.STRIPE_BOTTOM);
patternKey.put("ms", PatternType.STRIPE_CENTER);
patternKey.put("dls", PatternType.STRIPE_DOWNLEFT);
patternKey.put("drs", PatternType.STRIPE_DOWNRIGHT);
patternKey.put("ls", PatternType.STRIPE_LEFT);
patternKey.put("ms", PatternType.STRIPE_MIDDLE);
patternKey.put("rs", PatternType.STRIPE_RIGHT);
patternKey.put("ss", PatternType.STRIPE_SMALL);
patternKey.put("ts", PatternType.STRIPE_TOP);
patternKey.put("bt", PatternType.TRIANGLE_BOTTOM);
patternKey.put("tt", PatternType.TRIANGLE_TOP);
patternKey.put("bts", PatternType.TRIANGLES_BOTTOM);
patternKey.put("tts", PatternType.TRIANGLES_TOP);
}
public boolean set(Block block) {
Banner banner = (Banner) block.getState();
banner.setBaseColor(bannerBaseColor);
banner.setPatterns(bannerPattern);
banner.update();
return true;
}
@SuppressWarnings("deprecation")
public boolean prep(Map<String, Tag> tileData) {
// Format for banner is:
// Patterns = List of patterns
// id = String "BannerBlock"
// Base = Int color
// Then the location
// z = Int
// y = Int
// x = Int
try {
// Do the base color
int baseColor = 15 - ((IntTag) tileData.get("Base")).getValue();
// //ASkyBlock.getPlugin().getLogger().info("Base value = " +
// baseColor);
// baseColor green = 10
bannerBaseColor = DyeColor.getByDyeData((byte) baseColor);
// Do the patterns (no idea if this will work or not)
bannerPattern = new ArrayList<Pattern>();
ListTag patterns = (ListTag) tileData.get("Patterns");
if (patterns != null) {
for (Tag pattern : patterns.getValue()) {
// ASkyBlock.getPlugin().getLogger().info("pattern = " +
// pattern);
// Translate pattern to PatternType
if (pattern instanceof CompoundTag) {
CompoundTag patternColor = (CompoundTag) pattern;
// The tag is made up of pattern (String) and color
// (int)
Map<String, Tag> patternValue = patternColor.getValue();
StringTag mark = (StringTag) patternValue.get("Pattern");
Integer markColor = 15 - ((IntTag) patternValue.get("Color")).getValue();
// ASkyBlock.getPlugin().getLogger().info("mark = " +
// mark.getValue());
// ASkyBlock.getPlugin().getLogger().info("color = " +
// markColor);
DyeColor dColor = DyeColor.getByDyeData(markColor.byteValue());
// ASkyBlock.getPlugin().getLogger().info(" dye color = "
// + dColor.toString());
if (patternKey.containsKey(mark.getValue())) {
Pattern newPattern = new Pattern(dColor, patternKey.get(mark.getValue()));
bannerPattern.add(newPattern);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}

View File

@ -0,0 +1,364 @@
/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ASkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.schematics;
import org.bukkit.entity.EntityType;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
public class EntityObject {
private EntityType type;
private BlockVector location;
private byte color;
private float yaw;
private float pitch;
private boolean sheared;
private Vector motion;
private int age;
private int rabbitType;
private int catType;
private boolean sitting;
private int profession;
private boolean carryingChest;
private boolean owned;
private byte collarColor;
// Paintings
private byte facing;
private String motive;
// Item Frames
private float itemDropChance;
private byte itemRotation;
// Coordinates for tiles
private Double tileX = null;
private Double tileY = null;
private Double tileZ = null;
// Items informations
private Byte count = null;
private Short damage = null;
private String id = null;
/**
* @return the type
*/
public EntityType getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(EntityType type) {
this.type = type;
}
/**
* @return the location
*/
public BlockVector getLocation() {
return location;
}
/**
* @param location the location to set
*/
public void setLocation(BlockVector location) {
this.location = location;
}
/**
* @return the color
*/
public byte getColor() {
return color;
}
/**
* @param color the color to set
*/
public void setColor(byte color) {
this.color = color;
}
/**
* @return the yaw
*/
public float getYaw() {
return yaw;
}
/**
* @param yaw the yaw to set
*/
public void setYaw(float yaw) {
this.yaw = yaw;
}
/**
* @return the pitch
*/
public float getPitch() {
return pitch;
}
/**
* @param pitch
*/
public void setPitch(float pitch) {
this.pitch = pitch;
}
/**
* @return the sheared
*/
public boolean isSheared() {
return sheared;
}
/**
* @param sheared the sheared to set
*/
public void setSheared(boolean sheared) {
this.sheared = sheared;
}
/**
* @return the motion
*/
public Vector getMotion() {
return motion;
}
/**
* @param motion the motion to set
*/
public void setMotion(Vector motion) {
this.motion = motion;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
/**
* @return the profession
*/
public int getProfession() {
return profession;
}
/**
* @param profession the profession to set
*/
public void setProfession(int profession) {
this.profession = profession;
}
/**
* @return the rabbitType
*/
public int getRabbitType() {
return rabbitType;
}
/**
* @param rabbitType the rabbitType to set
*/
public void setRabbitType(int rabbitType) {
this.rabbitType = rabbitType;
}
/**
* @return the carryingChest
*/
public boolean isCarryingChest() {
return carryingChest;
}
/**
* @param carryingChest the carryingChest to set
*/
public void setCarryingChest(byte carryingChest) {
if (carryingChest > (byte)0) {
this.carryingChest = true;
}
this.carryingChest = false;
}
/**
* @return the catType
*/
public int getCatType() {
return catType;
}
/**
* @param catType the catType to set
*/
public void setCatType(int catType) {
this.catType = catType;
}
/**
* @return the sitting
*/
public boolean isSitting() {
return sitting;
}
/**
* @param sitting the sitting to set
*/
public void setSitting(byte sitting) {
if (sitting > (byte)0) {
this.sitting = true;
}
this.sitting = false;
}
/**
* @return the owned
*/
public boolean isOwned() {
return owned;
}
/**
* @param owned the owned to set
*/
public void setOwned(boolean owned) {
this.owned = owned;
}
/**
* @return the collarColor
*/
public byte getCollarColor() {
return collarColor;
}
/**
* @param collarColor the collarColor to set
*/
public void setCollarColor(byte collarColor) {
this.collarColor = collarColor;
}
/**
* @return the facing
*/
public byte getFacing() {
return facing;
}
/**
* @param facing the facing to set
*/
public void setFacing(byte facing) {
this.facing = facing;
}
/**
* @return the motive
*/
public String getMotive() {
return motive;
}
/**
* @param motive the motive to set
*/
public void setMotive(String motive) {
this.motive = motive;
}
/**
* @return the itemDropChance
*/
public float getItemDropChance() {
return itemDropChance;
}
/**
* @param itemDropChance the itemDropChance to set
*/
public void setItemDropChance(float itemDropChance) {
this.itemDropChance = itemDropChance;
}
/**
* @return the itemRotation
*/
public byte getItemRotation() {
return itemRotation;
}
/**
* @param itemRotation the itemRotation to set
*/
public void setItemRotation(byte itemRotation) {
this.itemRotation = itemRotation;
}
/**
* @return the tileX
*/
public Double getTileX() {
return tileX;
}
/**
* @param tileX the tileX to set
*/
public void setTileX(Double tileX) {
this.tileX = tileX;
}
/**
* @return the tileX
*/
public Double getTileY() {
return tileY;
}
/**
* @param tileY the tileY to set
*/
public void setTileY(Double tileY) {
this.tileY = tileY;
}
/**
* @return the tileX
*/
public Double getTileZ() {
return tileZ;
}
/**
* @param tileZ the tileZ to set
*/
public void setTileZ(Double tileZ) {
this.tileZ = tileZ;
}
/**
* @return the count
*/
public Byte getCount() {
return count;
}
/**
* @param count the count to set
*/
public void setCount(Byte count) {
this.count = count;
}
/**
* @return the damage
*/
public Short getDamage() {
return damage;
}
/**
* @param damage the damage to set
*/
public void setDamage(Short damage) {
this.damage = damage;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
}

View File

@ -0,0 +1,600 @@
/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ASkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.schematics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.Chest;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.DoubleChest;
import org.bukkit.block.Sign;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import org.json.simple.JSONValue;
import org.json.simple.parser.ContainerFactory;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
import us.tastybento.org.jnbt.CompoundTag;
import us.tastybento.org.jnbt.ListTag;
import us.tastybento.org.jnbt.StringTag;
import us.tastybento.org.jnbt.Tag;
public class IslandBlock {
private short typeId;
private byte data;
private int x;
private int y;
private int z;
private List<String> signText;
private BannerBlock banner;
private SkullBlock skull;
private PotBlock pot;
private EntityType spawnerBlockType;
// Chest contents
private HashMap<Byte,ItemStack> chestContents = new HashMap<Byte,ItemStack>();
public static final HashMap<String, Material> WEtoM = new HashMap<String, Material>();
public static final HashMap<String, EntityType> WEtoME = new HashMap<String, EntityType>();
static {
// Establish the World Edit to Material look up
// V1.8 items
if (!Bukkit.getServer().getVersion().contains("(MC: 1.7")) {
WEtoM.put("ARMORSTAND",Material.ARMOR_STAND);
WEtoM.put("ACACIA_DOOR",Material.ACACIA_DOOR_ITEM);
WEtoM.put("BIRCH_DOOR",Material.BIRCH_DOOR_ITEM);
WEtoM.put("BIRCH_STAIRS",Material.BIRCH_WOOD_STAIRS);
WEtoM.put("DARK_OAK_DOOR",Material.DARK_OAK_DOOR_ITEM);
WEtoM.put("JUNGLE_DOOR",Material.JUNGLE_DOOR_ITEM);
WEtoM.put("SLIME",Material.SLIME_BLOCK);
WEtoM.put("SPRUCE_DOOR",Material.SPRUCE_DOOR_ITEM);
}
WEtoM.put("BREWING_STAND",Material.BREWING_STAND_ITEM);
WEtoM.put("CARROT_ON_A_STICK",Material.CARROT_STICK);
WEtoM.put("CARROT",Material.CARROT_ITEM);
WEtoM.put("CAULDRON", Material.CAULDRON_ITEM);
WEtoM.put("CLOCK", Material.WATCH);
WEtoM.put("COBBLESTONE_WALL",Material.COBBLE_WALL);
WEtoM.put("COMMAND_BLOCK",Material.COMMAND);
WEtoM.put("COMMANDBLOCK_MINECART",Material.COMMAND_MINECART);
WEtoM.put("COMPARATOR",Material.REDSTONE_COMPARATOR);
WEtoM.put("COOKED_PORKCHOP", Material.GRILLED_PORK);
WEtoM.put("CLOCK", Material.WATCH);
WEtoM.put("CRAFTING_TABLE", Material.WORKBENCH);
WEtoM.put("DIAMOND_HORSE_ARMOR",Material.DIAMOND_BARDING);
WEtoM.put("DIAMOND_SHOVEL",Material.DIAMOND_SPADE);
WEtoM.put("DYE",Material.INK_SACK);
WEtoM.put("ENCHANTING_TABLE", Material.ENCHANTMENT_TABLE); //1.11 rename
WEtoM.put("END_PORTAL_FRAME",Material.ENDER_PORTAL_FRAME);
WEtoM.put("END_PORTAL", Material.ENDER_PORTAL); // 1.11 rename
WEtoM.put("END_STONE", Material.ENDER_STONE);
WEtoM.put("EXPERIENCE_BOTTLE",Material.EXP_BOTTLE);
WEtoM.put("FILLED_MAP",Material.MAP);
WEtoM.put("FIRE_CHARGE",Material.FIREBALL);
WEtoM.put("FIREWORKS",Material.FIREWORK);
WEtoM.put("FLOWER_POT", Material.FLOWER_POT_ITEM);
WEtoM.put("GLASS_PANE",Material.THIN_GLASS);
WEtoM.put("GOLDEN_CHESTPLATE",Material.GOLD_CHESTPLATE);
WEtoM.put("GOLDEN_HORSE_ARMOR",Material.GOLD_BARDING);
WEtoM.put("GOLDEN_LEGGINGS",Material.GOLD_LEGGINGS);
WEtoM.put("GOLDEN_PICKAXE",Material.GOLD_PICKAXE);
WEtoM.put("GOLDEN_RAIL",Material.POWERED_RAIL);
WEtoM.put("GOLDEN_SHOVEL",Material.GOLD_SPADE);
WEtoM.put("GOLDEN_SWORD", Material.GOLD_SWORD);
WEtoM.put("GOLDEN_HELMET", Material.GOLD_HELMET);
WEtoM.put("GOLDEN_HOE", Material.GOLD_HOE);
WEtoM.put("GOLDEN_AXE", Material.GOLD_AXE);
WEtoM.put("GOLDEN_BOOTS", Material.GOLD_BOOTS);
WEtoM.put("GUNPOWDER", Material.SULPHUR);
WEtoM.put("HARDENED_CLAY",Material.HARD_CLAY);
WEtoM.put("HEAVY_WEIGHTED_PRESSURE_PLATE",Material.GOLD_PLATE);
WEtoM.put("IRON_BARS",Material.IRON_FENCE);
WEtoM.put("IRON_HORSE_ARMOR",Material.IRON_BARDING);
WEtoM.put("IRON_SHOVEL",Material.IRON_SPADE);
WEtoM.put("LEAD",Material.LEASH);
WEtoM.put("LEAVES2",Material.LEAVES_2);
WEtoM.put("LIGHT_WEIGHTED_PRESSURE_PLATE",Material.IRON_PLATE);
WEtoM.put("LOG2",Material.LOG_2);
WEtoM.put("MAP",Material.EMPTY_MAP);
WEtoM.put("MYCELIUM", Material.MYCEL);
WEtoM.put("NETHER_BRICK_FENCE",Material.NETHER_FENCE);
WEtoM.put("NETHER_WART",Material.NETHER_STALK);
WEtoM.put("NETHERBRICK",Material.NETHER_BRICK_ITEM);
WEtoM.put("OAK_STAIRS",Material.WOOD_STAIRS);
WEtoM.put("POTATO", Material.POTATO_ITEM);
WEtoM.put("RAIL",Material.RAILS);
WEtoM.put("RECORD_11",Material.RECORD_11);
WEtoM.put("RECORD_13",Material.GOLD_RECORD);
WEtoM.put("RECORD_BLOCKS",Material.RECORD_3);
WEtoM.put("RECORD_CAT",Material.GREEN_RECORD);
WEtoM.put("RECORD_CHIRP",Material.RECORD_4);
WEtoM.put("RECORD_FAR",Material.RECORD_5);
WEtoM.put("RECORD_MALL",Material.RECORD_6);
WEtoM.put("RECORD_MELLOHI",Material.RECORD_7);
WEtoM.put("RECORD_STAL",Material.RECORD_8);
WEtoM.put("RECORD_STRAD",Material.RECORD_9);
WEtoM.put("RECORD_WAIT",Material.RECORD_12);
WEtoM.put("RECORD_WARD",Material.RECORD_10);
WEtoM.put("RED_FLOWER",Material.RED_ROSE);
WEtoM.put("REEDS",Material.SUGAR_CANE);
WEtoM.put("REPEATER",Material.DIODE);
WEtoM.put("SKULL", Material.SKULL_ITEM);
WEtoM.put("SPAWN_EGG",Material.MONSTER_EGG);
WEtoM.put("STONE_BRICK_STAIRS",Material.BRICK_STAIRS);
WEtoM.put("STONE_BRICK_STAIRS",Material.SMOOTH_STAIRS);
WEtoM.put("STONE_SHOVEL",Material.STONE_SPADE);
WEtoM.put("STONE_SLAB",Material.STEP);
WEtoM.put("STONE_STAIRS",Material.COBBLESTONE_STAIRS);
WEtoM.put("TNT_MINECART",Material.EXPLOSIVE_MINECART);
WEtoM.put("WATERLILY",Material.WATER_LILY);
WEtoM.put("WHEAT_SEEDS", Material.SEEDS);
WEtoM.put("WOODEN_AXE",Material.WOOD_AXE);
WEtoM.put("WOODEN_BUTTON",Material.WOOD_BUTTON);
WEtoM.put("WOODEN_DOOR",Material.WOOD_DOOR);
WEtoM.put("WOODEN_HOE",Material.WOOD_HOE);
WEtoM.put("WOODEN_PICKAXE",Material.WOOD_PICKAXE);
WEtoM.put("WOODEN_PRESSURE_PLATE",Material.WOOD_PLATE);
WEtoM.put("WOODEN_SHOVEL",Material.WOOD_SPADE);
WEtoM.put("WOODEN_SLAB",Material.WOOD_STEP);
WEtoM.put("WOODEN_SWORD",Material.WOOD_SWORD);
WEtoM.put("MUSHROOM_STEW",Material.MUSHROOM_SOUP);
// Entities
WEtoME.put("LAVASLIME", EntityType.MAGMA_CUBE);
WEtoME.put("ENTITYHORSE", EntityType.HORSE);
WEtoME.put("OZELOT", EntityType.OCELOT);
WEtoME.put("MUSHROOMCOW", EntityType.MUSHROOM_COW);
WEtoME.put("MOOSHROOM", EntityType.MUSHROOM_COW); // 1.11 rename
WEtoME.put("PIGZOMBIE", EntityType.PIG_ZOMBIE);
WEtoME.put("ZOMBIE_PIGMAN", EntityType.PIG_ZOMBIE); // 1.11 rename
WEtoME.put("CAVESPIDER", EntityType.CAVE_SPIDER);
WEtoME.put("XPORB", EntityType.EXPERIENCE_ORB);
WEtoME.put("XP_ORB", EntityType.EXPERIENCE_ORB); // 1.11 rename
WEtoME.put("MINECARTRIDEABLE", EntityType.MINECART);
WEtoME.put("MINECARTHOPPER", EntityType.MINECART_HOPPER);
WEtoME.put("HOPPER_MINECART", EntityType.MINECART_HOPPER);
WEtoME.put("MINECARTFURNACE", EntityType.MINECART_FURNACE);
WEtoME.put("FURNACE_MINECART", EntityType.MINECART_FURNACE);
WEtoME.put("MINECARTMOBSPAWNER", EntityType.MINECART_MOB_SPAWNER);
WEtoME.put("SPAWNER_MINECART", EntityType.MINECART_MOB_SPAWNER); // 1.11 rename
WEtoME.put("MINECARTTNT", EntityType.MINECART_TNT);
WEtoME.put("TNT_MINECART", EntityType.MINECART_TNT); // 1.11
WEtoME.put("LEASH_KNOT",EntityType.LEASH_HITCH); // 1.11
WEtoME.put("MINECARTCHEST", EntityType.MINECART_CHEST);
WEtoME.put("CHEST_MINECART", EntityType.MINECART_CHEST); //1.11 rename
WEtoME.put("VILLAGERGOLEM", EntityType.IRON_GOLEM);
WEtoME.put("ENDERDRAGON", EntityType.ENDER_DRAGON);
WEtoME.put("PAINTING", EntityType.PAINTING);
WEtoME.put("ITEMFRAME", EntityType.ITEM_FRAME);
if (!Bukkit.getServer().getVersion().contains("(MC: 1.7")) {
WEtoME.put("ENDERCRYSTAL", EntityType.ENDER_CRYSTAL);
WEtoME.put("ARMORSTAND", EntityType.ARMOR_STAND);
}
// 1.10 entities and materials
if (!Bukkit.getServer().getVersion().contains("(MC: 1.7") && !Bukkit.getServer().getVersion().contains("(MC: 1.8") && !Bukkit.getServer().getVersion().contains("(MC: 1.9")) {
WEtoME.put("POLARBEAR", EntityType.POLAR_BEAR);
WEtoM.put("ENDER_CRYSTAL", Material.END_CRYSTAL); // 1.11
}
}
/**
* @param x
* @param y
* @param z
*/
public IslandBlock(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
signText = null;
banner = null;
skull = null;
pot = null;
spawnerBlockType = null;
chestContents = new HashMap<Byte,ItemStack>();
}
/**
* @return the type
*/
public int getTypeId() {
return typeId;
}
/**
* @param type the type to set
*/
public void setTypeId(short type) {
this.typeId = type;
}
/**
* @return the data
*/
public int getData() {
return data;
}
/**
* @param data the data to set
*/
public void setData(byte data) {
this.data = data;
}
/**
* @return the signText
*/
public List<String> getSignText() {
return signText;
}
/**
* @param signText the signText to set
*/
public void setSignText(List<String> signText) {
this.signText = signText;
}
/**
* @param s
* @param b
*/
public void setBlock(int s, byte b) {
this.typeId = (short)s;
this.data = b;
}
/**
* Sets this block up with all the banner data required
* @param map
*/
public void setBanner(Map<String, Tag> map) {
banner = new BannerBlock();
banner.prep(map);
}
/**
* Sets this block up with all the skull data required
* @param map
* @param dataValue
*/
public void setSkull(Map<String, Tag> map, int dataValue) {
skull = new SkullBlock();
skull.prep(map, dataValue);
}
public void setFlowerPot(Map<String, Tag> map){
pot = new PotBlock();
pot.prep(map);
}
/**
* Sets the spawner type if this block is a spawner
* @param tileData
*/
public void setSpawnerType(Map<String, Tag> tileData) {
//Bukkit.getLogger().info("DEBUG: " + tileData.toString());
String creatureType = "";
if (tileData.containsKey("EntityId")) {
creatureType = ((StringTag) tileData.get("EntityId")).getValue().toUpperCase();
} else if (tileData.containsKey("SpawnData")) {
// 1.9 format
Map<String,Tag> spawnData = ((CompoundTag) tileData.get("SpawnData")).getValue();
//Bukkit.getLogger().info("DEBUG: " + spawnData.toString());
if (spawnData.containsKey("id")) {
creatureType = ((StringTag) spawnData.get("id")).getValue().toUpperCase();
}
}
//Bukkit.getLogger().info("DEBUG: creature type = " + creatureType);
// The mob type might be prefixed with "Minecraft:"
if (creatureType.startsWith("MINECRAFT:")) {
creatureType = creatureType.substring(10);
}
if (WEtoME.containsKey(creatureType)) {
spawnerBlockType = WEtoME.get(creatureType);
} else {
try {
spawnerBlockType = EntityType.valueOf(creatureType);
} catch (Exception e) {
Bukkit.getLogger().warning("Spawner setting of " + creatureType + " is unknown for this server. Skipping.");
}
}
//Bukkit.getLogger().info("DEBUG: spawnerblock type = " + spawnerBlockType);
}
/**
* Sets this block's sign data
* @param tileData
*/
public void setSign(Map<String, Tag> tileData) {
signText = new ArrayList<String>();
List<String> text = new ArrayList<String>();
for (int i = 1; i < 5; i++) {
String line = ((StringTag) tileData.get("Text" + String.valueOf(i))).getValue();
// This value can actually be a string that says null sometimes.
if (line.equalsIgnoreCase("null")) {
line = "";
}
//System.out.println("DEBUG: line " + i + " = '"+ line + "' of length " + line.length());
text.add(line);
}
JSONParser parser = new JSONParser();
ContainerFactory containerFactory = new ContainerFactory(){
public List creatArrayContainer() {
return new LinkedList();
}
public Map createObjectContainer() {
return new LinkedHashMap();
}
};
// This just removes all the JSON formatting and provides the raw text
for (int line = 0; line < 4; line++) {
String lineText = "";
if (!text.get(line).equals("\"\"") && !text.get(line).isEmpty()) {
//String lineText = text.get(line).replace("{\"extra\":[\"", "").replace("\"],\"text\":\"\"}", "");
//Bukkit.getLogger().info("DEBUG: sign text = '" + text.get(line) + "'");
if (text.get(line).startsWith("{")) {
// JSON string
try {
Map json = (Map)parser.parse(text.get(line), containerFactory);
List list = (List) json.get("extra");
//System.out.println("DEBUG1:" + JSONValue.toJSONString(list));
if (list != null) {
Iterator iter = list.iterator();
while(iter.hasNext()){
Object next = iter.next();
String format = JSONValue.toJSONString(next);
//System.out.println("DEBUG2:" + format);
// This doesn't see right, but appears to be the easiest way to identify this string as JSON...
if (format.startsWith("{")) {
// JSON string
Map jsonFormat = (Map)parser.parse(format, containerFactory);
Iterator formatIter = jsonFormat.entrySet().iterator();
while (formatIter.hasNext()) {
Map.Entry entry = (Map.Entry)formatIter.next();
//System.out.println("DEBUG3:" + entry.getKey() + "=>" + entry.getValue());
String key = entry.getKey().toString();
String value = entry.getValue().toString();
if (key.equalsIgnoreCase("color")) {
try {
lineText += ChatColor.valueOf(value.toUpperCase());
} catch (Exception noColor) {
Bukkit.getLogger().warning("Unknown color " + value +" in sign when pasting schematic, skipping...");
}
} else if (key.equalsIgnoreCase("text")) {
lineText += value;
} else {
// Formatting - usually the value is always true, but check just in case
if (key.equalsIgnoreCase("obfuscated") && value.equalsIgnoreCase("true")) {
lineText += ChatColor.MAGIC;
} else if (key.equalsIgnoreCase("underlined") && value.equalsIgnoreCase("true")) {
lineText += ChatColor.UNDERLINE;
} else {
// The rest of the formats
try {
lineText += ChatColor.valueOf(key.toUpperCase());
} catch (Exception noFormat) {
// Ignore
//System.out.println("DEBUG3:" + key + "=>" + value);
Bukkit.getLogger().warning("Unknown format " + value +" in sign when pasting schematic, skipping...");
}
}
}
}
} else {
// This is unformatted text. It is included in "". A reset is required to clear
// any previous formatting
if (format.length()>1) {
lineText += ChatColor.RESET + format.substring(format.indexOf('"')+1,format.lastIndexOf('"'));
}
}
}
} else {
// No extra tag
json = (Map)parser.parse(text.get(line), containerFactory);
String value = (String) json.get("text");
//System.out.println("DEBUG text only?:" + value);
lineText += value;
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
// This is unformatted text (not JSON). It is included in "".
if (text.get(line).length() > 1) {
try {
lineText = text.get(line).substring(text.get(line).indexOf('"')+1,text.get(line).lastIndexOf('"'));
} catch (Exception e) {
//There may not be those "'s, so just use the raw line
lineText = text.get(line);
}
} else {
// just in case it isn't - show the raw line
lineText = text.get(line);
}
}
//Bukkit.getLogger().info("Line " + line + " is " + lineText);
}
signText.add(lineText);
}
}
public void setBook(Map<String, Tag> tileData) {
//Bukkit.getLogger().info("DEBUG: Book data ");
Bukkit.getLogger().info(tileData.toString());
}
@SuppressWarnings("deprecation")
public void setChest(NMSAbstraction nms, Map<String, Tag> tileData) {
try {
ListTag chestItems = (ListTag) tileData.get("Items");
if (chestItems != null) {
//int number = 0;
for (Tag item : chestItems.getValue()) {
// Format for chest items is:
// id = short value of item id
// Damage = short value of item damage
// Count = the number of items
// Slot = the slot in the chest
// inventory
if (item instanceof CompoundTag) {
try {
// Id is a number
short itemType = (Short) ((CompoundTag) item).getValue().get("id").getValue();
short itemDamage = (Short) ((CompoundTag) item).getValue().get("Damage").getValue();
byte itemAmount = (Byte) ((CompoundTag) item).getValue().get("Count").getValue();
byte itemSlot = (Byte) ((CompoundTag) item).getValue().get("Slot").getValue();
ItemStack chestItem = new ItemStack(itemType, itemAmount, itemDamage);
chestContents.put(itemSlot, chestItem);
} catch (ClassCastException ex) {
// Id is a material
String itemType = (String) ((CompoundTag) item).getValue().get("id").getValue();
try {
// Get the material
if (itemType.startsWith("minecraft:")) {
String material = itemType.substring(10).toUpperCase();
// Special case for non-standard material names
Material itemMaterial;
//Bukkit.getLogger().info("DEBUG: " + material);
if (WEtoM.containsKey(material)) {
//Bukkit.getLogger().info("DEBUG: Found in hashmap");
itemMaterial = WEtoM.get(material);
} else {
//Bukkit.getLogger().info("DEBUG: Not in hashmap");
itemMaterial = Material.valueOf(material);
}
short itemDamage = (Short) ((CompoundTag) item).getValue().get("Damage").getValue();
byte itemAmount = (Byte) ((CompoundTag) item).getValue().get("Count").getValue();
byte itemSlot = (Byte) ((CompoundTag) item).getValue().get("Slot").getValue();
ItemStack chestItem = new ItemStack(itemMaterial, itemAmount, itemDamage);
if (itemMaterial.equals(Material.WRITTEN_BOOK)) {
chestItem = nms.setBook(item);
}
// Check for potions
if (itemMaterial.toString().contains("POTION")) {
chestItem = nms.setPotion(itemMaterial, item, chestItem);
}
chestContents.put(itemSlot, chestItem);
}
} catch (Exception exx) {
// Bukkit.getLogger().info(item.toString());
// Bukkit.getLogger().info(((CompoundTag)item).getValue().get("id").getName());
Bukkit.getLogger().severe(
"Could not parse item [" + itemType.substring(10).toUpperCase() + "] in schematic - skipping!");
// Bukkit.getLogger().severe(item.toString());
exx.printStackTrace();
}
}
// Bukkit.getLogger().info("Set chest inventory slot "
// + itemSlot + " to " +
// chestItem.toString());
}
}
//Bukkit.getLogger().info("Added " + number + " items to chest");
}
} catch (Exception e) {
Bukkit.getLogger().severe("Could not parse schematic file item, skipping!");
// e.printStackTrace();
}
}
/**
* Paste this block at blockLoc
* @param nms
* @param blockLoc
*/
//@SuppressWarnings("deprecation")
@SuppressWarnings("deprecation")
public void paste(NMSAbstraction nms, Location blockLoc, boolean usePhysics, Biome biome) {
// Only paste air if it is below the sea level and in the overworld
Block block = new Location(blockLoc.getWorld(), x, y, z).add(blockLoc).getBlock();
block.setBiome(biome);
nms.setBlockSuperFast(block, typeId, data, usePhysics);
if (signText != null) {
if (block.getTypeId() != typeId) {
block.setTypeId(typeId);
}
// Sign
Sign sign = (Sign) block.getState();
int index = 0;
for (String line : signText) {
sign.setLine(index++, line);
}
sign.update();
} else if (banner != null) {
banner.set(block);
} else if (skull != null){
skull.set(block);
} else if (pot != null){
pot.set(nms, block);
} else if (spawnerBlockType != null) {
if (block.getTypeId() != typeId) {
block.setTypeId(typeId);
}
CreatureSpawner cs = (CreatureSpawner)block.getState();
cs.setSpawnedType(spawnerBlockType);
} else if (!chestContents.isEmpty()) {
if (block.getTypeId() != typeId) {
block.setTypeId(typeId);
}
// Check if this is a double chest
Chest chestBlock = (Chest) block.getState();
InventoryHolder iH = chestBlock.getInventory().getHolder();
if (iH instanceof DoubleChest) {
//Bukkit.getLogger().info("DEBUG: double chest");
DoubleChest doubleChest = (DoubleChest) iH;
for (ItemStack chestItem: chestContents.values()) {
doubleChest.getInventory().addItem(chestItem);
}
} else {
// Single chest
for (Entry<Byte, ItemStack> en : chestContents.entrySet()) {
chestBlock.getInventory().setItem(en.getKey(), en.getValue());
}
}
}
}
/**
* @return Vector for where this block is in the schematic
*/
public Vector getVector() {
return new Vector(x,y,z);
}
}

View File

@ -0,0 +1,139 @@
/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ASkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.schematics;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
import us.tastybento.org.jnbt.IntTag;
import us.tastybento.org.jnbt.StringTag;
import us.tastybento.org.jnbt.Tag;
/**
* This class describes pots and is used in schematic importing
*
* @author SpyL1nk
*
*/
public class PotBlock {
private Material potItem;
private int potItemData;
private static HashMap<String, Material> potItemList;
static {
potItemList = new HashMap<String, Material>();
potItemList.put("", Material.AIR);
potItemList.put("minecraft:red_flower", Material.RED_ROSE);
potItemList.put("minecraft:yellow_flower", Material.YELLOW_FLOWER);
potItemList.put("minecraft:sapling", Material.SAPLING);
potItemList.put("minecraft:red_mushroom", Material.RED_MUSHROOM);
potItemList.put("minecraft:brown_mushroom", Material.BROWN_MUSHROOM);
potItemList.put("minecraft:cactus", Material.CACTUS);
potItemList.put("minecraft:deadbush", Material.LONG_GRASS);
potItemList.put("minecraft:tallgrass", Material.LONG_GRASS);
}
public boolean set(NMSAbstraction nms, Block block) {
if(potItem != Material.AIR){
nms.setFlowerPotBlock(block, new ItemStack(potItem, 1,(short) potItemData));
}
return true;
}
public boolean prep(Map<String, Tag> tileData) {
// Initialize as default
potItem = Material.AIR;
potItemData = 0;
try {
if(tileData.containsKey("Item")){
// Get the item in the pot
if (tileData.get("Item") instanceof IntTag) {
// Item is a number, not a material
int id = ((IntTag) tileData.get("Item")).getValue();
potItem = Material.getMaterial(id);
// Check it's a viable pot item
if (!potItemList.containsValue(potItem)) {
// No, so reset to AIR
potItem = Material.AIR;
}
} else if (tileData.get("Item") instanceof StringTag) {
// Item is a material
String itemName = ((StringTag) tileData.get("Item")).getValue();
if (potItemList.containsKey(itemName)){
// Check it's a viable pot item
if (potItemList.containsKey(itemName)) {
potItem = potItemList.get(itemName);
}
}
}
if(tileData.containsKey("Data")){
int dataTag = ((IntTag) tileData.get("Data")).getValue();
// We should check data for each type of potItem
if(potItem == Material.RED_ROSE){
if(dataTag >= 0 && dataTag <= 8){
potItemData = dataTag;
} else {
// Prevent hacks
potItemData = 0;
}
} else if(potItem == Material.YELLOW_FLOWER ||
potItem == Material.RED_MUSHROOM ||
potItem == Material.BROWN_MUSHROOM ||
potItem == Material.CACTUS){
// Set to 0 anyway
potItemData = 0;
} else if(potItem == Material.SAPLING){
if(dataTag >= 0 && dataTag <= 4){
potItemData = dataTag;
} else {
// Prevent hacks
potItemData = 0;
}
} else if(potItem == Material.LONG_GRASS){
// Only 0 or 2
if(dataTag == 0 || dataTag == 2){
potItemData = dataTag;
} else {
potItemData = 0;
}
} else {
// ERROR ?
potItemData = 0;
}
}
else {
potItemData = 0;
}
}
//Bukkit.getLogger().info("Debug: flowerpot item = " + potItem.toString());
//Bukkit.getLogger().info("Debug: flowerpot item data = " + potItemData);
//Bukkit.getLogger().info("Debug: flowerpot materialdata = " + new MaterialData(potItem,(byte) potItemData).toString());
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,193 @@
package us.tastybento.bskyblock.schematics;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.util.VaultHelper;
public class SchematicsMgr {
private BSkyBlock plugin;
private static HashMap<String, Schematic> schematics = new HashMap<String, Schematic>();
/**
* Class to hold all schematics that are available
* @param plugin
*/
public SchematicsMgr(BSkyBlock plugin) {
this.plugin = plugin;
loadSchematics();
}
/**
* Loads schematics. If the default
* island is not included, it will be made
*/
public void loadSchematics() {
// Check if there is a schematic folder and make it if it does not exist
File schematicFolder = new File(plugin.getDataFolder(), "schematics");
if (!schematicFolder.exists()) {
schematicFolder.mkdir();
}
// Clear the schematic list that is kept in memory
schematics.clear();
// Load the default schematic if it exists
// Set up the default schematic
File schematicFile = new File(schematicFolder, "island.schematic");
File netherFile = new File(schematicFolder, "nether.schematic");
if (!schematicFile.exists()) {
//plugin.getLogger().info("Default schematic does not exist...");
// Only copy if the default exists
if (plugin.getResource("schematics/island.schematic") != null) {
plugin.getLogger().info("Default schematic does not exist, saving it...");
plugin.saveResource("schematics/island.schematic", false);
// Add it to schematics
try {
schematics.put("default",new Schematic(plugin, schematicFile));
} catch (IOException e) {
plugin.getLogger().severe("Could not load default schematic!");
e.printStackTrace();
}
// If this is repeated later due to the schematic config, fine, it will only add info
} else {
// No islands.schematic in the jar, so just make the default using
// built-in island generation
schematics.put("default",new Schematic(plugin));
}
plugin.getLogger().info("Loaded default nether schematic");
} else {
// It exists, so load it
try {
schematics.put("default",new Schematic(plugin, schematicFile));
plugin.getLogger().info("Loaded default island schematic.");
} catch (IOException e) {
plugin.getLogger().severe("Could not load default schematic!");
e.printStackTrace();
}
}
// Add the nether default too
if (!netherFile.exists()) {
if (plugin.getResource("schematics/nether.schematic") != null) {
plugin.saveResource("schematics/nether.schematic", false);
// Add it to schematics
try {
Schematic netherIsland = new Schematic(plugin, netherFile);
netherIsland.setVisible(false);
schematics.put("nether", netherIsland);
plugin.getLogger().info("Loaded default nether schematic.");
} catch (IOException e) {
plugin.getLogger().severe("Could not load default nether schematic!");
e.printStackTrace();
}
} else {
plugin.getLogger().severe("Could not find default nether schematic!");
}
} else {
// It exists, so load it
try {
Schematic netherIsland = new Schematic(plugin, netherFile);
netherIsland.setVisible(false);
schematics.put("nether", netherIsland);
plugin.getLogger().info("Loaded default nether schematic.");
} catch (IOException e) {
plugin.getLogger().severe("Could not load default nether schematic!");
e.printStackTrace();
}
}
// Set up some basic settings
if (schematics.containsKey("default")) {
schematics.get("default").setName("Island");
schematics.get("default").setDescription("");
schematics.get("default").setPartnerName("nether");
schematics.get("default").setBiome(Settings.defaultBiome);
schematics.get("default").setIcon(Material.GRASS);
if (Settings.chestItems.length == 0) {
schematics.get("default").setUseDefaultChest(false);
}
schematics.get("default").setOrder(0);
}
if (schematics.containsKey("nether")) {
schematics.get("nether").setName("NetherBlock Island");
schematics.get("nether").setDescription("Nether Island");
schematics.get("nether").setPartnerName("default");
schematics.get("nether").setBiome(Biome.HELL);
schematics.get("nether").setIcon(Material.NETHERRACK);
schematics.get("nether").setVisible(false);
schematics.get("nether").setPasteEntities(true);
if (Settings.chestItems.length == 0) {
schematics.get("nether").setUseDefaultChest(false);
}
}
// TODO: Load other settings from config.yml
}
/**
* Get schematic with name
* @param name
* @return schematic or null if it does not exist
*/
public Schematic getSchematic(String name) {
return schematics.get(name);
}
/**
* List schematics this player can access. If @param ignoreNoPermission is true, then only
* schematics with a specific permission set will be checked. I.e., no common schematics will
* be returned (including the default one).
* @param player
* @param ignoreNoPermission
* @return List of schematics this player can use based on their permission level
*/
public List<Schematic> getSchematics(Player player, boolean ignoreNoPermission) {
List<Schematic> result = new ArrayList<Schematic>();
// Find out what schematics this player can choose from
//Bukkit.getLogger().info("DEBUG: Checking schematics for " + player.getName());
for (Schematic schematic : schematics.values()) {
//Bukkit.getLogger().info("DEBUG: schematic name is '"+ schematic.getName() + "'");
//Bukkit.getLogger().info("DEBUG: perm is " + schematic.getPerm());
if ((!ignoreNoPermission && schematic.getPerm().isEmpty()) || VaultHelper.hasPerm(player, schematic.getPerm())) {
//Bukkit.getLogger().info("DEBUG: player can use this schematic");
// Only add if it's visible
if (schematic.isVisible()) {
// Check if it's a nether island, but the nether is not enables
if (schematic.getBiome().equals(Biome.HELL)) {
if (Settings.createNether && IslandWorld.getNetherWorld() != null) {
result.add(schematic);
}
} else {
result.add(schematic);
}
}
}
}
// Sort according to order
Collections.sort(result, new Comparator<Schematic>() {
@Override
public int compare(Schematic o1, Schematic o2) {
return ((o2.getOrder() < o1.getOrder()) ? 1 : -1);
}
});
return result;
}
public HashMap<String, Schematic> getAll() {
return schematics;
}
}

View File

@ -0,0 +1,308 @@
/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ASkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.schematics;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.SkullType;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Skull;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import us.tastybento.org.jnbt.ByteTag;
import us.tastybento.org.jnbt.CompoundTag;
import us.tastybento.org.jnbt.IntTag;
import us.tastybento.org.jnbt.ListTag;
import us.tastybento.org.jnbt.StringTag;
import us.tastybento.org.jnbt.Tag;
/**
* This class describes skulls and is used in schematic importing
*
* @author SpyL1nk
*
*/
public class SkullBlock {
private static final Random random = new Random();
private static final String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private SkullType skullType;
private String skullOwnerName;
private String skullOwnerUUID;
private BlockFace skullRotation;
private int skullStanding;
private String skullTextureValue = null;
private String skullTextureSignature = null;
private static HashMap<Integer, SkullType> skullTypeList;
private static HashMap<Integer, BlockFace> skullRotationList;
static {
skullTypeList = new HashMap<Integer, SkullType>();
skullTypeList.put(0, SkullType.SKELETON);
skullTypeList.put(1, SkullType.WITHER);
skullTypeList.put(2, SkullType.ZOMBIE);
skullTypeList.put(3, SkullType.PLAYER);
skullTypeList.put(4, SkullType.CREEPER);
}
static {
skullRotationList = new HashMap<Integer, BlockFace>();
skullRotationList.put(0, BlockFace.NORTH);
skullRotationList.put(1, BlockFace.NORTH_NORTH_EAST);
skullRotationList.put(2, BlockFace.NORTH_EAST);
skullRotationList.put(3, BlockFace.EAST_NORTH_EAST);
skullRotationList.put(4, BlockFace.EAST);
skullRotationList.put(5, BlockFace.EAST_SOUTH_EAST);
skullRotationList.put(6, BlockFace.SOUTH_EAST);
skullRotationList.put(7, BlockFace.SOUTH_SOUTH_EAST);
skullRotationList.put(8, BlockFace.SOUTH);
skullRotationList.put(9, BlockFace.SOUTH_SOUTH_WEST);
skullRotationList.put(10, BlockFace.SOUTH_WEST);
skullRotationList.put(11, BlockFace.WEST_SOUTH_WEST);
skullRotationList.put(12, BlockFace.WEST);
skullRotationList.put(13, BlockFace.WEST_NORTH_WEST);
skullRotationList.put(14, BlockFace.NORTH_WEST);
skullRotationList.put(15, BlockFace.NORTH_NORTH_WEST);
}
@SuppressWarnings("deprecation")
public boolean set(Block block) {
Skull skull = (Skull) block.getState();
if(skullOwnerName != null){
skull.setOwner(skullOwnerName);
}
skull.setSkullType(skullType);
skull.setRotation(skullRotation);
skull.setRawData((byte) skullStanding);
// Texture update
if(skullTextureValue != null){
setSkullWithNonPlayerProfile(skullTextureValue, skullTextureSignature, skullOwnerUUID, skullOwnerName, skull);
}
skull.update();
return true;
}
public boolean prep(Map<String, Tag> tileData, int dataValue) {
try {
// Take skull type
if(tileData.containsKey("SkullType")){
int skullTypeId = (int) ((ByteTag) tileData.get("SkullType")).getValue();
//Bukkit.getLogger().info("DEBUG: skull type = " + skullTypeId);
if(skullTypeList.containsKey(skullTypeId)){
skullType = skullTypeList.get(skullTypeId);
}
else {
// Prevent hacks, set to default skull type
skullType = skullTypeList.get(0);
}
}
else{
// Prevent hacks, set to defaut skull type
skullType = skullTypeList.get(0);
}
//Bukkit.getLogger().info("DEBUG: skull's data value = " + dataValue);
// Data value 0 is actually unused for skulls, set to 2 to prevent hacks
if(dataValue > 0 && dataValue < 6){
skullStanding = dataValue;
if(tileData.containsKey("Rot")){
int skullRotId = (int) ((ByteTag) tileData.get("Rot")).getValue();
//Bukkit.getLogger().info("DEBUG: skull's rotation byte = " + skullRotId);
// Useful for skulls on the floor to insert rotation data
if(skullRotationList.containsKey(skullStanding)){
skullRotation = skullRotationList.get(skullRotId);
}
else{
// Prevents hacks
skullRotation = skullRotationList.get(0);
}
}
else{
skullRotation = skullRotationList.get(0);
}
}
else{
skullStanding = 2;
if(tileData.containsKey("Rot")){
int skullRotId = ((IntTag) tileData.get("Rot")).getValue();
//Bukkit.getLogger().info("DEBUG: skull's rotation byte = " + skullRotId);
// Useful for skulls on the floor to insert rotation data
if(skullRotationList.containsKey(skullStanding)){
skullRotation = skullRotationList.get(skullRotId);
}
// Prevents hacks
else{
skullRotation = skullRotationList.get(0);
}
}
else{
skullRotation = skullRotationList.get(0);
}
}
// Check for Player Heads (skin, texture etc.)
if(skullType == SkullType.PLAYER && tileData.containsKey("Owner")){
Map<String, Tag> skullOwner = ((CompoundTag) tileData.get("Owner")).getValue();
if(skullOwner.containsKey("Name")){
skullOwnerName = ((StringTag) skullOwner.get("Name")).getValue();
//Bukkit.getLogger().info("DEBUG: skull owner's name = " + skullOwnerName);
}
if(skullOwner.containsKey("Id")){
skullOwnerUUID = ((StringTag) skullOwner.get("Id")).getValue();
//Bukkit.getLogger().info("DEBUG: skull owner's UUID = " + skullOwnerUUID);
}
if(skullOwner.containsKey("Properties")){
Map<String, Tag> skullOwnerProperties = ((CompoundTag) skullOwner.get("Properties")).getValue();
if(skullOwnerProperties.containsKey("textures")){
ListTag listTagTextures = (ListTag) skullOwnerProperties.get("textures");
//Bukkit.getLogger().info("DEBUG: skull texture's list = " + listTagTextures);
if(listTagTextures != null){
// Logicaly, textures should have only one entry ...
Map<String, Tag> skullOwnerTextures = ((CompoundTag) listTagTextures.getValue().get(0)).getValue();
if(skullOwnerTextures.containsKey("Value")){
skullTextureValue = ((StringTag) skullOwnerTextures.get("Value")).getValue();
//Bukkit.getLogger().info("DEBUG: skull texture's value = " + skullTextureValue);
}
if(skullOwnerTextures.containsKey("Signature")){
skullTextureSignature = ((StringTag) skullOwnerTextures.get("Signature")).getValue();
//Bukkit.getLogger().info("DEBUG: skull's texture signature = " + skullTextureSignature);
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
// Credits: GermanCoding
@SuppressWarnings("deprecation")
public static void setSkullWithNonPlayerProfile(String textureValue, String textureSignature, String ownerUUID, String ownerName, Skull skull) {
if (skull.getType() != Material.SKULL)
throw new IllegalArgumentException("Block must be a skull.");
skull.getWorld().refreshChunk(skull.getChunk().getX(), skull.getChunk().getZ());
// Difference beetween NonPlayerSkin and PlayerSkin
if(textureSignature != null){
try {
setSkullProfile(skull, getPlayerProfile(textureValue, textureSignature, ownerUUID, ownerName));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
else {
try {
setSkullProfile(skull, getNonPlayerProfile(textureValue, ownerUUID, ownerName));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
//skull.getWorld().refreshChunk(skull.getChunk().getX(), skull.getChunk().getZ());
}
// Credits: val59000 (THANK YOU VERY MUCH VAL59000 !)
private static void setSkullProfile(Skull skull, GameProfile gameProfile) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Field profileField = null;
try {
profileField = skull.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
profileField.set(skull, gameProfile);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
// Credits: dori99xd
public static GameProfile getNonPlayerProfile(String textureValue, String ownerUUID, String ownerName) {
// Create a new GameProfile with .schematic informations or with fake informations
GameProfile newSkinProfile = new GameProfile(ownerUUID == null ? UUID.randomUUID() : UUID.fromString(ownerUUID),
ownerName == null ? getRandomString(16) : null);
// Insert textures properties
newSkinProfile.getProperties().put("textures", new Property("textures", textureValue));
return newSkinProfile;
}
// Credits: dori99xd
public static GameProfile getPlayerProfile(String textureValue, String textureSignature, String ownerUUID, String ownerName) {
// Create a new GameProfile with .schematic informations or with fake informations
GameProfile newSkinProfile = new GameProfile( ownerUUID == null ? UUID.randomUUID() : UUID.fromString(ownerUUID),
ownerName == null ? getRandomString(16) : null);
// Insert textures properties
newSkinProfile.getProperties().put("textures", new Property("textures", textureValue, textureSignature));
return newSkinProfile;
}
// Credits: dori99xd
public static String getRandomString(int length) {
StringBuilder b = new StringBuilder(length);
for(int j = 0; j < length; j++){
b.append(chars.charAt(random.nextInt(chars.length())));
}
return b.toString();
}
}

View File

@ -0,0 +1,356 @@
/*******************************************************************************
* This file is part of BSkyBlock.
*
* BSkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* BSkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with BSkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.util;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.objects.Island;
/**
* A class that calculates finds a safe spot asynchronously and then teleports the player there.
* @author tastybento
*
*/
public class SafeSpotTeleport {
//private NMSAbstraction nms;
//private BSkyBlock plugin;
/**
* Teleport to a safe place and if it fails, show a failure message
* @param plugin
* @param player
* @param l
* @param failureMessage
*/
public SafeSpotTeleport(final BSkyBlock plugin, final Entity player, final Location l, final String failureMessage) {
new SafeSpotTeleport(plugin, player, l, 1, failureMessage, false);
}
/**
* Teleport to a safe place and set home
* @param plugin
* @param player
* @param l
* @param number
*/
public SafeSpotTeleport(final BSkyBlock plugin, final Entity player, final Location l, final int number) {
new SafeSpotTeleport(plugin, player, l, number, "", true);
}
/**
* Teleport to a safe spot on an island
* @param plugin
* @param player
* @param l
*/
public SafeSpotTeleport(final BSkyBlock plugin, final Entity player, final Location l) {
new SafeSpotTeleport(plugin, player, l, 1, "", false);
}
/**
* Teleport to a safe spot on an island
* @param plugin
* @param entity
* @param islandLoc
*/
public SafeSpotTeleport(final BSkyBlock plugin, final Entity entity, final Location islandLoc, final int homeNumber, final String failureMessage, final boolean setHome) {
//this.plugin = plugin;
//plugin.getLogger().info("DEBUG: running safe spot");
// Get island
Island island = plugin.getIslands().getIslandAt(islandLoc);
if (island != null) {
final World world = islandLoc.getWorld();
// Get the chunks
List<ChunkSnapshot> chunkSnapshot = new ArrayList<ChunkSnapshot>();
// Add the center chunk
chunkSnapshot.add(island.getCenter().toVector().toLocation(world).getChunk().getChunkSnapshot());
// Add immediately adjacent chunks
for (int x = islandLoc.getChunk().getX()-1; x <= islandLoc.getChunk().getX()+1; x++) {
for (int z = islandLoc.getChunk().getZ()-1; z <= islandLoc.getChunk().getZ()+1; z++) {
if (x != islandLoc.getChunk().getX() || z != islandLoc.getChunk().getZ()) {
chunkSnapshot.add(world.getChunkAt(x, z).getChunkSnapshot());
}
}
}
// Add the rest of the island protected area
for (int x = island.getMinProtectedX() /16; x <= (island.getMinProtectedX() + island.getProtectionRange() - 1)/16; x++) {
for (int z = island.getMinProtectedZ() /16; z <= (island.getMinProtectedZ() + island.getProtectionRange() - 1)/16; z++) {
// This includes the center spots again, so is not as efficient...
chunkSnapshot.add(world.getChunkAt(x, z).getChunkSnapshot());
}
}
//plugin.getLogger().info("DEBUG: size of chunk ss = " + chunkSnapshot.size());
final List<ChunkSnapshot> finalChunk = chunkSnapshot;
int maxHeight = world.getMaxHeight() - 2;
if (world.getEnvironment().equals(Environment.NETHER)) {
// We need to ignore the roof
maxHeight -= 20;
}
final int worldHeight = maxHeight;
//plugin.getLogger().info("DEBUG:world height = " + worldHeight);
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@SuppressWarnings("deprecation")
@Override
public void run() {
// Find a safe spot, defined as a solid block, with 2 air spaces above it
//long time = System.nanoTime();
int x = 0;
int y = 0;
int z = 0;
ChunkSnapshot safeChunk = null;
ChunkSnapshot portalChunk = null;
boolean safeSpotFound = false;
/*
try {
nms = checkVersion();
} catch (Exception e) {
e.printStackTrace();
}*/
Vector safeSpotInChunk = null;
Vector portalPart = null;
double distance = 0D;
double safeDistance = 0D;
for (ChunkSnapshot chunk: finalChunk) {
for (x = 0; x< 16; x++) {
for (z = 0; z < 16; z++) {
// Work down from the entry point up
for (y = Math.min(chunk.getHighestBlockYAt(x, z), worldHeight); y >= 0; y--) {
//System.out.println("Trying " + (16 * chunk.getX() + x) + " " + y + " " + (16 * chunk.getZ() + z));
// Check for portal - only if this is not a safe home search
if (!setHome && chunk.getBlockTypeId(x, y, z) == Material.PORTAL.getId()) {
if (portalPart == null || (distance > islandLoc.toVector().distanceSquared(new Vector(x,y,z)))) {
// First one found or a closer one, save the chunk the position and the distance
portalChunk = chunk;
portalPart = new Vector(x,y,z);
distance = portalPart.distanceSquared(islandLoc.toVector());
}
}
// Check for safe spot, but only if it is closer than one we have found already
if (!safeSpotFound || (safeDistance > islandLoc.toVector().distanceSquared(new Vector(x,y,z)))) {
// No safe spot yet, or closer distance
if (checkBlock(chunk,x,y,z, worldHeight)) {
safeChunk = chunk;
safeSpotFound = true;
safeSpotInChunk = new Vector(x,y,z);
safeDistance = islandLoc.toVector().distanceSquared(safeSpotInChunk);
}
}
}
} //end z
} // end x
//if (safeSpotFound) {
//System.out.print("DEBUG: safe spot found " + safeSpotInChunk.toString());
//break search;
//}
}
// End search
// Check if the portal is safe (it should be)
if (portalPart != null) {
//System.out.print("DEBUG: Portal found");
// There is a portal available, but is it safe?
// Get the lowest portal spot
x = portalPart.getBlockX();
y = portalPart.getBlockY();
z = portalPart.getBlockZ();
while (portalChunk.getBlockTypeId(x,y,z) == Material.PORTAL.getId()) {
y--;
}
//System.out.print("DEBUG: Portal teleport loc = " + (16 * portalChunk.getX() + x) + "," + (y) + "," + (16 * portalChunk.getZ() + z));
// Now check if this is a safe location
if (checkBlock(portalChunk,x,y,z, worldHeight)) {
// Yes, so use this instead of the highest location
//System.out.print("DEBUG: Portal is safe");
safeSpotFound = true;
safeSpotInChunk = new Vector(x,y,z);
safeChunk = portalChunk;
// TODO: Add safe portal spot to island
}
}
//System.out.print("Seconds = " + ((System.nanoTime() - time) * 0.000000001));
if (safeChunk != null && safeSpotFound) {
//final Vector spot = new Vector((16 *currentChunk.getX()) + x + 0.5D, y +1, (16 * currentChunk.getZ()) + z + 0.5D)
final Vector spot = new Vector((16 *safeChunk.getX()) + 0.5D, 1, (16 * safeChunk.getZ()) + 0.5D).add(safeSpotInChunk);
// Return to main thread and teleport the player
plugin.getServer().getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
Location destination = spot.toLocation(islandLoc.getWorld());
//plugin.getLogger().info("DEBUG: safe spot found = " + destination);
// Create a portal
// TODO Add if statement here
//Block b = player.getLocation().getBlock();
//if (b.getType() != Material.PORTAL) {
/*
if (world.equals(BSkyBlock.getNetherWorld())) {
for (int x = -1; x < 3; x++) {
for (int y = -1; y< 4; y++) {
Location l = new Location(islandLoc.getWorld(), destination.getBlockX() + x, destination.getBlockY() + y, destination.getBlockZ() -1);
if (x == -1 || x == 2 || y == -1 || y == 3) {
//nms.setBlockSuperFast(l.getBlock(), Material.OBSIDIAN.getId(), (byte)0, false);
//l.getBlock().setType(Material.OBSIDIAN);
//plugin.getLogger().info("DEBUG: obsidian at "+ l);
} else {
//plugin.getLogger().info("DEBUG: Portal at "+ l);
nms.setBlockSuperFast(l.getBlock(), Material.PORTAL.getId(), (byte)0, false);
//l.getBlock().setType(Material.PORTAL);
}
}
}
}*/
if (setHome && entity instanceof Player) {
plugin.getPlayers().setHomeLocation(entity.getUniqueId(), destination, homeNumber);
}
Vector velocity = entity.getVelocity();
entity.teleport(destination);
entity.setVelocity(velocity);
}});
} else {
// We did not find a spot
plugin.getServer().getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
//plugin.getLogger().info("DEBUG: safe spot not found");
if (entity instanceof Player) {
if (!failureMessage.isEmpty()) {
Util.sendMessage(((Player)entity), failureMessage);
} else {
Util.sendMessage(((Player)entity), ChatColor.RED + "Warp not safe");
}
}
}});
}
}
/**
* Returns true if the location is a safe one.
* @param chunk
* @param x
* @param y
* @param z
* @param worldHeight
* @return
*/
@SuppressWarnings("deprecation")
private boolean checkBlock(ChunkSnapshot chunk, int x, int y, int z, int worldHeight) {
int type = chunk.getBlockTypeId(x, y, z);
if (type != 0) { // AIR
int space1 = chunk.getBlockTypeId(x, Math.min(y + 1, worldHeight), z);
int space2 = chunk.getBlockTypeId(x, Math.min(y + 2, worldHeight), z);
if ((space1 == 0 && space2 == 0) || (space1 == Material.PORTAL.getId() || space2 == Material.PORTAL.getId())) {
// Now there is a chance that this is a safe spot
// Check for safe ground
Material mat = Material.getMaterial(type);
if (!mat.toString().contains("FENCE")
&& !mat.toString().contains("DOOR")
&& !mat.toString().contains("GATE")
&& !mat.toString().contains("PLATE")) {
switch (mat) {
// Unsafe
case ANVIL:
case BARRIER:
case BOAT:
case CACTUS:
case DOUBLE_PLANT:
case ENDER_PORTAL:
case FIRE:
case FLOWER_POT:
case LADDER:
case LAVA:
case LEVER:
case LONG_GRASS:
case PISTON_EXTENSION:
case PISTON_MOVING_PIECE:
case PORTAL:
case SIGN_POST:
case SKULL:
case STANDING_BANNER:
case STATIONARY_LAVA:
case STATIONARY_WATER:
case STONE_BUTTON:
case TORCH:
case TRIPWIRE:
case WATER:
case WEB:
case WOOD_BUTTON:
//System.out.println("Block is dangerous " + mat.toString());
break;
default:
// Safe
// System.out.println("Block is safe " + mat.toString());
return true;
}
}
}
}
return false;
}});
}
}
/**
* Checks what version the server is running and picks the appropriate NMS handler, or fallback
* @return NMSAbstraction class
* @throws ClassNotFoundException
* @throws IllegalArgumentException
* @throws SecurityException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
/*
private NMSAbstraction checkVersion() throws ClassNotFoundException, IllegalArgumentException,
SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
String serverPackageName = plugin.getServer().getClass().getPackage().getName();
String pluginPackageName = plugin.getClass().getPackage().getName();
String version = serverPackageName.substring(serverPackageName.lastIndexOf('.') + 1);
Class<?> clazz;
try {
//plugin.getLogger().info("DEBUG: Trying " + pluginPackageName + ".nms." + version + ".NMSHandler");
clazz = Class.forName(pluginPackageName + ".nms." + version + ".NMSHandler");
} catch (Exception e) {
plugin.getLogger().info("No NMS Handler found, falling back to Bukkit API.");
clazz = Class.forName(pluginPackageName + ".nms.fallback.NMSHandler");
}
//plugin.getLogger().info("DEBUG: " + serverPackageName);
//plugin.getLogger().info("DEBUG: " + pluginPackageName);
// Check if we have a NMSAbstraction implementing class at that location.
if (NMSAbstraction.class.isAssignableFrom(clazz)) {
return (NMSAbstraction) clazz.getConstructor().newInstance();
} else {
throw new IllegalStateException("Class " + clazz.getName() + " does not implement NMSAbstraction");
}
}*/
}

View File

@ -142,4 +142,9 @@ public class Util {
} }
return result; return result;
} }
public static boolean isOnePointEight() {
// TODO Auto-generated method stub
return false;
}
} }

View File

@ -1,10 +1,90 @@
/*******************************************************************************
* This file is part of BSkyBlock.
*
* BSkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* BSkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with BSkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.util.nms; package us.tastybento.bskyblock.util.nms;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import us.tastybento.org.jnbt.Tag;
public interface NMSAbstraction { public interface NMSAbstraction {
/**
* Update the low-level chunk information for the given block to the new block ID and data. This
* change will not be propagated to clients until the chunk is refreshed to them.
* @param block
* @param blockId
* @param data
* @param applyPhysics
*/
public void setBlockSuperFast(Block block, int blockId, byte data, boolean applyPhysics);
public ItemStack setBook(Tag item);
/**
* Sets a block to be an item stack
* @param block
* @param itemStack
*/
public void setFlowerPotBlock(Block block, ItemStack itemStack);
boolean isPotion(ItemStack item);
/**
* Returns a potion ItemStack
* @param itemMaterial
* @param itemTag
* @param chestItem
* @return
*/
public ItemStack setPotion(Material itemMaterial, Tag itemTag, ItemStack chestItem);
/**
* Gets a monster egg itemstack
* @param type
* @param amount
* @return itemstack
*/
public ItemStack getSpawnEgg(EntityType type, int amount);
/**
* Send an action bar message to player
* @param player
* @param message
*/
public void sendActionBar(Player player, String message); public void sendActionBar(Player player, String message);
/**
* Send a title to a player
* @param player
* @param message
*/
public void sendTitle(Player player, String message); public void sendTitle(Player player, String message);
/**
* Send a subtitle to a player
* @param player
* @param message
*/
public void sendSubtitle(Player player, String message); public void sendSubtitle(Player player, String message);
} }

View File

@ -1,8 +1,21 @@
package us.tastybento.bskyblock.util.nms.fallback; package us.tastybento.bskyblock.util.nms.fallback;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.SpawnEgg;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionType;
import us.tastybento.bskyblock.util.nms.NMSAbstraction; import us.tastybento.bskyblock.util.nms.NMSAbstraction;
import us.tastybento.org.jnbt.CompoundTag;
import us.tastybento.org.jnbt.StringTag;
import us.tastybento.org.jnbt.Tag;
/** /**
* A fallback NMS Handler when the NMS version is not supported by BSkyBlock * A fallback NMS Handler when the NMS version is not supported by BSkyBlock
@ -30,4 +43,96 @@ public class NMSHandler implements NMSAbstraction{
} }
/* (non-Javadoc)
* @see com.wasteofplastic.askyblock.nms.NMSAbstraction#getSpawnEgg(org.bukkit.entity.EntityType, int)
*/
@Override
public ItemStack getSpawnEgg(EntityType type, int amount) {
SpawnEgg egg = new SpawnEgg(type);
return egg.toItemStack(amount);
}
@Override
public boolean isPotion(ItemStack item) {
if (item.getType().equals(Material.POTION) && item.getDurability() != 0) {
return true;
}
return false;
}
/* (non-Javadoc)
* @see com.wasteofplastic.askyblock.nms.NMSAbstraction#setBlockSuperFast(org.bukkit.block.Block, org.bukkit.Material)
*/
@SuppressWarnings("deprecation")
@Override
public void setBlockSuperFast(Block b, int blockId, byte data, boolean applyPhysics) {
b.setTypeIdAndData(blockId, data, applyPhysics);
}
@Override
public ItemStack setBook(Tag item) {
Bukkit.getLogger().warning("Written books in schematics not supported with this version of server");
return new ItemStack(Material.WRITTEN_BOOK);
}
@SuppressWarnings("deprecation")
@Override
public void setFlowerPotBlock(Block block, ItemStack itemStack) {
block.setTypeIdAndData(itemStack.getTypeId(), itemStack.getData().getData(), false);
}
@SuppressWarnings("deprecation")
@Override
public ItemStack setPotion(Material itemMaterial, Tag itemTags,
ItemStack chestItem) {
// Try some backwards compatibility with new 1.9 schematics
Map<String,Tag> contents = (Map<String,Tag>) ((CompoundTag) itemTags).getValue().get("tag").getValue();
StringTag stringTag = ((StringTag)contents.get("Potion"));
if (stringTag != null) {
String tag = stringTag.getValue().replace("minecraft:", "");
PotionType type = null;
boolean strong = tag.contains("strong");
boolean _long = tag.contains("long");
//Bukkit.getLogger().info("tag = " + tag);
if(tag.equals("fire_resistance") || tag.equals("long_fire_resistance")){
type = PotionType.FIRE_RESISTANCE;
}else if(tag.equals("harming") || tag.equals("strong_harming")){
type = PotionType.INSTANT_DAMAGE;
}else if(tag.equals("healing") || tag.equals("strong_healing")){
type = PotionType.INSTANT_HEAL;
}else if(tag.equals("invisibility") || tag.equals("long_invisibility")){
type = PotionType.INVISIBILITY;
}else if(tag.equals("leaping") || tag.equals("long_leaping") || tag.equals("strong_leaping")){
type = PotionType.JUMP;
}else if(tag.equals("night_vision") || tag.equals("long_night_vision")){
type = PotionType.NIGHT_VISION;
}else if(tag.equals("poison") || tag.equals("long_poison") || tag.equals("strong_poison")){
type = PotionType.POISON;
}else if(tag.equals("regeneration") || tag.equals("long_regeneration") || tag.equals("strong_regeneration")){
type = PotionType.REGEN;
}else if(tag.equals("slowness") || tag.equals("long_slowness")){
type = PotionType.SLOWNESS;
}else if(tag.equals("swiftness") || tag.equals("long_swiftness") || tag.equals("strong_swiftness")){
type = PotionType.SPEED;
}else if(tag.equals("strength") || tag.equals("long_strength") || tag.equals("strong_strength")){
type = PotionType.STRENGTH;
}else if(tag.equals("water_breathing") || tag.equals("long_water_breathing")){
type = PotionType.WATER_BREATHING;
}else if(tag.equals("water")){
type = PotionType.WATER;
}else if(tag.equals("weakness") || tag.equals("long_weakness")){
type = PotionType.WEAKNESS;
}else{
return chestItem;
}
Potion potion = new Potion(type);
potion.setHasExtendedDuration(_long);
potion.setLevel(strong ? 2 : 1);
chestItem = potion.toItemStack(chestItem.getAmount());
}
return chestItem;
}
} }

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_10_R1;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_10_R1
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_11_R1;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_11_R1
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,8 +1,32 @@
package us.tastybento.bskyblock.util.nms.v1_12_R1; package us.tastybento.bskyblock.util.nms.v1_12_R1;
import org.bukkit.entity.Player; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStack;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import net.minecraft.server.v1_12_R1.BlockPosition;
import net.minecraft.server.v1_12_R1.IBlockData;
import net.minecraft.server.v1_12_R1.NBTTagCompound;
import net.minecraft.server.v1_12_R1.NBTTagList;
import net.minecraft.server.v1_12_R1.NBTTagString;
import net.minecraft.server.v1_12_R1.TileEntityFlowerPot;
import us.tastybento.bskyblock.util.nms.NMSAbstraction; import us.tastybento.bskyblock.util.nms.NMSAbstraction;
import us.tastybento.org.jnbt.CompoundTag;
import us.tastybento.org.jnbt.ListTag;
import us.tastybento.org.jnbt.StringTag;
import us.tastybento.org.jnbt.Tag;
/** /**
* NMS Handler for v1_12_R1 * NMS Handler for v1_12_R1
@ -11,6 +35,178 @@ import us.tastybento.bskyblock.util.nms.NMSAbstraction;
* @author Poslovitch * @author Poslovitch
*/ */
public class NMSHandler implements NMSAbstraction{ public class NMSHandler implements NMSAbstraction{
private static HashMap<EntityType, String> bToMConversion;
static {
bToMConversion = new HashMap<EntityType, String> ();
bToMConversion.put(EntityType.MUSHROOM_COW, "mooshroom");
bToMConversion.put(EntityType.PIG_ZOMBIE, "zombie_pigman");
}
@Override
public void setBlockSuperFast(Block b, int blockId, byte data, boolean applyPhysics) {
net.minecraft.server.v1_12_R1.World w = ((CraftWorld) b.getWorld()).getHandle();
net.minecraft.server.v1_12_R1.Chunk chunk = w.getChunkAt(b.getX() >> 4, b.getZ() >> 4);
BlockPosition bp = new BlockPosition(b.getX(), b.getY(), b.getZ());
int combined = blockId + (data << 12);
IBlockData ibd = net.minecraft.server.v1_12_R1.Block.getByCombinedId(combined);
if (applyPhysics) {
w.setTypeAndData(bp, ibd, 3);
} else {
w.setTypeAndData(bp, ibd, 2);
}
chunk.a(bp, ibd);
}
@Override
public ItemStack setBook(Tag item) {
ItemStack chestItem = new ItemStack(Material.WRITTEN_BOOK);
//Bukkit.getLogger().info("item data");
//Bukkit.getLogger().info(item.toString());
if (((CompoundTag) item).getValue().containsKey("tag")) {
Map<String,Tag> contents = (Map<String,Tag>) ((CompoundTag) item).getValue().get("tag").getValue();
//BookMeta bookMeta = (BookMeta) chestItem.getItemMeta();
String author = "";
if (contents.containsKey("author")) {
author = ((StringTag)contents.get("author")).getValue();
}
//Bukkit.getLogger().info("Author: " + author);
//bookMeta.setAuthor(author);
String title = "";
if (contents.containsKey("title")) {
title = ((StringTag)contents.get("title")).getValue();
}
//Bukkit.getLogger().info("Title: " + title);
//bookMeta.setTitle(title);
List<String> lore = new ArrayList<String>();
if (contents.containsKey("display")) {
Map<String,Tag> display = (Map<String, Tag>) (contents.get("display")).getValue();
List<Tag> loreTag = ((ListTag)display.get("Lore")).getValue();
for (Tag s: loreTag) {
lore.add(((StringTag)s).getValue());
}
}
//Bukkit.getLogger().info("Lore: " + lore);
net.minecraft.server.v1_12_R1.ItemStack stack = CraftItemStack.asNMSCopy(chestItem);
// Pages
NBTTagCompound tag = new NBTTagCompound(); //Create the NMS Stack's NBT (item data)
tag.setString("title", title); //Set the book's title
tag.setString("author", author);
if (contents.containsKey("pages")) {
NBTTagList pages = new NBTTagList();
List<Tag> pagesTag = ((ListTag)contents.get("pages")).getValue();
for (Tag s: pagesTag) {
pages.add(new NBTTagString(((StringTag)s).getValue()));
}
tag.set("pages", pages); //Add the pages to the tag
}
stack.setTag(tag); //Apply the tag to the item
chestItem = CraftItemStack.asCraftMirror(stack);
ItemMeta bookMeta = (ItemMeta) chestItem.getItemMeta();
bookMeta.setLore(lore);
chestItem.setItemMeta(bookMeta);
}
return chestItem;
}
/* (non-Javadoc)
* @see com.wasteofplastic.askyblock.nms.NMSAbstraction#setBlock(org.bukkit.block.Block, org.bukkit.inventory.ItemStack)
*/
@Override
public void setFlowerPotBlock(final Block block, final ItemStack itemStack) {
if (block.getType().equals(Material.FLOWER_POT)) {
Location loc = block.getLocation();
CraftWorld cw = (CraftWorld)block.getWorld();
BlockPosition bp = new BlockPosition(loc.getX(), loc.getY(), loc.getZ());
TileEntityFlowerPot te = (TileEntityFlowerPot)cw.getHandle().getTileEntity(bp);
//Bukkit.getLogger().info("Debug: flowerpot materialdata = " + (new ItemStack(potItem, 1,(short) potItemData).toString()));
net.minecraft.server.v1_12_R1.ItemStack cis = CraftItemStack.asNMSCopy(itemStack);
te.setContents(cis);
te.update();
}
}
/* (non-Javadoc)
* @see com.wasteofplastic.askyblock.nms.NMSAbstraction#isPotion(org.bukkit.inventory.ItemStack)
*/
@Override
public boolean isPotion(ItemStack item) {
//Bukkit.getLogger().info("DEBUG:item = " + item);
if (item.getType().equals(Material.POTION)) {
net.minecraft.server.v1_12_R1.ItemStack stack = CraftItemStack.asNMSCopy(item);
NBTTagCompound tag = stack.getTag();
//Bukkit.getLogger().info("DEBUG: tag is " + tag);
//Bukkit.getLogger().info("DEBUG: display is " + tag.getString("display"));
/*
for (String list : tag.c()) {
Bukkit.getLogger().info("DEBUG: list = " + list);
}*/
if (tag != null && (!tag.getString("Potion").equalsIgnoreCase("minecraft:water") || tag.getString("Potion").isEmpty())) {
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see com.wasteofplastic.acidisland.nms.NMSAbstraction#setPotion(com.wasteofplastic.org.jnbt.Tag)
*/
@SuppressWarnings({ "unchecked"})
@Override
public ItemStack setPotion(Material material, Tag itemTags, ItemStack chestItem) {
Map<String,Tag> cont = (Map<String,Tag>) ((CompoundTag) itemTags).getValue();
if (cont != null) {
if (((CompoundTag) itemTags).getValue().containsKey("tag")) {
Map<String,Tag> contents = (Map<String,Tag>)((CompoundTag) itemTags).getValue().get("tag").getValue();
StringTag stringTag = ((StringTag)contents.get("Potion"));
if (stringTag != null) {
String tag = ((StringTag)contents.get("Potion")).getValue();
//Bukkit.getLogger().info("DEBUG: potioninfo found: " + tag);
net.minecraft.server.v1_12_R1.ItemStack stack = CraftItemStack.asNMSCopy(chestItem);
NBTTagCompound tagCompound = stack.getTag();
if(tagCompound == null){
tagCompound = new NBTTagCompound();
}
tagCompound.setString("Potion", tag);
stack.setTag(tagCompound);
return CraftItemStack.asBukkitCopy(stack);
}
}
}
// Schematic is old, the potions do not have tags
// Set it to zero so that the potion bottles don't look like giant purple and black blocks
chestItem.setDurability((short)0);
Bukkit.getLogger().warning("Potion in schematic is pre-V1.9 format and will just be water.");
return chestItem;
}
/**
* Get spawn egg
* @param type
* @param amount
* @return
*/
public ItemStack getSpawnEgg(EntityType type, int amount) {
//Bukkit.getLogger().info("DEBUG: setting spawn egg " + type.toString());
ItemStack item = new ItemStack(Material.MONSTER_EGG, amount);
net.minecraft.server.v1_12_R1.ItemStack stack = CraftItemStack.asNMSCopy(item);
NBTTagCompound tagCompound = stack.getTag();
if(tagCompound == null){
tagCompound = new NBTTagCompound();
}
//Bukkit.getLogger().info("DEBUG: tag = " + tagCompound);
NBTTagCompound id = new NBTTagCompound();
if (!bToMConversion.containsKey(type)) {
id.setString("id", "minecraft:" + type.toString().toLowerCase());
} else {
id.setString("id", "minecraft:" + bToMConversion.get(type));
}
tagCompound.set("EntityTag", id);
stack.setTag(tagCompound);
//Bukkit.getLogger().info("DEBUG: after tag = " + tagCompound);
return CraftItemStack.asBukkitCopy(stack);
}
@Override @Override
public void sendActionBar(Player player, String message) { public void sendActionBar(Player player, String message) {
@ -29,5 +225,4 @@ public class NMSHandler implements NMSAbstraction{
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
} }

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_7_R3;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_7_R3
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_7_R4;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_7_R4
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_8_R1;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_8_R1
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_8_R2;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_8_R2
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_8_R3;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_8_R3
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_9_R1;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_9_R1
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -1,33 +0,0 @@
package us.tastybento.bskyblock.util.nms.v1_9_R2;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
/**
* NMS Handler for v1_9_R2
*
* @author Tastybento
* @author Poslovitch
*/
public class NMSHandler implements NMSAbstraction{
@Override
public void sendActionBar(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendTitle(Player player, String message) {
// TODO Auto-generated method stub
}
@Override
public void sendSubtitle(Player player, String message) {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,52 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_Byte_Array</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class ByteArrayTag extends Tag {
/**
* The value.
*/
private final byte[] value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public ByteArrayTag(String name, byte[] value) {
super(name);
this.value = value;
}
@Override
public byte[] getValue() {
return value;
}
@Override
public String toString() {
StringBuilder hex = new StringBuilder();
for (byte b : value) {
String hexDigits = Integer.toHexString(b).toUpperCase();
if (hexDigits.length() == 1) {
hex.append("0");
}
hex.append(hexDigits).append(" ");
}
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Byte_Array" + append + ": " + hex.toString();
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_Byte</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class ByteTag extends Tag {
/**
* The value.
*/
private final byte value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public ByteTag(String name, byte value) {
super(name);
this.value = value;
}
@Override
public Byte getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Byte" + append + ": " + value;
}
}

View File

@ -0,0 +1,53 @@
package us.tastybento.org.jnbt;
import java.util.Collections;
import java.util.Map;
/**
* The <code>TAG_Compound</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class CompoundTag extends Tag {
/**
* The value.
*/
private final Map<String, Tag> value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public CompoundTag(String name, Map<String, Tag> value) {
super(name);
this.value = Collections.unmodifiableMap(value);
}
@Override
public Map<String, Tag> getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
StringBuilder bldr = new StringBuilder();
bldr.append("TAG_Compound" + append + ": " + value.size() + " entries\r\n{\r\n");
for (Map.Entry<String, Tag> entry : value.entrySet()) {
bldr.append(" " + entry.getValue().toString().replaceAll("\r\n", "\r\n ") + "\r\n");
}
bldr.append("}");
return bldr.toString();
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_Double</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class DoubleTag extends Tag {
/**
* The value.
*/
private final double value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public DoubleTag(String name, double value) {
super(name);
this.value = value;
}
@Override
public Double getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Double" + append + ": " + value;
}
}

View File

@ -0,0 +1,28 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_End</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class EndTag extends Tag {
/**
* Creates the tag.
*/
public EndTag() {
super("");
}
@Override
public Object getValue() {
return null;
}
@Override
public String toString() {
return "TAG_End";
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_Float</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class FloatTag extends Tag {
/**
* The value.
*/
private final float value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public FloatTag(String name, float value) {
super(name);
this.value = value;
}
@Override
public Float getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Float" + append + ": " + value;
}
}

View File

@ -0,0 +1,60 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package us.tastybento.org.jnbt;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The {@code TAG_Int_Array} tag.
*/
public final class IntArrayTag extends Tag {
private final int[] value;
/**
* Creates the tag with an empty name.
*
* @param value the value of the tag
*/
public IntArrayTag(String name, int[] value) {
super(name);
checkNotNull(value);
this.value = value;
}
@Override
public int[] getValue() {
return value;
}
@Override
public String toString() {
StringBuilder hex = new StringBuilder();
for (int b : value) {
String hexDigits = Integer.toHexString(b).toUpperCase();
if (hexDigits.length() == 1) {
hex.append("0");
}
hex.append(hexDigits).append(" ");
}
return "TAG_Int_Array(" + hex + ")";
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_Int</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class IntTag extends Tag {
/**
* The value.
*/
private final int value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public IntTag(String name, int value) {
super(name);
this.value = value;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Int" + append + ": " + value;
}
}

View File

@ -0,0 +1,70 @@
package us.tastybento.org.jnbt;
import java.util.Collections;
import java.util.List;
/**
* The <code>TAG_List</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class ListTag extends Tag {
/**
* The type.
*/
private final Class<? extends Tag> type;
/**
* The value.
*/
private final List<Tag> value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param type
* The type of item in the list.
* @param value
* The value.
*/
public ListTag(String name, Class<? extends Tag> type, List<Tag> value) {
super(name);
this.type = type;
this.value = Collections.unmodifiableList(value);
}
/**
* Gets the type of item in this list.
*
* @return The type of item in this list.
*/
public Class<? extends Tag> getType() {
return type;
}
@Override
public List<Tag> getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
StringBuilder bldr = new StringBuilder();
bldr.append("TAG_List" + append + ": " + value.size() + " entries of type " + NBTUtils.getTypeName(type) + "\r\n{\r\n");
for (Tag t : value) {
bldr.append(" " + t.toString().replaceAll("\r\n", "\r\n ") + "\r\n");
}
bldr.append("}");
return bldr.toString();
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_Long</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class LongTag extends Tag {
/**
* The value.
*/
private final long value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public LongTag(String name, long value) {
super(name);
this.value = value;
}
@Override
public Long getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Long" + append + ": " + value;
}
}

View File

@ -0,0 +1,69 @@
package us.tastybento.org.jnbt;
import java.nio.charset.Charset;
/**
* A class which holds constant values.
*
* @author Graham Edgecombe
*
*/
public final class NBTConstants {
/**
* The character set used by NBT (UTF-8).
*/
public static final Charset CHARSET = Charset.forName("UTF-8");
/**
* Tag type constants.
*/
public static final int TYPE_END = 0, TYPE_BYTE = 1, TYPE_SHORT = 2, TYPE_INT = 3, TYPE_LONG = 4, TYPE_FLOAT = 5, TYPE_DOUBLE = 6, TYPE_BYTE_ARRAY = 7,
TYPE_STRING = 8, TYPE_LIST = 9, TYPE_COMPOUND = 10, TYPE_INT_ARRAY = 11;
/**
* Default private constructor.
*/
private NBTConstants() {
}
/**
* Convert a type ID to its corresponding {@link Tag} class.
*
* @param id type ID
* @return tag class
* @throws IllegalArgumentException thrown if the tag ID is not valid
*/
public static Class<? extends Tag> getClassFromType(int id) {
switch (id) {
case TYPE_END:
return EndTag.class;
case TYPE_BYTE:
return ByteTag.class;
case TYPE_SHORT:
return ShortTag.class;
case TYPE_INT:
return IntTag.class;
case TYPE_LONG:
return LongTag.class;
case TYPE_FLOAT:
return FloatTag.class;
case TYPE_DOUBLE:
return DoubleTag.class;
case TYPE_BYTE_ARRAY:
return ByteArrayTag.class;
case TYPE_STRING:
return StringTag.class;
case TYPE_LIST:
return ListTag.class;
case TYPE_COMPOUND:
return CompoundTag.class;
case TYPE_INT_ARRAY:
return IntArrayTag.class;
default:
throw new IllegalArgumentException("Unknown tag type ID of " + id);
}
}
}

View File

@ -0,0 +1,172 @@
package us.tastybento.org.jnbt;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
/**
* <p>
* This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* streams, and produces an object graph of subclasses of the <code>Tag</code>
* object.
* </p>
*
* <p>
* The NBT format was created by Markus Persson, and the specification may be
* found at <a href="http://www.minecraft.net/docs/NBT.txt">
* http://www.minecraft.net/docs/NBT.txt</a>.
* </p>
*
* @author Graham Edgecombe
*
*/
public final class NBTInputStream implements Closeable {
/**
* The data input stream.
*/
private final DataInputStream is;
/**
* Creates a new <code>NBTInputStream</code>, which will source its data
* from the specified input stream.
*
* @param is
* The input stream.
* @throws IOException
* if an I/O error occurs.
*/
public NBTInputStream(InputStream is) throws IOException {
this.is = new DataInputStream(new GZIPInputStream(is));
}
/**
* Reads an NBT tag from the stream.
*
* @return The tag that was read.
* @throws IOException
* if an I/O error occurs.
*/
public Tag readTag() throws IOException {
return readTag(0);
}
/**
* Reads an NBT from the stream.
*
* @param depth
* The depth of this tag.
* @return The tag that was read.
* @throws IOException
* if an I/O error occurs.
*/
private Tag readTag(int depth) throws IOException {
int type = is.readByte() & 0xFF;
String name;
if (type != NBTConstants.TYPE_END) {
int nameLength = is.readShort() & 0xFFFF;
byte[] nameBytes = new byte[nameLength];
is.readFully(nameBytes);
name = new String(nameBytes, NBTConstants.CHARSET);
} else {
name = "";
}
return readTagPayload(type, name, depth);
}
/**
* Reads the payload of a tag, given the name and type.
*
* @param type
* The type.
* @param name
* The name.
* @param depth
* The depth.
* @return The tag.
* @throws IOException
* if an I/O error occurs.
*/
private Tag readTagPayload(int type, String name, int depth) throws IOException {
switch (type) {
case NBTConstants.TYPE_END:
if (depth == 0) {
throw new IOException("TAG_End found without a TAG_Compound/TAG_List tag preceding it.");
} else {
return new EndTag();
}
case NBTConstants.TYPE_BYTE:
return new ByteTag(name, is.readByte());
case NBTConstants.TYPE_SHORT:
return new ShortTag(name, is.readShort());
case NBTConstants.TYPE_INT:
return new IntTag(name, is.readInt());
case NBTConstants.TYPE_LONG:
return new LongTag(name, is.readLong());
case NBTConstants.TYPE_FLOAT:
return new FloatTag(name, is.readFloat());
case NBTConstants.TYPE_DOUBLE:
return new DoubleTag(name, is.readDouble());
case NBTConstants.TYPE_BYTE_ARRAY:
int length = is.readInt();
byte[] bytes = new byte[length];
is.readFully(bytes);
return new ByteArrayTag(name, bytes);
case NBTConstants.TYPE_STRING:
length = is.readShort();
bytes = new byte[length];
is.readFully(bytes);
return new StringTag(name, new String(bytes, NBTConstants.CHARSET));
case NBTConstants.TYPE_LIST:
int childType = is.readByte();
length = is.readInt();
List<Tag> tagList = new ArrayList<Tag>();
for (int i = 0; i < length; i++) {
Tag tag = readTagPayload(childType, "", depth + 1);
if (tag instanceof EndTag) {
throw new IOException("TAG_End not permitted in a list.");
}
tagList.add(tag);
}
return new ListTag(name, NBTUtils.getTypeClass(childType), tagList);
case NBTConstants.TYPE_COMPOUND:
Map<String, Tag> tagMap = new HashMap<String, Tag>();
while (true) {
Tag tag = readTag(depth + 1);
if (tag instanceof EndTag) {
break;
} else {
tagMap.put(tag.getName(), tag);
}
}
return new CompoundTag(name, tagMap);
case NBTConstants.TYPE_INT_ARRAY:
length = is.readInt();
int[] data = new int[length];
for (int i = 0; i < length; i++) {
data[i] = is.readInt();
}
return new IntArrayTag(name, data);
default:
throw new IOException("Invalid tag type: " + type + ".");
}
}
@Override
public void close() throws IOException {
is.close();
}
}

View File

@ -0,0 +1,270 @@
package us.tastybento.org.jnbt;
import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.GZIPOutputStream;
/**
* <p>
* This class writes <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* <code>Tag</code> objects to an underlying <code>OutputStream</code>.
* </p>
*
* <p>
* The NBT format was created by Markus Persson, and the specification may be
* found at <a href="http://www.minecraft.net/docs/NBT.txt">
* http://www.minecraft.net/docs/NBT.txt</a>.
* </p>
*
* @author Graham Edgecombe
*
*/
public final class NBTOutputStream implements Closeable {
/**
* The output stream.
*/
private final DataOutputStream os;
/**
* Creates a new <code>NBTOutputStream</code>, which will write data to the
* specified underlying output stream.
*
* @param os
* The output stream.
* @throws IOException
* if an I/O error occurs.
*/
public NBTOutputStream(OutputStream os) throws IOException {
this.os = new DataOutputStream(new GZIPOutputStream(os));
}
/**
* Writes a tag.
*
* @param tag
* The tag to write.
* @throws IOException
* if an I/O error occurs.
*/
public void writeTag(Tag tag) throws IOException {
int type = NBTUtils.getTypeCode(tag.getClass());
String name = tag.getName();
byte[] nameBytes = name.getBytes(NBTConstants.CHARSET);
os.writeByte(type);
os.writeShort(nameBytes.length);
os.write(nameBytes);
if (type == NBTConstants.TYPE_END) {
throw new IOException("Named TAG_End not permitted.");
}
writeTagPayload(tag);
}
/**
* Writes tag payload.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeTagPayload(Tag tag) throws IOException {
int type = NBTUtils.getTypeCode(tag.getClass());
switch (type) {
case NBTConstants.TYPE_END:
writeEndTagPayload((EndTag) tag);
break;
case NBTConstants.TYPE_BYTE:
writeByteTagPayload((ByteTag) tag);
break;
case NBTConstants.TYPE_SHORT:
writeShortTagPayload((ShortTag) tag);
break;
case NBTConstants.TYPE_INT:
writeIntTagPayload((IntTag) tag);
break;
case NBTConstants.TYPE_LONG:
writeLongTagPayload((LongTag) tag);
break;
case NBTConstants.TYPE_FLOAT:
writeFloatTagPayload((FloatTag) tag);
break;
case NBTConstants.TYPE_DOUBLE:
writeDoubleTagPayload((DoubleTag) tag);
break;
case NBTConstants.TYPE_BYTE_ARRAY:
writeByteArrayTagPayload((ByteArrayTag) tag);
break;
case NBTConstants.TYPE_STRING:
writeStringTagPayload((StringTag) tag);
break;
case NBTConstants.TYPE_LIST:
writeListTagPayload((ListTag) tag);
break;
case NBTConstants.TYPE_COMPOUND:
writeCompoundTagPayload((CompoundTag) tag);
break;
default:
throw new IOException("Invalid tag type: " + type + ".");
}
}
/**
* Writes a <code>TAG_Byte</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeByteTagPayload(ByteTag tag) throws IOException {
os.writeByte(tag.getValue());
}
/**
* Writes a <code>TAG_Byte_Array</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeByteArrayTagPayload(ByteArrayTag tag) throws IOException {
byte[] bytes = tag.getValue();
os.writeInt(bytes.length);
os.write(bytes);
}
/**
* Writes a <code>TAG_Compound</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeCompoundTagPayload(CompoundTag tag) throws IOException {
for (Tag childTag : tag.getValue().values()) {
writeTag(childTag);
}
os.writeByte((byte) 0); // end tag - better way?
}
/**
* Writes a <code>TAG_List</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeListTagPayload(ListTag tag) throws IOException {
Class<? extends Tag> clazz = tag.getType();
List<Tag> tags = tag.getValue();
int size = tags.size();
os.writeByte(NBTUtils.getTypeCode(clazz));
os.writeInt(size);
for (int i = 0; i < size; i++) {
writeTagPayload(tags.get(i));
}
}
/**
* Writes a <code>TAG_String</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeStringTagPayload(StringTag tag) throws IOException {
byte[] bytes = tag.getValue().getBytes(NBTConstants.CHARSET);
os.writeShort(bytes.length);
os.write(bytes);
}
/**
* Writes a <code>TAG_Double</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeDoubleTagPayload(DoubleTag tag) throws IOException {
os.writeDouble(tag.getValue());
}
/**
* Writes a <code>TAG_Float</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeFloatTagPayload(FloatTag tag) throws IOException {
os.writeFloat(tag.getValue());
}
/**
* Writes a <code>TAG_Long</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeLongTagPayload(LongTag tag) throws IOException {
os.writeLong(tag.getValue());
}
/**
* Writes a <code>TAG_Int</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeIntTagPayload(IntTag tag) throws IOException {
os.writeInt(tag.getValue());
}
/**
* Writes a <code>TAG_Short</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeShortTagPayload(ShortTag tag) throws IOException {
os.writeShort(tag.getValue());
}
/**
* Writes a <code>TAG_Empty</code> tag.
*
* @param tag
* The tag.
* @throws IOException
* if an I/O error occurs.
*/
private void writeEndTagPayload(EndTag tag) {
/* empty */
}
@Override
public void close() throws IOException {
os.close();
}
}

View File

@ -0,0 +1,128 @@
package us.tastybento.org.jnbt;
/**
* A class which contains NBT-related utility methods.
*
* @author Graham Edgecombe
*
*/
public final class NBTUtils {
/**
* Gets the type name of a tag.
*
* @param clazz
* The tag class.
* @return The type name.
*/
public static String getTypeName(Class<? extends Tag> clazz) {
if (clazz.equals(ByteArrayTag.class)) {
return "TAG_Byte_Array";
} else if (clazz.equals(ByteTag.class)) {
return "TAG_Byte";
} else if (clazz.equals(CompoundTag.class)) {
return "TAG_Compound";
} else if (clazz.equals(DoubleTag.class)) {
return "TAG_Double";
} else if (clazz.equals(EndTag.class)) {
return "TAG_End";
} else if (clazz.equals(FloatTag.class)) {
return "TAG_Float";
} else if (clazz.equals(IntTag.class)) {
return "TAG_Int";
} else if (clazz.equals(ListTag.class)) {
return "TAG_List";
} else if (clazz.equals(LongTag.class)) {
return "TAG_Long";
} else if (clazz.equals(ShortTag.class)) {
return "TAG_Short";
} else if (clazz.equals(StringTag.class)) {
return "TAG_String";
} else {
throw new IllegalArgumentException("Invalid tag classs (" + clazz.getName() + ").");
}
}
/**
* Gets the type code of a tag class.
*
* @param clazz
* The tag class.
* @return The type code.
* @throws IllegalArgumentException
* if the tag class is invalid.
*/
public static int getTypeCode(Class<? extends Tag> clazz) {
if (clazz.equals(ByteArrayTag.class)) {
return NBTConstants.TYPE_BYTE_ARRAY;
} else if (clazz.equals(ByteTag.class)) {
return NBTConstants.TYPE_BYTE;
} else if (clazz.equals(CompoundTag.class)) {
return NBTConstants.TYPE_COMPOUND;
} else if (clazz.equals(DoubleTag.class)) {
return NBTConstants.TYPE_DOUBLE;
} else if (clazz.equals(EndTag.class)) {
return NBTConstants.TYPE_END;
} else if (clazz.equals(FloatTag.class)) {
return NBTConstants.TYPE_FLOAT;
} else if (clazz.equals(IntTag.class)) {
return NBTConstants.TYPE_INT;
} else if (clazz.equals(ListTag.class)) {
return NBTConstants.TYPE_LIST;
} else if (clazz.equals(LongTag.class)) {
return NBTConstants.TYPE_LONG;
} else if (clazz.equals(ShortTag.class)) {
return NBTConstants.TYPE_SHORT;
} else if (clazz.equals(StringTag.class)) {
return NBTConstants.TYPE_STRING;
} else {
throw new IllegalArgumentException("Invalid tag classs (" + clazz.getName() + ").");
}
}
/**
* Gets the class of a type of tag.
*
* @param type
* The type.
* @return The class.
* @throws IllegalArgumentException
* if the tag type is invalid.
*/
public static Class<? extends Tag> getTypeClass(int type) {
switch (type) {
case NBTConstants.TYPE_END:
return EndTag.class;
case NBTConstants.TYPE_BYTE:
return ByteTag.class;
case NBTConstants.TYPE_SHORT:
return ShortTag.class;
case NBTConstants.TYPE_INT:
return IntTag.class;
case NBTConstants.TYPE_LONG:
return LongTag.class;
case NBTConstants.TYPE_FLOAT:
return FloatTag.class;
case NBTConstants.TYPE_DOUBLE:
return DoubleTag.class;
case NBTConstants.TYPE_BYTE_ARRAY:
return ByteArrayTag.class;
case NBTConstants.TYPE_STRING:
return StringTag.class;
case NBTConstants.TYPE_LIST:
return ListTag.class;
case NBTConstants.TYPE_COMPOUND:
return CompoundTag.class;
default:
throw new IllegalArgumentException("Invalid tag type : " + type + ".");
}
}
/**
* Default private constructor.
*/
private NBTUtils() {
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_Short</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class ShortTag extends Tag {
/**
* The value.
*/
private final short value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public ShortTag(String name, short value) {
super(name);
this.value = value;
}
@Override
public Short getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_Short" + append + ": " + value;
}
}

View File

@ -0,0 +1,44 @@
package us.tastybento.org.jnbt;
/**
* The <code>TAG_String</code> tag.
*
* @author Graham Edgecombe
*
*/
public final class StringTag extends Tag {
/**
* The value.
*/
private final String value;
/**
* Creates the tag.
*
* @param name
* The name.
* @param value
* The value.
*/
public StringTag(String name, String value) {
super(name);
this.value = value;
}
@Override
public String getValue() {
return value;
}
@Override
public String toString() {
String name = getName();
String append = "";
if (name != null && !name.equals("")) {
append = "(\"" + this.getName() + "\")";
}
return "TAG_String" + append + ": " + value;
}
}

View File

@ -0,0 +1,42 @@
package us.tastybento.org.jnbt;
/**
* Represents a single NBT tag.
*
* @author Graham Edgecombe
*
*/
public abstract class Tag {
/**
* The name of this tag.
*/
private final String name;
/**
* Creates the tag with the specified name.
*
* @param name
* The name.
*/
public Tag(String name) {
this.name = name;
}
/**
* Gets the name of this tag.
*
* @return The name of this tag.
*/
public final String getName() {
return name;
}
/**
* Gets the value of this tag.
*
* @return The value of this tag.
*/
public abstract Object getValue();
}