feat: using the new safe getter api

This commit is contained in:
daoge_cmd 2024-09-20 19:47:49 +08:00
parent 4bad8f702c
commit af2ac64cd4
4 changed files with 33 additions and 60 deletions

View File

@ -6,7 +6,10 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.allaymc.api.block.type.BlockState; import org.allaymc.api.block.type.BlockState;
import org.allaymc.api.block.type.BlockStateSafeGetter;
import org.allaymc.api.block.type.BlockTypes; import org.allaymc.api.block.type.BlockTypes;
import org.allaymc.api.item.type.ItemType;
import org.allaymc.api.item.type.ItemTypeSafeGetter;
import org.allaymc.api.registry.Registries; import org.allaymc.api.registry.Registries;
import org.allaymc.api.utils.HashUtils; import org.allaymc.api.utils.HashUtils;
import org.allaymc.api.utils.JSONUtils; import org.allaymc.api.utils.JSONUtils;
@ -28,8 +31,7 @@ public final class Mapping {
private static final Map<String, Map<String, String>> JE_BLOCK_DEFAULT_PROPERTIES = new Object2ObjectOpenHashMap<>(); private static final Map<String, Map<String, String>> JE_BLOCK_DEFAULT_PROPERTIES = new Object2ObjectOpenHashMap<>();
private static final Map<BlockState, JeBlockState> BLOCK_STATE_BE_TO_JE = new Object2ObjectOpenHashMap<>(); private static final Map<BlockState, JeBlockState> BLOCK_STATE_BE_TO_JE = new Object2ObjectOpenHashMap<>();
private static final Map<Integer, BlockState> BLOCK_STATE_JE_HASH_TO_BE = new Int2ObjectOpenHashMap<>(); private static final Map<Integer, BlockState> BLOCK_STATE_JE_HASH_TO_BE = new Int2ObjectOpenHashMap<>();
private static final Map<String, String> ITEM_ID_JE_TO_BE = new Object2ObjectOpenHashMap<>(); private static final Map<String, ItemType<?>> ITEM_ID_JE_TO_BE = new Object2ObjectOpenHashMap<>();
private static final Map<String, Integer> JE_ITEM_ID_TO_BE_ITEM_META = new Object2IntOpenHashMap<>();
private static final Map<String, Integer> BIOME_ID_JE_TO_BE = new Object2IntOpenHashMap<>(); private static final Map<String, Integer> BIOME_ID_JE_TO_BE = new Object2IntOpenHashMap<>();
private static final BlockState BE_AIR_STATE = BlockTypes.AIR.getDefaultState(); private static final BlockState BE_AIR_STATE = BlockTypes.AIR.getDefaultState();
@ -69,15 +71,12 @@ public final class Mapping {
} }
var mappings = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, Object>>>(){}).entrySet(); var mappings = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, Object>>>(){}).entrySet();
for(var mapping : mappings) { for(var mapping : mappings) {
var updatedNBT = ItemStateUpdaters.updateItemState( var item = ItemTypeSafeGetter
NbtMap.builder() .name((String) mapping.getValue().get("bedrock_identifier"))
.putString("Name", (String) mapping.getValue().get("bedrock_identifier")) // NOTICE: Should be cast to double
.putInt("Damage", ((Double) mapping.getValue().get("bedrock_data")).intValue()) .meta(((Double) mapping.getValue().get("bedrock_data")).intValue())
.build(), .itemType();
ItemStateUpdaters.LATEST_VERSION ITEM_ID_JE_TO_BE.put(mapping.getKey(), item);
);
ITEM_ID_JE_TO_BE.put(mapping.getKey(), updatedNBT.getString("Name"));
JE_ITEM_ID_TO_BE_ITEM_META.put(mapping.getKey(), updatedNBT.getInt("Damage"));
} }
} catch(IOException e) { } catch(IOException e) {
log.error("Failed to load mapping", e); log.error("Failed to load mapping", e);
@ -91,6 +90,7 @@ public final class Mapping {
log.error("blocks mapping not found"); log.error("blocks mapping not found");
return false; return false;
} }
// noinspection unchecked
var mappings = (List<Map<String, Map<String, Object>>>) JSONUtils.from(stream, new TypeToken<Map<String, Object>>(){}).get("mappings"); var mappings = (List<Map<String, Map<String, Object>>>) JSONUtils.from(stream, new TypeToken<Map<String, Object>>(){}).get("mappings");
for(var mapping : mappings) { for(var mapping : mappings) {
var jeState = createJeBlockState(mapping.get("java_state")); var jeState = createJeBlockState(mapping.get("java_state"));
@ -123,47 +123,23 @@ public final class Mapping {
} }
private static BlockState createBeBlockState(Map<String, Object> data) { private static BlockState createBeBlockState(Map<String, Object> data) {
var builder = NbtMap.builder(); var getter = BlockStateSafeGetter
builder.putString("name", "minecraft:" + data.get("bedrock_identifier")); .name("minecraft:" + data.get("bedrock_identifier"));
if (data.containsKey("state")) {
Map<String, Object> state = (Map<String, Object>) data.get("state"); // noinspection unchecked
builder.put("states", state != null ? NbtMap.fromMap(convertValueType(state)) : NbtMap.EMPTY); convertValueType((Map<String, Object>) data.get("state")).forEach(getter::property);
// The mapping file may not be the latest, so we use block state updater
// to update the old block state to the latest version
var updatedNBT = BlockStateUpdaters.updateBlockState(builder.build(), BlockStateUpdaters.LATEST_VERSION);
var blockStateTag = NbtMap.builder()
// To calculate the hash of the block state
// 'name' field must be in the first place
.putString("name", updatedNBT.getString("name"))
// map implementation inside updatedNBT.getCompound("states") should be TreeMap
// see convertValueType() method
.putCompound("states", updatedNBT.getCompound("states"))
.build();
var blockStateHash = HashUtils.fnv1a_32_nbt(blockStateTag);
var blockState = Registries.BLOCK_STATE_PALETTE.get(blockStateHash);
if (blockState == null) {
log.error("Cannot find bedrock block state: {}", blockStateTag);
return BE_AIR_STATE;
} }
return blockState; return getter.blockState();
} }
private static TreeMap<String, Object> convertValueType(Map<String, Object> data) { private static Map<String, Object> convertValueType(Map<String, Object> data) {
// Use tree map to make sure that the order of property is correct
// Otherwise the block state hash calculated may not be correct!
var result = new TreeMap<String, Object>(); var result = new TreeMap<String, Object>();
for (var entry : data.entrySet()) { for (var entry : data.entrySet()) {
var value = entry.getValue(); if (entry.getValue() instanceof Number number) {
if (value instanceof Boolean) { // Convert double to int because the number in json is double
// BooleanProperty
result.put(entry.getKey(), (Boolean) value ? (byte) 1 : (byte) 0);
} else if (value instanceof Number number) {
// IntProperty
result.put(entry.getKey(), number.intValue()); result.put(entry.getKey(), number.intValue());
} else { } else {
// EnumProperty result.put(entry.getKey(), entry.getValue());
result.put(entry.getKey(), value);
} }
} }
return result; return result;
@ -171,8 +147,8 @@ public final class Mapping {
private static JeBlockState createJeBlockState(Map<String, Object> data) { private static JeBlockState createJeBlockState(Map<String, Object> data) {
var identifier = (String) data.get("Name"); var identifier = (String) data.get("Name");
var properties = (Map<String, String>) data.getOrDefault("Properties", Map.of()); // noinspection unchecked
return JeBlockState.create(identifier, new TreeMap<>(properties)); return JeBlockState.create(identifier, new TreeMap<>((Map<String, String>) data.getOrDefault("Properties", Map.of())));
} }
public static JeBlockState blockStateBeToJe(BlockState beBlockState) { public static JeBlockState blockStateBeToJe(BlockState beBlockState) {
@ -188,14 +164,10 @@ public final class Mapping {
return result; return result;
} }
public static String itemIdJeToBe(String jeItemId) { public static ItemType<?> itemIdJeToBe(String jeItemId) {
return ITEM_ID_JE_TO_BE.get(jeItemId); return ITEM_ID_JE_TO_BE.get(jeItemId);
} }
public static int jeItemIdToBeItemMeta(String jeItemId) {
return JE_ITEM_ID_TO_BE_ITEM_META.get(jeItemId);
}
// Enchantment identifiers are same in both versions // Enchantment identifiers are same in both versions
public static String enchantmentIdBeToJe(String beEnchantmentId) { public static String enchantmentIdBeToJe(String beEnchantmentId) {

View File

@ -21,7 +21,7 @@ public record AllayItemStack(ItemStack allayItemStack) implements com.dfsek.terr
@Override @Override
public Item getType() { public Item getType() {
return new AllayItemType(allayItemStack.getItemType(), allayItemStack.getMeta()); return new AllayItemType(allayItemStack.getItemType());
} }
@Override @Override

View File

@ -1,27 +1,28 @@
package org.allaymc.terra.allay.delegate; package org.allaymc.terra.allay.delegate;
import org.allaymc.api.item.data.ItemId;
import org.allaymc.api.item.type.ItemType; import org.allaymc.api.item.type.ItemType;
import com.dfsek.terra.api.inventory.Item; import com.dfsek.terra.api.inventory.Item;
import org.allaymc.api.registry.Registries;
/** /**
* @author daoge_cmd * @author daoge_cmd
*/ */
public final class AllayItemType implements Item { public final class AllayItemType implements Item {
private final ItemType<?> allayItemType; private final ItemType<?> allayItemType;
private final int beData;
private final double maxDurability; private final double maxDurability;
public AllayItemType(ItemType<?> allayItemType, int beData) { public AllayItemType(ItemType<?> allayItemType) {
this.allayItemType = allayItemType; this.allayItemType = allayItemType;
this.beData = beData; this.maxDurability = Registries.ITEM_DATA.get(ItemId.fromIdentifier(allayItemType.getIdentifier())).maxDamage();
// TODO: Better way to get max damage
this.maxDurability = allayItemType.createItemStack().getItemData().maxDamage();
} }
@Override @Override
public com.dfsek.terra.api.inventory.ItemStack newItemStack(int amount) { public com.dfsek.terra.api.inventory.ItemStack newItemStack(int amount) {
return new AllayItemStack(allayItemType.createItemStack(amount, beData)); return new AllayItemStack(allayItemType.createItemStack(amount));
} }
@Override @Override

View File

@ -19,7 +19,7 @@ import com.dfsek.terra.api.inventory.item.Enchantment;
public class AllayItemHandle implements ItemHandle { public class AllayItemHandle implements ItemHandle {
@Override @Override
public Item createItem(String data) { public Item createItem(String data) {
return new AllayItemType(Registries.ITEMS.get(new Identifier(Mapping.itemIdJeToBe(data))), Mapping.jeItemIdToBeItemMeta(data)); return new AllayItemType(Mapping.itemIdJeToBe(data));
} }
@Override @Override