Entity conversion

This commit is contained in:
Jesse Boyd 2017-10-09 23:52:04 +11:00
parent b2395f7aa9
commit d93f9f0553
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
12 changed files with 229 additions and 140 deletions

View File

@ -28,7 +28,7 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal4;
import com.boydti.fawe.object.changeset.AnvilHistory;
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
import com.boydti.fawe.object.mask.FaweBlockMatcher;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.SetQueue;

View File

@ -5,7 +5,7 @@ import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.jnbt.anvil.MCAFile;
import com.boydti.fawe.jnbt.anvil.MCAFilterCounter;
import com.boydti.fawe.jnbt.anvil.MutableMCABackedBaseBlock;
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.boydti.fawe.object.number.MutableLong;
import com.boydti.fawe.util.ReflectionUtils;
@ -84,9 +84,10 @@ public class RemapFilter extends MCAFilterCounter {
case PC: {
int newLight = 0;
switch (id) {
case 90:
case 90: {
pLocs.add(x, y, z);
if (pLocs.contains(x, y - 1, z) || pLocs.contains(x - 1, y, z) || pLocs.contains(x, y, z - 1)) break;
if (pLocs.contains(x, y - 1, z) || pLocs.contains(x - 1, y, z) || pLocs.contains(x, y, z - 1))
break;
Map<String, Tag> tag = new HashMap<>();
tag.put("Span", new ByteTag((byte) 1));
tag.put("TpX", new IntTag(x));
@ -98,8 +99,10 @@ public class RemapFilter extends MCAFilterCounter {
tag.put("Za", new ByteTag((byte) ((data == 2) ? 1 : 0)));
portals.add(new CompoundTag(tag));
break;
}
case 29:
case 33:
case 33: {
int data = block.getData();
Map<String, Object> map = new HashMap<>();
map.put("Progress", 1f);
map.put("State", (byte) 2);
@ -114,6 +117,7 @@ public class RemapFilter extends MCAFilterCounter {
map.put("z", z);
block.setNbtData(FaweCache.asTag(map));
break;
}
case 44:
case 182:
case 158:

View File

@ -1,99 +0,0 @@
package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.util.MainUtil;
import com.google.common.io.Resources;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.Map;
public class ItemWikiScraper {
private static String PE = "https://minecraft.gamepedia.com/index.php?title=Bedrock_Edition_data_values&action=edit&section=1";
private static String PC = "https://minecraft.gamepedia.com/index.php?title=Java_Edition_data_values/Item_IDs&action=edit";
private Map<ClipboardRemapper.RemapPlatform, Map<String, Integer>> cache = new HashMap<>();
public Map<String, Integer> expand(Map<String, Integer> map) {
HashMap<String, Integer> newMap = new HashMap<>(map);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
newMap.put(entry.getKey().replace("_", ""), entry.getValue());
}
return newMap;
}
public synchronized Map<String, Integer> scapeOrCache(ClipboardRemapper.RemapPlatform platform) throws IOException {
Map<String, Integer> map;
try {
Map<String, Integer> cached = cache.get(platform);
if (cached != null) return cached;
File file = new File("lib" + File.separator + "item-mappings-" + platform.name().toLowerCase() + ".json");
Gson gson = new Gson();
if (file.exists()) {
try {
String str = Resources.toString(file.toURL(), Charset.defaultCharset());
return gson.fromJson(str, new TypeToken<Map<String, Integer>>() {
}.getType());
} catch (Throwable ignore) {
ignore.printStackTrace();
}
}
map = scrape(platform);
java.io.File parent = file.getParentFile();
parent.mkdirs();
file.createNewFile();
Files.write(file.toPath(), gson.toJson(map).getBytes(), StandardOpenOption.CREATE);
} catch (IOException e) {
map = new HashMap<>();
}
cache.put(platform, map);
return map;
}
private Map<String, Integer> scrape(ClipboardRemapper.RemapPlatform platform) throws IOException {
String url = (platform == ClipboardRemapper.RemapPlatform.PC) ? PC : PE;
String text = MainUtil.getText(url);
String header = platform == ClipboardRemapper.RemapPlatform.PE ? "=== Item IDs ===" : "{{";
String footer = "{{-}}";
String prefix = "{{id table|";
HashMap<String, Integer> map = new HashMap<>();
int headerIndex = text.indexOf(header);
if (headerIndex == -1) return map;
int endIndex = text.indexOf(footer, headerIndex);
String part = text.substring(headerIndex, endIndex == -1 ? text.length() : endIndex);
int id = 255;
for (String line : part.split("\n")) {
String lower = line.toLowerCase();
if (lower.startsWith(prefix)) {
line = line.substring(prefix.length(), line.indexOf("}}"));
String[] split = line.split("\\|");
String nameId = null;
for (String entry : split) {
String[] pair = entry.split("=");
switch (pair[0].toLowerCase()) {
case "dv":
id = Integer.parseInt(pair[1]);
break;
case "nameid":
nameId = pair[1];
break;
}
}
if (nameId == null) nameId = split[0].toLowerCase().replace(' ', '_');
map.put(nameId, id);
}
id++;
}
return map;
}
}

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.object.clipboard;
package com.boydti.fawe.object.clipboard.remap;
import com.boydti.fawe.FaweCache;
import com.google.common.io.Resources;
@ -40,12 +40,12 @@ public class ClipboardRemapper {
this.from = null;
}
private ItemWikiScraper scraper;
private WikiScraper scraper;
private synchronized ItemWikiScraper loadItemMapping() throws IOException {
ItemWikiScraper tmp = scraper;
public synchronized WikiScraper loadItemMapping() throws IOException {
WikiScraper tmp = scraper;
if (tmp == null) {
scraper = tmp = new ItemWikiScraper();
scraper = tmp = new WikiScraper();
}
return tmp;
}
@ -60,9 +60,9 @@ public class ClipboardRemapper {
} else {
try {
name = name.replace("minecraft:", "");
ItemWikiScraper scraper = loadItemMapping();
Map<String, Integer> mapFrom = scraper.scapeOrCache(from);
Map<String, Integer> mapTo = scraper.scapeOrCache(from.opposite());
WikiScraper scraper = loadItemMapping();
Map<String, Integer> mapFrom = scraper.scapeOrCache(WikiScraper.Wiki.valueOf("ITEM_MAPPINGS_" + from.name()));
Map<String, Integer> mapTo = scraper.scapeOrCache(WikiScraper.Wiki.valueOf("ITEM_MAPPINGS_" + from.opposite().name()));
scraper.expand(mapTo);
switch (name) {
case "spruce_boat": return new BaseItem(333, (short) 1);
@ -100,7 +100,19 @@ public class ClipboardRemapper {
throw new UnsupportedOperationException("TODO");
}
public String remapEntityId(String id) {
public int remapEntityId(String id) {
try {
Map<String, Integer> mappings = loadItemMapping().scapeOrCache(WikiScraper.Wiki.ENTITY_MAPPINGS);
id = id.replace("minecraft:", "");
Integer legacyId = mappings.get(id);
if (legacyId != null) return legacyId;
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}
public String remapBlockEntityId(String id) {
if (from == null) return id;
switch (from) {
case PE: {

View File

@ -1,6 +1,8 @@
package com.boydti.fawe.object.clipboard;
package com.boydti.fawe.object.clipboard.remap;
import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.clipboard.AbstractDelegateFaweClipboard;
import com.boydti.fawe.object.clipboard.FaweClipboard;
import com.sk89q.worldedit.blocks.BaseBlock;
public class RemappedClipboard extends AbstractDelegateFaweClipboard {

View File

@ -0,0 +1,133 @@
package com.boydti.fawe.object.clipboard.remap;
import com.boydti.fawe.util.MainUtil;
import com.google.common.io.Resources;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.Map;
public class WikiScraper {
public enum Wiki {
ITEM_MAPPINGS_PE("https://minecraft.gamepedia.com/index.php?title=Bedrock_Edition_data_values&action=edit&section=1"),
ITEM_MAPPINGS_PC("https://minecraft.gamepedia.com/index.php?title=Java_Edition_data_values/Item_IDs&action=edit"),
ENTITY_MAPPINGS("https://minecraft.gamepedia.com/index.php?title=Bedrock_Edition_data_values&action=edit&section=4"),
;
public final String url;
Wiki(String url) {this.url = url;}
}
private Map<Wiki, Map<String, Integer>> cache = new HashMap<>();
public Map<String, Integer> expand(Map<String, Integer> map) {
HashMap<String, Integer> newMap = new HashMap<>(map);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
newMap.put(entry.getKey().replace("_", ""), entry.getValue());
}
return newMap;
}
protected String getName() {
return "item-mappings";
}
public synchronized Map<String, Integer> scapeOrCache(Wiki wiki) throws IOException {
Map<String, Integer> map;
try {
Map<String, Integer> cached = cache.get(wiki);
if (cached != null) return cached;
File file = new File("lib" + File.separator + wiki.name().toLowerCase().replace('_', '-') + ".json");
Gson gson = new Gson();
if (file.exists()) {
try {
String str = Resources.toString(file.toURL(), Charset.defaultCharset());
return gson.fromJson(str, new TypeToken<Map<String, Integer>>() {
}.getType());
} catch (Throwable ignore) {
ignore.printStackTrace();
}
}
map = scrape(wiki);
java.io.File parent = file.getParentFile();
parent.mkdirs();
file.createNewFile();
Files.write(file.toPath(), gson.toJson(map).getBytes(), StandardOpenOption.CREATE);
} catch (IOException e) {
map = new HashMap<>();
}
cache.put(wiki, map);
return map;
}
protected Map<String, Integer> scrape(Wiki wiki) throws IOException {
String url = wiki.url;
String text = MainUtil.getText(url);
HashMap<String, Integer> map = new HashMap<>();
if (wiki == Wiki.ENTITY_MAPPINGS) {
String header = "{|";
String footer = "|}";
int headerIndex = text.indexOf(header);
if (headerIndex == -1) return map;
int endIndex = text.indexOf(footer, headerIndex);
String part = text.substring(headerIndex, endIndex == -1 ? text.length() : endIndex);
// System.out.println(part);
for (String line : part.split("\n")) {
if (line.startsWith("| {{")) {
String[] split = line.split("\\|\\|");
if (split.length == 5) {
int id = Integer.parseInt(split[1].trim());
String name = split[3].trim();
map.put(name, id);
}
}
}
return map;
} else {
String header = wiki == Wiki.ITEM_MAPPINGS_PE ? "=== Item IDs ===" : "{{";
String footer = "{{-}}";
String prefix = "{{id table|";
int headerIndex = text.indexOf(header);
if (headerIndex == -1) return map;
int endIndex = text.indexOf(footer, headerIndex);
String part = text.substring(headerIndex, endIndex == -1 ? text.length() : endIndex);
int id = 255;
for (String line : part.split("\n")) {
String lower = line.toLowerCase();
if (lower.startsWith(prefix)) {
line = line.substring(prefix.length(), line.indexOf("}}"));
String[] split = line.split("\\|");
String nameId = null;
for (String entry : split) {
String[] pair = entry.split("=");
switch (pair[0].toLowerCase()) {
case "dv":
id = Integer.parseInt(pair[1]);
break;
case "nameid":
nameId = pair[1];
break;
}
}
if (nameId == null) nameId = split[0].toLowerCase().replace(' ', '_');
map.put(nameId, id);
}
id++;
}
return map;
}
}
}

View File

@ -11,10 +11,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* The {@code TAG_List} tag.
*/
public final class ListTag extends Tag {
public final class ListTag<T extends Tag> extends Tag {
private final Class<? extends Tag> type;
private final List<Tag> value;
private final Class<T> type;
private final List<T> value;
/**
* Creates the tag with an empty name.
@ -22,11 +22,11 @@ public final class ListTag extends Tag {
* @param type the type of tag
* @param value the value of the tag
*/
public ListTag(Class<? extends Tag> type, List<? extends Tag> value) {
public ListTag(Class<T> type, List<T> value) {
super();
checkNotNull(value);
this.type = type;
this.value = Collections.unmodifiableList(value);
this.value = value;
}
@Override
@ -43,12 +43,12 @@ public final class ListTag extends Tag {
*
* @return The type of item in this list.
*/
public Class<? extends Tag> getType() {
public Class<T> getType() {
return type;
}
@Override
public List<Tag> getValue() {
public List<T> getValue() {
return value;
}

View File

@ -23,7 +23,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Commands;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil;

View File

@ -128,7 +128,7 @@ public final class NBTConverter {
private static cn.nukkit.nbt.tag.ListTag toNative(ListTag tag) {
cn.nukkit.nbt.tag.ListTag list = new cn.nukkit.nbt.tag.ListTag();
for (Tag child : tag.getValue()) {
for (Tag child : (List<? extends Tag>) tag.getValue()) {
if (child instanceof EndTag) {
continue;
}

View File

@ -9,7 +9,7 @@ import com.boydti.fawe.jnbt.anvil.filters.DelegateMCAFilter;
import com.boydti.fawe.jnbt.anvil.filters.RemapFilter;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
import com.boydti.fawe.object.number.MutableLong;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.minecraft.util.commands.Command;

View File

@ -11,8 +11,7 @@ import com.boydti.fawe.installer.MinimizeButton;
import com.boydti.fawe.installer.MovablePanel;
import com.boydti.fawe.installer.TextAreaOutputStream;
import com.boydti.fawe.installer.URLButton;
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
import com.boydti.fawe.object.clipboard.ItemWikiScraper;
import com.boydti.fawe.object.clipboard.remap.WikiScraper;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.wrappers.FakePlayer;
import java.awt.BorderLayout;
@ -359,7 +358,7 @@ public class ConverterFrame extends JFrame {
if (dependenciesLoaded.get()) return;
try {
ExecutorService pool = Executors.newCachedThreadPool();
ItemWikiScraper scraper = new ItemWikiScraper();
WikiScraper scraper = new WikiScraper();
File lib = new File("lib");
File leveldb = new File(lib, "leveldb_v1.jar");
@ -376,7 +375,7 @@ public class ConverterFrame extends JFrame {
pool.submit((Runnable) () -> {
try {
scraper.scapeOrCache(ClipboardRemapper.RemapPlatform.PE);
scraper.scapeOrCache(WikiScraper.Wiki.ITEM_MAPPINGS_PE);
} catch (IOException e) {
e.printStackTrace();
}
@ -384,7 +383,15 @@ public class ConverterFrame extends JFrame {
pool.submit((Runnable) () -> {
try {
scraper.scapeOrCache(ClipboardRemapper.RemapPlatform.PC);
scraper.scapeOrCache(WikiScraper.Wiki.ITEM_MAPPINGS_PC);
} catch (IOException e) {
e.printStackTrace();
}
});
pool.submit((Runnable) () -> {
try {
scraper.scapeOrCache(WikiScraper.Wiki.ENTITY_MAPPINGS);
} catch (IOException e) {
e.printStackTrace();
}

View File

@ -9,7 +9,7 @@ import com.boydti.fawe.jnbt.anvil.MCAQueue;
import com.boydti.fawe.jnbt.anvil.filters.DelegateMCAFilter;
import com.boydti.fawe.jnbt.anvil.filters.RemapFilter;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
import com.boydti.fawe.object.io.LittleEndianOutputStream;
import com.boydti.fawe.object.number.MutableLong;
import com.boydti.fawe.util.MainUtil;
@ -432,7 +432,7 @@ public class MCAFile2LevelDB extends MapConverter {
List<com.sk89q.jnbt.Tag> tiles = new ArrayList<>();
for (Map.Entry<Short, CompoundTag> entry : chunk.getTiles().entrySet()) {
CompoundTag tag = entry.getValue();
if (transform(chunk, tag) && time != 0l) {
if (transform(chunk, tag, false) && time != 0l) {
// Needs tick
if (tickList == null) tickList = new ArrayList<>();
@ -464,7 +464,7 @@ public class MCAFile2LevelDB extends MapConverter {
if (!chunk.entities.isEmpty()) {
List<com.sk89q.jnbt.Tag> entities = new ArrayList<>();
for (CompoundTag tag : chunk.getEntities()) {
transform(chunk, tag);
transform(chunk, tag, true);
entities.add(tag);
}
update(getKey(chunk, Tag.Entity, dim), write(entities));
@ -590,13 +590,14 @@ public class MCAFile2LevelDB extends MapConverter {
Map<String, com.sk89q.jnbt.Tag> map = ReflectionUtils.getMap(item.getValue());
map.put("id", new ShortTag((short) remapped.getType()));
map.put("Damage", new ShortTag((short) remapped.getData()));
if (!map.containsKey("Count")) map.put("Count", new ByteTag((byte) 0));
CompoundTag tag = (CompoundTag) item.getValue().get("tag");
if (tag != null) {
Map<String, com.sk89q.jnbt.Tag> tagMap = ReflectionUtils.getMap(tag.getValue());
List<CompoundTag> enchants = (List) tag.getList("ench");
ListTag<CompoundTag> enchants = (ListTag<CompoundTag>) tagMap.get("ench");
if (enchants != null) {
for (CompoundTag ench : enchants) {
for (CompoundTag ench : enchants.getValue()) {
Map<String, com.sk89q.jnbt.Tag> value = ReflectionUtils.getMap(ench.getValue());
String id = ench.getString("id");
String lvl = ench.getString("lvl");
@ -612,19 +613,48 @@ public class MCAFile2LevelDB extends MapConverter {
return item;
}
private boolean transform(MCAChunk chunk, CompoundTag tag) {
private boolean transform(MCAChunk chunk, CompoundTag tag, boolean entity) {
try {
String id = tag.getString("id");
if (id != null) {
Map<String, com.sk89q.jnbt.Tag> map = ReflectionUtils.getMap(tag.getValue());
id = remapper.remapEntityId(id);
map.put("id", new StringTag(id));
if (map.containsKey("Pos")) {
map.put("id", new IntTag(11));
if (entity) {
int legacyId = remapper.remapEntityId(id);
if (legacyId != -1) map.put("id", new IntTag(legacyId));
} else {
id = remapper.remapBlockEntityId(id);
map.put("id", new StringTag(id));
}
{ // Hand items
com.sk89q.jnbt.ListTag items = (ListTag) map.remove("HandItems");
if (items != null) {
CompoundTag hand = transformItem((CompoundTag) items.getValue().get(0));
CompoundTag offHand = transformItem((CompoundTag) items.getValue().get(1));
map.put("Mainhand", hand);
map.put("Offhand", offHand);
}
}
{ // Convert armor
com.sk89q.jnbt.ListTag items = (ListTag) map.remove("ArmorItems");
if (items != null) {
((List<CompoundTag>) items.getValue()).forEach(this::transformItem);
Collections.reverse(items.getValue());
map.put("Armor", items);
}
}
{ // Convert items
com.sk89q.jnbt.ListTag items = tag.getListTag("Items");
((List<CompoundTag>) (List) items.getValue()).forEach(this::transformItem);
if (items != null) {
((List<CompoundTag>) items.getValue()).forEach(this::transformItem);
}
}
{ // Convert color
for (String key : new String[] {"color", "Color"}) {
com.sk89q.jnbt.Tag value = map.get(key);
if (value instanceof IntTag) {
map.put(key, new ByteTag((byte) (int) ((IntTag) value).getValue()));
}
}
}
{ // Convert item
String item = tag.getString("Item");