diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java index 2c1f11da95..b94d3f1fd1 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -910,7 +910,8 @@ public abstract class Entity { nbttagcompound.a("Air", (short) this.airTicks); nbttagcompound.a("OnGround", this.onGround); // CraftBukkit start - nbttagcompound.setLong("WorldUID", this.world.worldData.getWorldUID()); + nbttagcompound.setLong("WorldUUIDLeast", this.world.getUUID().getLeastSignificantBits()); + nbttagcompound.setLong("WorldUUIDMost", this.world.getUUID().getMostSignificantBits()); nbttagcompound.setLong("UUIDLeast", this.uniqueId.getLeastSignificantBits()); nbttagcompound.setLong("UUIDMost", this.uniqueId.getMostSignificantBits()); // CraftBukkit end @@ -983,23 +984,17 @@ public abstract class Entity { org.bukkit.World bworld = null; // TODO: Remove World related checks, replaced with WorldUID. - if (this instanceof EntityPlayer) { - EntityPlayer entityPlayer = (EntityPlayer) this; - String worldName = nbttagcompound.getString("World"); + String worldName = nbttagcompound.getString("World"); - if (nbttagcompound.hasKey("WorldUID")) { - bworld = server.getWorld(nbttagcompound.getLong("WorldUID")); - } else if ("".equals(worldName)) { - bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(entityPlayer.dimension).getWorld(); - } else { - bworld = server.getWorld(worldName); - } + if (nbttagcompound.hasKey("WorldUUIDMost") && nbttagcompound.hasKey("WorldUUIDLeast")) { + UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); + bworld = server.getWorld(uid); } else { - if (nbttagcompound.hasKey("WorldUID")) { - bworld = server.getWorld(nbttagcompound.getLong("WorldUID")); - } else { - bworld = server.getWorld(nbttagcompound.getString("World")); - } + bworld = server.getWorld(worldName); + } + if(bworld == null && this instanceof EntityPlayer) { + EntityPlayer entityPlayer = (EntityPlayer) this; + bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(entityPlayer.dimension).getWorld(); } this.spawnIn(bworld == null ? null : ((org.bukkit.craftbukkit.CraftWorld) bworld).getHandle()); diff --git a/src/main/java/net/minecraft/server/IDataManager.java b/src/main/java/net/minecraft/server/IDataManager.java new file mode 100644 index 0000000000..643a1e1a3a --- /dev/null +++ b/src/main/java/net/minecraft/server/IDataManager.java @@ -0,0 +1,26 @@ +package net.minecraft.server; + +import java.io.File; +import java.util.List; +import java.util.UUID; + +public interface IDataManager { + + WorldData c(); + + void b(); + + IChunkLoader a(WorldProvider worldprovider); + + void a(WorldData worlddata, List list); + + void a(WorldData worlddata); + + PlayerFileData d(); + + void e(); + + File b(String s); + + UUID getUUID(); +} diff --git a/src/main/java/net/minecraft/server/PlayerNBTManager.java b/src/main/java/net/minecraft/server/PlayerNBTManager.java new file mode 100644 index 0000000000..99b89fc29f --- /dev/null +++ b/src/main/java/net/minecraft/server/PlayerNBTManager.java @@ -0,0 +1,246 @@ +package net.minecraft.server; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.UUID; +import java.util.logging.Logger; + +public class PlayerNBTManager implements PlayerFileData, IDataManager { + + private static final Logger a = Logger.getLogger("Minecraft"); + private final File b; + private final File c; + private final File d; + private final long e = System.currentTimeMillis(); + + public PlayerNBTManager(File file1, String s, boolean flag) { + this.b = new File(file1, s); + this.b.mkdirs(); + this.c = new File(this.b, "players"); + this.d = new File(this.b, "data"); + this.d.mkdirs(); + if (flag) { + this.c.mkdirs(); + } + + this.f(); + } + + private void f() { + try { + File file1 = new File(this.b, "session.lock"); + DataOutputStream dataoutputstream = new DataOutputStream(new FileOutputStream(file1)); + + try { + dataoutputstream.writeLong(this.e); + } finally { + dataoutputstream.close(); + } + } catch (IOException ioexception) { + ioexception.printStackTrace(); + throw new RuntimeException("Failed to check session lock, aborting"); + } + } + + protected File a() { + return this.b; + } + + public void b() { + try { + File file1 = new File(this.b, "session.lock"); + DataInputStream datainputstream = new DataInputStream(new FileInputStream(file1)); + + try { + if (datainputstream.readLong() != this.e) { + throw new MinecraftException("The save is being accessed from another location, aborting"); + } + } finally { + datainputstream.close(); + } + } catch (IOException ioexception) { + throw new MinecraftException("Failed to check session lock, aborting"); + } + } + + public IChunkLoader a(WorldProvider worldprovider) { + if (worldprovider instanceof WorldProviderHell) { + File file1 = new File(this.b, "DIM-1"); + + file1.mkdirs(); + return new ChunkLoader(file1, true); + } else { + return new ChunkLoader(this.b, true); + } + } + + public WorldData c() { + File file1 = new File(this.b, "level.dat"); + NBTTagCompound nbttagcompound; + NBTTagCompound nbttagcompound1; + + if (file1.exists()) { + try { + nbttagcompound = CompressedStreamTools.a((InputStream) (new FileInputStream(file1))); + nbttagcompound1 = nbttagcompound.k("Data"); + return new WorldData(nbttagcompound1); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + file1 = new File(this.b, "level.dat_old"); + if (file1.exists()) { + try { + nbttagcompound = CompressedStreamTools.a((InputStream) (new FileInputStream(file1))); + nbttagcompound1 = nbttagcompound.k("Data"); + return new WorldData(nbttagcompound1); + } catch (Exception exception1) { + exception1.printStackTrace(); + } + } + + return null; + } + + public void a(WorldData worlddata, List list) { + NBTTagCompound nbttagcompound = worlddata.a(list); + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + + nbttagcompound1.a("Data", (NBTBase) nbttagcompound); + + try { + File file1 = new File(this.b, "level.dat_new"); + File file2 = new File(this.b, "level.dat_old"); + File file3 = new File(this.b, "level.dat"); + + CompressedStreamTools.a(nbttagcompound1, (OutputStream) (new FileOutputStream(file1))); + if (file2.exists()) { + file2.delete(); + } + + file3.renameTo(file2); + if (file3.exists()) { + file3.delete(); + } + + file1.renameTo(file3); + if (file1.exists()) { + file1.delete(); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + public void a(WorldData worlddata) { + NBTTagCompound nbttagcompound = worlddata.a(); + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + + nbttagcompound1.a("Data", (NBTBase) nbttagcompound); + + try { + File file1 = new File(this.b, "level.dat_new"); + File file2 = new File(this.b, "level.dat_old"); + File file3 = new File(this.b, "level.dat"); + + CompressedStreamTools.a(nbttagcompound1, (OutputStream) (new FileOutputStream(file1))); + if (file2.exists()) { + file2.delete(); + } + + file3.renameTo(file2); + if (file3.exists()) { + file3.delete(); + } + + file1.renameTo(file3); + if (file1.exists()) { + file1.delete(); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + public void a(EntityHuman entityhuman) { + try { + NBTTagCompound nbttagcompound = new NBTTagCompound(); + + entityhuman.d(nbttagcompound); + File file1 = new File(this.c, "_tmp_.dat"); + File file2 = new File(this.c, entityhuman.name + ".dat"); + + CompressedStreamTools.a(nbttagcompound, (OutputStream) (new FileOutputStream(file1))); + if (file2.exists()) { + file2.delete(); + } + + file1.renameTo(file2); + } catch (Exception exception) { + a.warning("Failed to save player data for " + entityhuman.name); + } + } + + public void b(EntityHuman entityhuman) { + NBTTagCompound nbttagcompound = this.a(entityhuman.name); + + if (nbttagcompound != null) { + entityhuman.e(nbttagcompound); + } + } + + public NBTTagCompound a(String s) { + try { + File file1 = new File(this.c, s + ".dat"); + + if (file1.exists()) { + return CompressedStreamTools.a((InputStream) (new FileInputStream(file1))); + } + } catch (Exception exception) { + a.warning("Failed to load player data for " + s); + } + + return null; + } + + public PlayerFileData d() { + return this; + } + + public void e() {} + + public File b(String s) { + return new File(this.d, s + ".dat"); + } + + // CraftBukkit start + public UUID getUUID() { + try { + File file1 = new File(this.b, "uid.dat"); + UUID id; + if(!file1.exists()) { + DataOutputStream dos = new DataOutputStream(new FileOutputStream(file1)); + id = UUID.randomUUID(); + dos.writeLong(id.getMostSignificantBits()); + dos.writeLong(id.getLeastSignificantBits()); + } + else { + DataInputStream dis = new DataInputStream(new FileInputStream(file1)); + id = new UUID(dis.readLong(), dis.readLong()); + } + return id; + } + catch (IOException ex) { + return null; + } + } + // CraftBukkit end +} diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java index aca1058d62..78e9002eba 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Random; import java.util.Set; import java.util.TreeSet; +import java.util.UUID; // CraftBukkit start import org.bukkit.Bukkit; @@ -2407,4 +2408,9 @@ public class World implements IBlockAccess { ((IWorldAccess) this.u.get(j1)).a(entityhuman, i, j, k, l, i1); } } + + // CraftBukkit start + public UUID getUUID() { + return this.w.getUUID(); + } } diff --git a/src/main/java/net/minecraft/server/WorldData.java b/src/main/java/net/minecraft/server/WorldData.java index bef6a94fdf..3e8ef772b6 100644 --- a/src/main/java/net/minecraft/server/WorldData.java +++ b/src/main/java/net/minecraft/server/WorldData.java @@ -1,7 +1,6 @@ package net.minecraft.server; import java.util.List; -import org.bukkit.Bukkit; public class WorldData { @@ -20,7 +19,6 @@ public class WorldData { private int m; private boolean n; private int o; - private long worldUID; // CraftBukkit public WorldData(NBTTagCompound nbttagcompound) { this.a = nbttagcompound.getLong("RandomSeed"); @@ -40,24 +38,11 @@ public class WorldData { this.h = nbttagcompound.k("Player"); this.i = this.h.e("Dimension"); } - // CraftBukkit start - if (nbttagcompound.hasKey("WorldUID")) { - this.worldUID = nbttagcompound.getLong("WorldUID"); - } else { - this.worldUID = (System.nanoTime() << 20) + this.a; - nbttagcompound.setLong("WorldUID", this.worldUID); - } - - if (Bukkit.getServer().getWorld(worldUID) != null) { - throw new IllegalStateException("World '" + name + "' contains a conflicting UID with existing world. Please edit its level.dat and remove WorldUID, or delete its level.dat (and lose its seed/etc)."); - } - // CraftBukkit end } public WorldData(long i, String s) { this.a = i; this.name = s; - this.worldUID = (System.nanoTime() << 20) + this.a; // CraftBukkit } public WorldData(WorldData worlddata) { @@ -120,7 +105,6 @@ public class WorldData { if (nbttagcompound1 != null) { nbttagcompound.a("Player", nbttagcompound1); } - nbttagcompound.setLong("WorldUID", this.worldUID); // CraftBukkit } public long getSeed() { @@ -208,10 +192,4 @@ public class WorldData { public void setWeatherDuration(int i) { this.m = i; } - - // CraftBukkit start - public long getWorldUID() { - return this.worldUID; - } - // CraftBukkit end } diff --git a/src/main/java/net/minecraft/server/WorldMap.java b/src/main/java/net/minecraft/server/WorldMap.java index 92eac2e753..6f2eff71be 100644 --- a/src/main/java/net/minecraft/server/WorldMap.java +++ b/src/main/java/net/minecraft/server/WorldMap.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; // CraftBukkit start import org.bukkit.Bukkit; @@ -25,7 +26,7 @@ public class WorldMap extends WorldMapBase { // CraftBukkit start private CraftServer server; - private long worldUID = 0L; + private UUID uniqueId = null; // CraftBukkit end public WorldMap(String s) { @@ -38,8 +39,13 @@ public class WorldMap extends WorldMapBase { byte dimension = nbttagcompound.c("dimension"); if (dimension >= 10) { - this.worldUID = nbttagcompound.getLong("WorldUID"); - CraftWorld world = (CraftWorld) server.getWorld(this.worldUID); + long least = nbttagcompound.getLong("UUIDLeast"); + long most = nbttagcompound.getLong("UUIDMost"); + + if (least != 0L && most != 0L) { + this.uniqueId = new UUID(most, least); + } + CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); // Check if the stored world details are correct. if (world == null) { /* All Maps which do not have their valid world loaded are set to a dimension which hopefully won't be reached. @@ -94,16 +100,17 @@ public class WorldMap extends WorldMapBase { public void b(NBTTagCompound nbttagcompound) { // CraftBukkit start if (this.map >= 10) { - if (this.worldUID == 0L) { + if (this.uniqueId == null) { for (org.bukkit.World world : server.getWorlds()) { CraftWorld cWorld = (CraftWorld) world; if (cWorld.getHandle().dimension == this.map) { - this.worldUID = cWorld.getUID(); + this.uniqueId = cWorld.getUID(); break; } } } - nbttagcompound.setLong("WorldUID", this.worldUID); + nbttagcompound.setLong("UUIDLeast", this.uniqueId.getLeastSignificantBits()); + nbttagcompound.setLong("UUIDMost", this.uniqueId.getMostSignificantBits()); } // CraftBukkit end nbttagcompound.a("dimension", this.map); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 0010117097..f50b13e9ea 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -24,6 +24,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import jline.ConsoleReader; @@ -494,9 +495,9 @@ public final class CraftServer implements Server { return worlds.get(name.toLowerCase()); } - public World getWorld(long uid) { + public World getWorld(UUID uid) { for (World world : worlds.values()) { - if (world.getUID() == uid) { + if (world.getUID().equals(uid)) { return world; } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index fac24e3eec..7170a9be4c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -8,6 +8,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Random; +import java.util.UUID; + import net.minecraft.server.*; import org.bukkit.entity.Arrow; @@ -400,8 +402,8 @@ public class CraftWorld implements World { return world.worldData.getSeed(); } - public long getUID() { - return world.worldData.getWorldUID(); + public UUID getUID() { + return world.getUUID(); } @Override