forked from BLOCKFANTASY/LOOHP-Limbo
reupload
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import com.loohp.limbo.location.Location;
|
||||
|
||||
public class BlockPosition {
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
|
||||
public BlockPosition(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
public static BlockPosition from(Location location) {
|
||||
return new BlockPosition((int) Math.floor(location.getX()), (int) Math.floor(location.getY()), (int) Math.floor(location.getZ()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
import net.querz.nbt.tag.StringTag;
|
||||
import net.querz.nbt.tag.Tag;
|
||||
|
||||
public class BlockState {
|
||||
|
||||
private CompoundTag tag;
|
||||
|
||||
public BlockState(CompoundTag tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public CompoundTag toCompoundTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public NamespacedKey getType() {
|
||||
return new NamespacedKey(tag.getString("Name"));
|
||||
}
|
||||
|
||||
public void setType(NamespacedKey namespacedKey) {
|
||||
tag.putString("Name", namespacedKey.toString());
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
Map<String, String> mapping = new HashMap<>();
|
||||
for (Entry<String, Tag<?>> entry : tag.getCompoundTag("Properties")) {
|
||||
String key = entry.getKey();
|
||||
String value = ((StringTag) entry.getValue()).getValue();
|
||||
mapping.put(key, value);
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public String getProperty(String key) {
|
||||
Tag<?> value = tag.getCompoundTag("Properties").get(key);
|
||||
return value == null ? null : ((StringTag) value).getValue();
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, String> mapping) {
|
||||
CompoundTag properties = new CompoundTag();
|
||||
for (Entry<String, String> entry : mapping.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
properties.putString(key, value);
|
||||
}
|
||||
tag.put("Properties", properties);
|
||||
}
|
||||
|
||||
public <T> void setProperty(String key, T value) {
|
||||
CompoundTag properties = tag.getCompoundTag("Properties");
|
||||
properties.putString(key, ((T) value).toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((tag == null) ? 0 : tag.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
BlockState other = (BlockState) obj;
|
||||
if (tag == null) {
|
||||
if (other.tag != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!tag.equals(other.tag)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.utils.CustomNBTUtils;
|
||||
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
|
||||
public class DimensionRegistry {
|
||||
|
||||
private CompoundTag defaultTag;
|
||||
private CompoundTag codec;
|
||||
private File reg;
|
||||
|
||||
public DimensionRegistry() {
|
||||
this.defaultTag = new CompoundTag();
|
||||
|
||||
String name = "dimension_registry.json";
|
||||
File file = new File(Limbo.getInstance().getInternalDataFolder(), name);
|
||||
if (!file.exists()) {
|
||||
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(name)) {
|
||||
Files.copy(in, file.toPath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
this.reg = file;
|
||||
|
||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(reg), StandardCharsets.UTF_8)) {
|
||||
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
||||
CompoundTag tag = CustomNBTUtils.getCompoundTagFromJson((JSONObject) json.get("value"));
|
||||
defaultTag = tag;
|
||||
codec = defaultTag.clone();
|
||||
} catch (IOException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return reg;
|
||||
}
|
||||
|
||||
public void resetCodec() {
|
||||
codec = defaultTag.clone();
|
||||
}
|
||||
|
||||
public CompoundTag getCodec() {
|
||||
return codec;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.loohp.limbo.utils.NamespacedKey;
|
||||
|
||||
public class Environment {
|
||||
|
||||
public static final Environment NORMAL = new Environment(new NamespacedKey("minecraft:overworld"), true);
|
||||
public static final Environment NETHER = new Environment(new NamespacedKey("minecraft:the_nether"), false);
|
||||
public static final Environment END = new Environment(new NamespacedKey("minecraft:the_end"), false);
|
||||
|
||||
public static final Set<Environment> REGISTERED_ENVIRONMENTS = new HashSet<>();
|
||||
|
||||
public static Environment fromNamespacedKey(NamespacedKey key) {
|
||||
if (key.equals(NORMAL.getNamespacedKey())) {
|
||||
return NORMAL;
|
||||
} else if (key.equals(NETHER.getNamespacedKey())) {
|
||||
return NETHER;
|
||||
} else if (key.equals(END.getNamespacedKey())) {
|
||||
return END;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Environment createCustom(NamespacedKey key) {
|
||||
return createCustom(key, true);
|
||||
}
|
||||
|
||||
public static Environment createCustom(NamespacedKey key, boolean hasSkyLight) {
|
||||
if (REGISTERED_ENVIRONMENTS.stream().anyMatch(each -> each.getNamespacedKey().equals(key))) {
|
||||
throw new IllegalArgumentException("An Environment is already created with this NamespacedKey");
|
||||
}
|
||||
return new Environment(key, hasSkyLight);
|
||||
}
|
||||
|
||||
public static Environment getCustom(NamespacedKey key) {
|
||||
return REGISTERED_ENVIRONMENTS.stream().filter(each -> each.getNamespacedKey().equals(key)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
//=========================
|
||||
|
||||
private NamespacedKey key;
|
||||
private boolean hasSkyLight;
|
||||
|
||||
private Environment(NamespacedKey key, boolean hasSkyLight) {
|
||||
this.key = key;
|
||||
this.hasSkyLight = hasSkyLight;
|
||||
}
|
||||
|
||||
public NamespacedKey getNamespacedKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public boolean hasSkyLight() {
|
||||
return hasSkyLight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (hasSkyLight ? 1231 : 1237);
|
||||
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Environment other = (Environment) obj;
|
||||
if (hasSkyLight != other.hasSkyLight) {
|
||||
return false;
|
||||
}
|
||||
if (key == null) {
|
||||
if (other.key != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!key.equals(other.key)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
|
||||
public class GeneratedBlockDataMappings {
|
||||
|
||||
private static JSONObject globalPalette = new JSONObject();
|
||||
|
||||
static {
|
||||
String block = "blocks.json";
|
||||
File file = new File(Limbo.getInstance().getInternalDataFolder(), block);
|
||||
if (!file.exists()) {
|
||||
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(block)) {
|
||||
Files.copy(in, file.toPath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
globalPalette = (JSONObject) new JSONParser().parse(new FileReader(file));
|
||||
} catch (IOException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static int getGlobalPaletteIDFromState(CompoundTag tag) {
|
||||
String blockname = tag.getString("Name");
|
||||
|
||||
JSONObject data = (JSONObject) globalPalette.get(blockname);
|
||||
Object obj = data.get("properties");
|
||||
if (obj == null) {
|
||||
return (int) (long) ((JSONObject) ((JSONArray) data.get("states")).get(0)).get("id");
|
||||
}
|
||||
|
||||
//JSONObject properties = (JSONObject) obj;
|
||||
|
||||
if (tag.containsKey("Properties")) {
|
||||
CompoundTag blockProp = tag.get("Properties", CompoundTag.class);
|
||||
Map<String, String> blockstate = new HashMap<>();
|
||||
for (String key : blockProp.keySet()) {
|
||||
blockstate.put(key, blockProp.getString(key));
|
||||
}
|
||||
|
||||
for (Object entry : (JSONArray) data.get("states")) {
|
||||
JSONObject jsonobj = (JSONObject) entry;
|
||||
if (((JSONObject) jsonobj.get("properties")).keySet().stream().allMatch(key -> blockstate.get(key).equals((String) (((JSONObject) jsonobj.get("properties")).get(key))))) {
|
||||
return (int) (long) jsonobj.get("id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Object entry : (JSONArray) data.get("states")) {
|
||||
if (((JSONObject) entry).containsKey("default") && ((boolean) ((JSONObject) entry).get("default"))) {
|
||||
return (int) (long) ((JSONObject) entry).get("id");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class LightEngine {
|
||||
|
||||
private static Map<String, Byte> blockLightLevelMapping = new HashMap<>();
|
||||
|
||||
static {
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:torch", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
blockLightLevelMapping.put("minecraft:beacon", (byte) 15);
|
||||
|
||||
}
|
||||
|
||||
public static int getBlockLight(BlockState block) {
|
||||
return blockLightLevelMapping.getOrDefault(block.getType().toString(), (byte) 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LightEngineBlock extends LightEngine {
|
||||
|
||||
private World world;
|
||||
private byte[][][] blockLightArray;
|
||||
|
||||
public LightEngineBlock(World world) {
|
||||
blockLightArray = new byte[world.getChunkWidth() * 16][16 * 18][world.getChunkLength() * 16];
|
||||
this.world = world;
|
||||
updateWorld();
|
||||
}
|
||||
|
||||
public void updateWorld() {
|
||||
blockLightArray = new byte[world.getChunkWidth() * 16][16 * 18][world.getChunkLength() * 16];
|
||||
for (int x = 0; x < world.getWidth(); x++) {
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int z = 0; z < world.getLength(); z++) {
|
||||
updateBlock(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBlock(int x, int y, int z) {
|
||||
BlockState block = world.getBlock(x, y, z);
|
||||
int lightLevel = getBlockLight(block);
|
||||
if (lightLevel > 0) {
|
||||
propergate(lightLevel, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private void propergate(int level, int x, int y, int z) {
|
||||
try {
|
||||
if (blockLightArray[x][y + 16][z] < level) {
|
||||
blockLightArray[x][y + 16][z] = (byte) level;
|
||||
if (level > 1) {
|
||||
try {propergate(level - 1, x + 1, y, z);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x - 1, y, z);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x, y + 1, z);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x, y - 1, z);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x, y, z + 1);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x, y, z - 1);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
}
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
}
|
||||
|
||||
public List<Byte[]> getBlockLightBitMask(int chunkX, int chunkZ) {
|
||||
List<Byte[]> subchunks = new ArrayList<>(18);
|
||||
int startX = chunkX * 16;
|
||||
int endingX = startX + 16;
|
||||
int startZ = chunkZ * 16;
|
||||
int endingZ = startZ + 16;
|
||||
|
||||
for (int sub = 17; sub >= 0; sub--) {
|
||||
List<Byte> array = new ArrayList<>();
|
||||
for (int y = sub * 16; y < (sub * 16) + 16; y++) {
|
||||
for (int z = startZ; z < endingZ; z++) {
|
||||
for (int x = startX; x < endingX; x += 2) {
|
||||
int bit = blockLightArray[x][y][z];
|
||||
bit = bit << 4;
|
||||
bit |= blockLightArray[x + 1][y][z];
|
||||
array.add((byte) bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
subchunks.add(array.toArray(new Byte[2048]));
|
||||
}
|
||||
|
||||
return subchunks;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LightEngineSky extends LightEngine {
|
||||
|
||||
private World world;
|
||||
private byte[][][] skyLightArray;
|
||||
|
||||
public LightEngineSky(World world) {
|
||||
skyLightArray = new byte[world.getChunkWidth() * 16][16 * 18][world.getChunkLength() * 16];
|
||||
/*
|
||||
for (byte[][] arrayarray : skyLightArray) {
|
||||
for (byte[] array : arrayarray) {
|
||||
Arrays.fill(array, (byte) 0);
|
||||
}
|
||||
}
|
||||
*/
|
||||
this.world = world;
|
||||
updateWorld();
|
||||
}
|
||||
|
||||
public void updateWorld() {
|
||||
skyLightArray = new byte[world.getChunkWidth() * 16][16 * 18][world.getChunkLength() * 16];
|
||||
for (int x = 0; x < world.getWidth(); x++) {
|
||||
for (int z = 0; z < world.getLength(); z++) {
|
||||
updateColumn(x, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateColumn(int x, int z) {
|
||||
for (int y = 272; y >= 256; y--) {
|
||||
propergate(15, x, y, z);
|
||||
}
|
||||
for (int y = 255; y >= 0; y--) {
|
||||
BlockState block = world.getBlock(x, y, z);
|
||||
//System.out.println("X:" + x + " Y: " + y + " Z: " + z + " Block: " + block.getType().toString());
|
||||
if (!block.getType().toString().equals("minecraft:air")) {
|
||||
break;
|
||||
}
|
||||
propergate(15, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private void propergate(int level, int x, int y, int z) {
|
||||
try {
|
||||
if (skyLightArray[x][y + 16][z] < level) {
|
||||
skyLightArray[x][y + 16][z] = (byte) level;
|
||||
if (level > 1) {
|
||||
try {propergate(level - 1, x + 1, y, z);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x - 1, y, z);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x, y + 1, z);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x, y, z + 1);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
try {propergate(level - 1, x, y, z - 1);} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
}
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {}
|
||||
}
|
||||
|
||||
public List<Byte[]> getSkyLightBitMask(int chunkX, int chunkZ) {
|
||||
List<Byte[]> subchunks = new ArrayList<>(18);
|
||||
int startX = chunkX * 16;
|
||||
int endingX = startX + 16;
|
||||
int startZ = chunkZ * 16;
|
||||
int endingZ = startZ + 16;
|
||||
|
||||
for (int sub = 17; sub >= 0; sub--) {
|
||||
List<Byte> array = new ArrayList<>();
|
||||
for (int y = sub * 16; y < (sub * 16) + 16; y++) {
|
||||
for (int z = startZ; z < endingZ; z++) {
|
||||
for (int x = startX; x < endingX; x += 2) {
|
||||
int bit = skyLightArray[x][y][z];
|
||||
bit = bit << 4;
|
||||
bit |= skyLightArray[x + 1][y][z];
|
||||
array.add((byte) bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
subchunks.add(array.toArray(new Byte[2048]));
|
||||
}
|
||||
|
||||
return subchunks;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import com.loohp.limbo.utils.SchematicConvertionUtils;
|
||||
|
||||
import net.querz.mca.Chunk;
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
import net.querz.nbt.tag.ListTag;
|
||||
|
||||
|
||||
public class Schematic {
|
||||
|
||||
public static World toWorld(String name, Environment environment, CompoundTag nbt) {
|
||||
short width = nbt.getShort("Width");
|
||||
short length = nbt.getShort("Length");
|
||||
//short height = nbt.getShort("Height");
|
||||
byte[] blockdata = nbt.getByteArray("BlockData");
|
||||
CompoundTag palette = nbt.getCompoundTag("Palette");
|
||||
ListTag<CompoundTag> blockEntities = nbt.containsKey("BlockEntities") ? nbt.getListTag("BlockEntities").asTypedList(CompoundTag.class) : null;
|
||||
Map<Integer, String> mapping = new HashMap<>();
|
||||
for (String key : palette.keySet()) {
|
||||
mapping.put(palette.getInt(key), key);
|
||||
}
|
||||
|
||||
World world = new World(name, width, length, environment);
|
||||
|
||||
int index = 0;
|
||||
int i = 0;
|
||||
int value = 0;
|
||||
int varint_length = 0;
|
||||
while (i < blockdata.length) {
|
||||
value = 0;
|
||||
varint_length = 0;
|
||||
|
||||
while (true) {
|
||||
value |= (blockdata[i] & 127) << (varint_length++ * 7);
|
||||
if (varint_length > 5) {
|
||||
throw new RuntimeException("VarInt too big (probably corrupted data)");
|
||||
}
|
||||
if ((blockdata[i] & 128) != 128) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// index = (y * length + z) * width + x
|
||||
int y = index / (width * length);
|
||||
int z = (index % (width * length)) / width;
|
||||
int x = (index % (width * length)) % width;
|
||||
world.setBlock(x, y, z, mapping.get(value));
|
||||
|
||||
Chunk chunk = world.getChunkAtWorldPos(x, z);
|
||||
|
||||
if (blockEntities != null) {
|
||||
Iterator<CompoundTag> itr = blockEntities.iterator();
|
||||
while (itr.hasNext()) {
|
||||
CompoundTag tag = itr.next();
|
||||
int[] pos = tag.getIntArray("Pos");
|
||||
|
||||
if (pos[0] == x && pos[1] == y && pos[2] == z) {
|
||||
ListTag<CompoundTag> newTag = chunk.getTileEntities();
|
||||
newTag.add(SchematicConvertionUtils.toTileEntityTag(tag));
|
||||
chunk.setTileEntities(newTag);
|
||||
itr.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
for (Chunk[] chunkarray : world.getChunks()) {
|
||||
for (Chunk chunk : chunkarray) {
|
||||
if (chunk != null) {
|
||||
CompoundTag heightMap = new CompoundTag();
|
||||
heightMap.putLongArray("MOTION_BLOCKING", new long[] {1371773531765642314L,1389823183635651148L,1371738278539598925L,1389823183635388492L,1353688558756731469L,1389823114781694027L,1317765589597723213L,1371773531899860042L,1389823183635651149L,1371773462911685197L,1389823183635650636L,1353688626805119565L,1371773531900123211L,1335639250618849869L,1371738278674077258L,1389823114781694028L,1353723811310638154L,1371738278674077259L,1335674228429068364L,1335674228429067338L,1335674228698027594L,1317624576693539402L,1335709481520370249L,1299610178184057417L,1335638906349064264L,1299574993811968586L,1299574924958011464L,1299610178184056904L,1299574924958011464L,1299610109330100296L,1299574924958011464L,1299574924823793736L,1299574924958011465L,1281525273222484040L,1299574924958011464L,1281525273222484040L,9548107335L});
|
||||
chunk.setHeightMaps(heightMap);
|
||||
chunk.setBiomes(new int[256]);
|
||||
chunk.cleanupPalettesAndBlockStates();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
world.getLightEngineBlock().updateWorld();
|
||||
if (world.hasSkyLight()) {
|
||||
world.getLightEngineSky().updateWorld();
|
||||
}
|
||||
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import com.loohp.limbo.entity.DataWatcher;
|
||||
import com.loohp.limbo.entity.Entity;
|
||||
|
||||
@Deprecated
|
||||
public class Unsafe {
|
||||
|
||||
private Unsafe() {}
|
||||
|
||||
@Deprecated
|
||||
public void a(World a, Entity b) {
|
||||
a.removeEntity(b);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public DataWatcher b(World a, Entity b) {
|
||||
return a.getDataWatcher(b);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
package com.loohp.limbo.world;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.server.packets.PacketPlayOutEntityDestroy;
|
||||
import com.loohp.limbo.server.packets.PacketPlayOutEntityMetadata;
|
||||
import com.loohp.limbo.entity.ArmorStand;
|
||||
import com.loohp.limbo.entity.DataWatcher;
|
||||
import com.loohp.limbo.entity.Entity;
|
||||
import com.loohp.limbo.entity.EntityType;
|
||||
import com.loohp.limbo.entity.DataWatcher.WatchableObject;
|
||||
import com.loohp.limbo.location.Location;
|
||||
import com.loohp.limbo.player.Player;
|
||||
import com.loohp.limbo.utils.SchematicConvertionUtils;
|
||||
|
||||
import net.querz.mca.Chunk;
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
import net.querz.nbt.tag.ListTag;
|
||||
|
||||
public class World {
|
||||
|
||||
private String name;
|
||||
private Environment environment;
|
||||
private Chunk[][] chunks;
|
||||
private int width;
|
||||
private int length;
|
||||
private LightEngineBlock lightEngineBlock;
|
||||
private LightEngineSky lightEngineSky;
|
||||
private Map<Entity, DataWatcher> entities;
|
||||
|
||||
public World(String name, int width, int length, Environment environment) {
|
||||
this.name = name;
|
||||
this.environment = environment;
|
||||
this.chunks = new Chunk[(width >> 4) + 1][(length >> 4) + 1];
|
||||
this.width = width;
|
||||
this.length = length;
|
||||
|
||||
for (int x = 0; x < chunks.length; x++) {
|
||||
for (int z = 0; z < chunks[x].length; z++) {
|
||||
chunks[x][z] = Chunk.newChunk();
|
||||
Chunk chunk = chunks[x][z];
|
||||
chunk.cleanupPalettesAndBlockStates();
|
||||
CompoundTag heightMap = new CompoundTag();
|
||||
heightMap.putLongArray("MOTION_BLOCKING",
|
||||
new long[] {1371773531765642314L, 1389823183635651148L, 1371738278539598925L,
|
||||
1389823183635388492L, 1353688558756731469L, 1389823114781694027L, 1317765589597723213L,
|
||||
1371773531899860042L, 1389823183635651149L, 1371773462911685197L, 1389823183635650636L,
|
||||
1353688626805119565L, 1371773531900123211L, 1335639250618849869L, 1371738278674077258L,
|
||||
1389823114781694028L, 1353723811310638154L, 1371738278674077259L, 1335674228429068364L,
|
||||
1335674228429067338L, 1335674228698027594L, 1317624576693539402L, 1335709481520370249L,
|
||||
1299610178184057417L, 1335638906349064264L, 1299574993811968586L, 1299574924958011464L,
|
||||
1299610178184056904L, 1299574924958011464L, 1299610109330100296L, 1299574924958011464L,
|
||||
1299574924823793736L, 1299574924958011465L, 1281525273222484040L, 1299574924958011464L,
|
||||
1281525273222484040L, 9548107335L});
|
||||
chunk.setHeightMaps(heightMap);
|
||||
chunk.setBiomes(new int[256]);
|
||||
chunk.setTileEntities(new ListTag<CompoundTag>(CompoundTag.class));
|
||||
}
|
||||
}
|
||||
|
||||
this.lightEngineBlock = new LightEngineBlock(this);
|
||||
if (environment.hasSkyLight()) {
|
||||
this.lightEngineSky = new LightEngineSky(this);
|
||||
}
|
||||
|
||||
this.entities = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public LightEngineBlock getLightEngineBlock() {
|
||||
return lightEngineBlock;
|
||||
}
|
||||
|
||||
public LightEngineSky getLightEngineSky() {
|
||||
return lightEngineSky;
|
||||
}
|
||||
|
||||
public boolean hasSkyLight() {
|
||||
return lightEngineSky != null;
|
||||
}
|
||||
|
||||
protected void setBlock(int x, int y, int z, String blockdata) {
|
||||
Chunk chunk = this.chunks[(x >> 4)][(z >> 4)];
|
||||
if (chunk == null) {
|
||||
chunk = Chunk.newChunk();
|
||||
this.chunks[(x >> 4)][(z >> 4)] = chunk;
|
||||
}
|
||||
CompoundTag block = SchematicConvertionUtils.toBlockTag(blockdata);
|
||||
chunk.setBlockStateAt(x, y, z, block, false);
|
||||
}
|
||||
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
Chunk chunk = this.chunks[(x >> 4)][(z >> 4)];
|
||||
if (chunk == null) {
|
||||
chunk = Chunk.newChunk();
|
||||
this.chunks[(x >> 4)][(z >> 4)] = chunk;
|
||||
}
|
||||
|
||||
CompoundTag tag = chunk.getBlockStateAt(x, y, z);
|
||||
if (tag == null) {
|
||||
tag = new CompoundTag();
|
||||
tag.putString("Name", "minecraft:air");
|
||||
}
|
||||
return new BlockState(tag);
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, BlockState state) {
|
||||
Chunk chunk = this.chunks[(x >> 4)][(z >> 4)];
|
||||
if (chunk == null) {
|
||||
chunk = Chunk.newChunk();
|
||||
this.chunks[(x >> 4)][(z >> 4)] = chunk;
|
||||
}
|
||||
chunk.setBlockStateAt(x % 16, y % 16, z % 16, state.toCompoundTag(), false);
|
||||
}
|
||||
|
||||
public Chunk[][] getChunks() {
|
||||
return this.chunks;
|
||||
}
|
||||
|
||||
public Chunk getChunkAtWorldPos(int x, int z) {
|
||||
return this.chunks[(x >> 4)][(z >> 4)];
|
||||
}
|
||||
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
if (x < 0 || z < 0 || x >= chunks.length || z >= chunks[x].length) {
|
||||
return null;
|
||||
}
|
||||
return this.chunks[x][z];
|
||||
}
|
||||
|
||||
public int getChunkX(Chunk chunk) {
|
||||
for (int x = 0; x < chunks.length; x++) {
|
||||
for (int z = 0; z < chunks[x].length; z++) {
|
||||
Chunk c = getChunkAt(x, z);
|
||||
if (c.equals(chunk)) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public int getChunkZ(Chunk chunk) {
|
||||
for (int x = 0; x < chunks.length; x++) {
|
||||
for (int z = 0; z < chunks[x].length; z++) {
|
||||
Chunk c = getChunkAt(x, z);
|
||||
if (c.equals(chunk)) {
|
||||
return z;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public int[] getChunkXZ(Chunk chunk) {
|
||||
for (int x = 0; x < chunks.length; x++) {
|
||||
for (int z = 0; z < chunks[x].length; z++) {
|
||||
Chunk c = getChunkAt(x, z);
|
||||
if (c.equals(chunk)) {
|
||||
return new int[] {x, z};
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Environment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public int getChunkWidth() {
|
||||
return (width >> 4) + 1;
|
||||
}
|
||||
|
||||
public int getChunkLength() {
|
||||
return (length >> 4) + 1;
|
||||
}
|
||||
|
||||
public Set<Entity> getEntities() {
|
||||
return Collections.unmodifiableSet(entities.keySet());
|
||||
}
|
||||
|
||||
public Entity spawnEntity(EntityType type, Location location) {
|
||||
if (!location.getWorld().equals(this)) {
|
||||
throw new IllegalArgumentException("Location not in world.");
|
||||
}
|
||||
Entity entity;
|
||||
switch (type) {
|
||||
case ARMOR_STAND:
|
||||
entity = new ArmorStand(location);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("This EntityType cannot be summoned.");
|
||||
}
|
||||
entities.put(entity, new DataWatcher(entity));
|
||||
return entity;
|
||||
}
|
||||
|
||||
public Entity addEntity(Entity entity) {
|
||||
if (entity.getWorld().equals(this)) {
|
||||
entities.put(entity, new DataWatcher(entity));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Location not in world.");
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public List<Player> getPlayers() {
|
||||
return Limbo.getInstance().getPlayers().stream().filter(each -> each.getWorld().equals(this)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected void removeEntity(Entity entity) {
|
||||
entities.remove(entity);
|
||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(entity.getEntityId());
|
||||
for (Player player : getPlayers()) {
|
||||
try {
|
||||
player.clientConnection.sendPacket(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected DataWatcher getDataWatcher(Entity entity) {
|
||||
return entities.get(entity);
|
||||
}
|
||||
|
||||
public void update() throws IllegalArgumentException, IllegalAccessException {
|
||||
for (DataWatcher watcher : entities.values()) {
|
||||
if (watcher.getEntity().getWorld().equals(this)) {
|
||||
Map<Field, WatchableObject> updated = watcher.update();
|
||||
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(watcher.getEntity(), false, updated.keySet().toArray(new Field[0]));
|
||||
for (Player player : getPlayers()) {
|
||||
try {
|
||||
player.clientConnection.sendPacket(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(watcher.getEntity().getEntityId());
|
||||
for (Player player : getPlayers()) {
|
||||
try {
|
||||
player.clientConnection.sendPacket(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
entities.remove(watcher.getEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.deepHashCode(chunks);
|
||||
result = prime * result + ((environment == null) ? 0 : environment.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
World other = (World) obj;
|
||||
if (!Arrays.deepEquals(chunks, other.chunks)) {
|
||||
return false;
|
||||
}
|
||||
if (environment != other.environment) {
|
||||
return false;
|
||||
}
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user