ViaBackwards/common/src/main/java/nl/matsv/viabackwards/api/rewriters/LegacyBlockItemRewriter.java

296 lines
12 KiB
Java
Raw Normal View History

/*
2016-10-03 15:40:19 +02:00
* Copyright (c) 2016 Matsv
*
2016-10-03 15:40:19 +02:00
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
2016-10-03 15:40:19 +02:00
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
2016-10-03 15:40:19 +02:00
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package nl.matsv.viabackwards.api.rewriters;
import nl.matsv.viabackwards.api.BackwardsProtocol;
import nl.matsv.viabackwards.api.data.MappedLegacyBlockItem;
import nl.matsv.viabackwards.api.data.VBMappingDataLoader;
2019-01-23 11:15:26 +01:00
import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.data.BlockColors;
import nl.matsv.viabackwards.utils.Block;
import org.jetbrains.annotations.Nullable;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.ChatRewriter;
2020-06-08 22:22:50 +02:00
import us.myles.viaversion.libs.fastutil.ints.Int2ObjectMap;
import us.myles.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import us.myles.viaversion.libs.gson.JsonElement;
import us.myles.viaversion.libs.gson.JsonObject;
import us.myles.viaversion.libs.gson.JsonPrimitive;
import us.myles.viaversion.libs.opennbt.tag.builtin.ByteTag;
import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import us.myles.viaversion.libs.opennbt.tag.builtin.IntTag;
2021-03-14 18:24:37 +01:00
import us.myles.viaversion.libs.opennbt.tag.builtin.NumberTag;
import us.myles.viaversion.libs.opennbt.tag.builtin.StringTag;
2020-06-03 11:20:17 +02:00
import us.myles.viaversion.libs.opennbt.tag.builtin.Tag;
2017-06-01 20:26:10 +02:00
import java.util.HashMap;
import java.util.Map;
public abstract class LegacyBlockItemRewriter<T extends BackwardsProtocol> extends ItemRewriterBase<T> {
2020-06-08 22:22:50 +02:00
private static final Map<String, Int2ObjectMap<MappedLegacyBlockItem>> LEGACY_MAPPINGS = new HashMap<>();
protected final Int2ObjectMap<MappedLegacyBlockItem> replacementData;
static {
JsonObject jsonObject = VBMappingDataLoader.loadFromDataDir("legacy-mappings.json");
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
2020-06-08 22:22:50 +02:00
Int2ObjectMap<MappedLegacyBlockItem> mappings = new Int2ObjectOpenHashMap<>(8);
LEGACY_MAPPINGS.put(entry.getKey(), mappings);
for (Map.Entry<String, JsonElement> dataEntry : entry.getValue().getAsJsonObject().entrySet()) {
JsonObject object = dataEntry.getValue().getAsJsonObject();
int id = object.getAsJsonPrimitive("id").getAsInt();
JsonPrimitive jsonData = object.getAsJsonPrimitive("data");
short data = jsonData != null ? jsonData.getAsShort() : 0;
String name = object.getAsJsonPrimitive("name").getAsString();
2020-02-01 12:44:56 +01:00
JsonPrimitive blockField = object.getAsJsonPrimitive("block");
boolean block = blockField != null && blockField.getAsBoolean();
2020-06-03 11:20:17 +02:00
if (dataEntry.getKey().indexOf('-') != -1) {
// Range of ids
String[] split = dataEntry.getKey().split("-", 2);
int from = Integer.parseInt(split[0]);
int to = Integer.parseInt(split[1]);
// Special block color handling
if (name.contains("%color%")) {
for (int i = from; i <= to; i++) {
2020-02-01 12:07:27 +01:00
mappings.put(i, new MappedLegacyBlockItem(id, data, name.replace("%color%", BlockColors.get(i - from)), block));
}
} else {
2020-02-01 12:07:27 +01:00
MappedLegacyBlockItem mappedBlockItem = new MappedLegacyBlockItem(id, data, name, block);
for (int i = from; i <= to; i++) {
mappings.put(i, mappedBlockItem);
}
}
} else {
2020-02-01 12:07:27 +01:00
mappings.put(Integer.parseInt(dataEntry.getKey()), new MappedLegacyBlockItem(id, data, name, block));
}
}
}
}
protected LegacyBlockItemRewriter(T protocol) {
2020-08-16 20:17:04 +02:00
super(protocol, false);
replacementData = LEGACY_MAPPINGS.get(protocol.getClass().getSimpleName().split("To")[1].replace("_", "."));
}
@Override
@Nullable
public Item handleItemToClient(Item item) {
if (item == null) return null;
MappedLegacyBlockItem data = replacementData.get(item.getIdentifier());
if (data == null) {
// Just rewrite the id
return super.handleItemToClient(item);
}
2017-06-01 20:26:10 +02:00
short originalData = item.getData();
item.setIdentifier(data.getId());
// Keep original data if mapped data is set to -1
if (data.getData() != -1) {
item.setData(data.getData());
}
// Set display name
if (data.getName() != null) {
if (item.getTag() == null) {
2021-03-14 18:24:37 +01:00
item.setTag(new CompoundTag());
}
CompoundTag display = item.getTag().get("display");
if (display == null) {
2021-03-14 18:24:37 +01:00
item.getTag().put("display", display = new CompoundTag());
}
StringTag nameTag = display.get("Name");
if (nameTag == null) {
2021-03-14 18:24:37 +01:00
display.put("Name", nameTag = new StringTag(data.getName()));
display.put(nbtTagName + "|customName", new ByteTag());
}
// Handle colors
String value = nameTag.getValue();
if (value.contains("%vb_color%")) {
2021-03-14 18:24:37 +01:00
display.put("Name", new StringTag(value.replace("%vb_color%", BlockColors.get(originalData))));
}
2017-06-03 11:47:08 +02:00
}
return item;
}
public int handleBlockID(int idx) {
2017-05-31 00:03:42 +02:00
int type = idx >> 4;
int meta = idx & 15;
Block b = handleBlock(type, meta);
if (b == null) return idx;
2017-05-31 00:03:42 +02:00
return (b.getId() << 4 | (b.getData() & 15));
}
@Nullable
public Block handleBlock(int blockId, int data) {
MappedLegacyBlockItem settings = replacementData.get(blockId);
if (settings == null || !settings.isBlock()) return null;
Block block = settings.getBlock();
2017-05-31 00:03:42 +02:00
// For some blocks, the data can still be useful (:
if (block.getData() == -1) {
return block.withData(data);
}
return block;
}
protected void handleChunk(Chunk chunk) {
2017-06-01 20:26:10 +02:00
// Map Block Entities
Map<Pos, CompoundTag> tags = new HashMap<>();
for (CompoundTag tag : chunk.getBlockEntities()) {
2020-06-03 11:20:17 +02:00
Tag xTag;
Tag yTag;
Tag zTag;
if ((xTag = tag.get("x")) == null || (yTag = tag.get("y")) == null || (zTag = tag.get("z")) == null) {
2017-06-01 20:26:10 +02:00
continue;
2020-06-03 11:20:17 +02:00
}
2017-06-01 20:26:10 +02:00
Pos pos = new Pos(
2021-03-14 18:24:37 +01:00
((NumberTag) xTag).asInt() & 0xF,
((NumberTag) yTag).asInt(),
((NumberTag) zTag).asInt() & 0xF);
2017-06-01 20:26:10 +02:00
tags.put(pos, tag);
2018-11-20 15:32:49 +01:00
// Handle given Block Entities
ChunkSection section = chunk.getSections()[pos.getY() >> 4];
if (section == null) continue;
2020-06-03 11:20:17 +02:00
2018-11-20 15:32:49 +01:00
int block = section.getFlatBlock(pos.getX(), pos.getY() & 0xF, pos.getZ());
int btype = block >> 4;
MappedLegacyBlockItem settings = replacementData.get(btype);
if (settings != null && settings.hasBlockEntityHandler()) {
settings.getBlockEntityHandler().handleOrNewCompoundTag(block, tag);
}
2017-06-01 20:26:10 +02:00
}
for (int i = 0; i < chunk.getSections().length; i++) {
ChunkSection section = chunk.getSections()[i];
if (section == null) continue;
2018-11-20 15:32:49 +01:00
boolean hasBlockEntityHandler = false;
// Map blocks
for (int j = 0; j < section.getPaletteSize(); j++) {
int block = section.getPaletteEntry(j);
int btype = block >> 4;
int meta = block & 0xF;
Block b = handleBlock(btype, meta);
if (b != null) {
2018-11-20 15:32:49 +01:00
section.setPaletteEntry(j, (b.getId() << 4) | (b.getData() & 0xF));
}
// We already know that is has a handler
if (hasBlockEntityHandler) continue;
MappedLegacyBlockItem settings = replacementData.get(btype);
if (settings != null && settings.hasBlockEntityHandler()) {
hasBlockEntityHandler = true;
}
2018-11-20 15:32:49 +01:00
}
if (!hasBlockEntityHandler) continue;
// We need to handle a Block Entity :(
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
2018-11-20 15:32:49 +01:00
int block = section.getFlatBlock(x, y, z);
int btype = block >> 4;
int meta = block & 15;
MappedLegacyBlockItem settings = replacementData.get(btype);
if (settings == null || !settings.hasBlockEntityHandler()) continue;
2018-11-20 15:32:49 +01:00
Pos pos = new Pos(x, (y + (i << 4)), z);
// Already handled above
if (tags.containsKey(pos)) continue;
2021-03-14 18:24:37 +01:00
CompoundTag tag = new CompoundTag();
tag.put("x", new IntTag(x + (chunk.getX() << 4)));
tag.put("y", new IntTag(y + (i << 4)));
tag.put("z", new IntTag(z + (chunk.getZ() << 4)));
settings.getBlockEntityHandler().handleOrNewCompoundTag(block, tag);
2018-11-20 15:32:49 +01:00
chunk.getBlockEntities().add(tag);
}
}
}
}
}
protected CompoundTag getNamedTag(String text) {
2021-03-14 18:24:37 +01:00
CompoundTag tag = new CompoundTag();
tag.put("display", new CompoundTag());
2020-11-24 10:56:24 +01:00
text = "§r" + text;
2021-03-14 18:24:37 +01:00
((CompoundTag) tag.get("display")).put("Name", new StringTag(jsonNameFormat ? ChatRewriter.legacyTextToJsonString(text) : text));
return tag;
}
private static final class Pos {
private final int x;
private final short y;
private final int z;
private Pos(int x, int y, int z) {
this.x = x;
this.y = (short) y;
this.z = z;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pos pos = (Pos) o;
if (x != pos.x) return false;
if (y != pos.y) return false;
return z == pos.z;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
result = 31 * result + z;
return result;
}
@Override
public String toString() {
return "Pos{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
}
2017-06-01 20:26:10 +02:00
}
}