Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/main/java/lol/sylvie/bedframe/BedframeInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import lol.sylvie.bedframe.geyser.TranslationManager;
import net.fabricmc.api.ModInitializer;

import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.metadata.Person;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package lol.sylvie.bedframe.geyser.translator;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import eu.pb4.polymer.blocks.api.BlockResourceCreator;
import eu.pb4.polymer.blocks.api.PolymerBlockModel;
import eu.pb4.polymer.blocks.api.PolymerTexturedBlock;
import lol.sylvie.bedframe.geyser.Translator;
import lol.sylvie.bedframe.mixin.BlockResourceCreatorAccessor;
import lol.sylvie.bedframe.mixin.PolymerBlockResourceUtilsAccessor;
import lol.sylvie.bedframe.util.JsonHelper;
import lol.sylvie.bedframe.util.ResourceHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
Expand Down Expand Up @@ -122,12 +126,6 @@ private void populateProperties(CustomBlockData.Builder builder, Collection<Prop
}
}

private String nonPrefixedBlockState(BlockState state, Identifier identifier) {
if (state.getProperties().isEmpty()) return "";
String stateString = BlockArgumentParser.stringifyBlockState(state);
return stateString.substring(identifier.toString().length() + 1, stateString.length() - 1);
}

private BoxComponent voxelShapeToBoxComponent(VoxelShape shape) {
if (shape.isEmpty()) {
return BoxComponent.emptyBox();
Expand Down Expand Up @@ -171,70 +169,46 @@ public void handle(GeyserDefineCustomBlocksEvent event, Path packRoot) {
// Properties
populateProperties(builder, realBlock.getStateManager().getProperties());

// Parsing models
HashMap<String, Pair<Integer, Integer>> rotationData = new HashMap<>();
HashMap<String, ModelData> models = new HashMap<>();

String blockstatesPath = "blockstates/" + identifier.getPath() + ".json";
try {
JsonObject variants = ResourceHelper.readJsonResource(identifier.getNamespace(), blockstatesPath)
.getAsJsonObject("variants");
forEachKey(variants, (key, element) -> {
JsonObject object = element.getAsJsonObject();

JsonElement potentialX = object.get("x");
int x = potentialX == null ? 0 : potentialX.getAsInt();

JsonElement potentialY = object.get("y");
int y = potentialY == null ? 0 : potentialY.getAsInt();

String modelPath = object.get("model").getAsString();
JsonObject model = ResourceHelper.readJsonResource(identifier.getNamespace(), "models/" + Identifier.of(modelPath).getPath() + ".json");

rotationData.put(key, new Pair<>(x, y));
models.put(key, ModelData.fromJson(model));
});
} catch (NullPointerException e) {
// SHAME!
LOGGER.warn("Missing blockstates for {}", identifier);
JsonObject model = ResourceHelper.readJsonResource(identifier.getNamespace(), "models/block/" + identifier.getPath() + ".json");
models.put("", ModelData.fromJson(model));
}

// Block states/permutations
List<CustomBlockPermutation> permutations = new ArrayList<>();
for (BlockState state : realBlock.getStateManager().getStates()) {
String stateKey = nonPrefixedBlockState(state, identifier);
CustomBlockComponents.Builder stateComponentBuilder = CustomBlockComponents.builder();

// Obtain model data from polymers internal api
BlockState polymerBlockState = block.getPolymerBlockState(state, PacketContext.get());
BlockResourceCreator creator = PolymerBlockResourceUtilsAccessor.getCREATOR();
PolymerBlockModel[] polymerBlockModels = ((BlockResourceCreatorAccessor)(Object)creator).getModels().get(polymerBlockState);
PolymerBlockModel modelEntry = polymerBlockModels[0]; // TODO: java selects one by weight, does bedrock support this?

// Rotation
Pair<Integer, Integer> rotation = rotationData.getOrDefault(stateKey, new Pair<>(0, 0));
TransformationComponent rotationComponent = new TransformationComponent((360 - rotation.getLeft()) % 360, (360 - rotation.getRight()) % 360, 0);
TransformationComponent rotationComponent = new TransformationComponent((360 - modelEntry.x()) % 360, (360 - modelEntry.y()) % 360, 0);
stateComponentBuilder.transformation(rotationComponent);

// Geometry
// TODO: More geometry types
ModelData modelData = models.getOrDefault(stateKey, models.get(""));
if (modelData == null) {
JsonObject blockModel = ResourceHelper.readJsonResource(modelEntry.model().getNamespace(), "models/" + modelEntry.model().getPath() + ".json");
if (blockModel == null) {
LOGGER.warn("Couldn't load model for blockstate {}", state);
continue;
}
boolean cross = modelData.parent().equals("minecraft:block/cross");

ModelData modelData = ModelData.fromJson(blockModel);
boolean cross = modelData.parent().toString().equals("minecraft:block/cross");
String geometryIdentifier = cross ? "minecraft:geometry.cross" : "minecraft:geometry.full_block";
String renderMethod = cross ? "alpha_test_single_sided" : "opaque";

GeometryComponent geometryComponent = GeometryComponent.builder().identifier(geometryIdentifier).build();
stateComponentBuilder.geometry(geometryComponent);

// Textures
List<Pair<String, String>> faceMap = parentFaceMap.getOrDefault(modelData.parent().replaceFirst("minecraft:", ""), parentFaceMap.get("block/cube_all"));
List<Pair<String, String>> faceMap = parentFaceMap.getOrDefault(modelData.parent().getPath(), parentFaceMap.get("block/cube_all"));
for (Pair<String, String> face : faceMap) {
String javaFaceName = face.getLeft();
String bedrockFaceName = face.getRight();
if (!modelData.textures.containsKey(javaFaceName)) continue;

String textureName = modelData.textures.get(javaFaceName);
String texturePath = "textures/" + textureName;
String texturePath = "textures/" + Identifier.of(textureName).getPath();
String bedrockPath = ResourceHelper.javaToBedrockTexture(texturePath);

JsonObject thisTexture = new JsonObject();
Expand Down Expand Up @@ -313,16 +287,9 @@ public void register(EventBus<EventRegistrar> eventBus, Path packRoot) {
eventBus.subscribe(this, GeyserDefineCustomBlocksEvent.class, event -> handle(event, packRoot));
}

record ModelData(String parent, Map<String, String> textures) {
record ModelData(Identifier parent, Map<String, String> textures) {
public static ModelData fromJson(JsonObject object) {
JsonObject texturesObject = object.getAsJsonObject("textures");
HashMap<String, String> texturesMap = new HashMap<>();
texturesObject.entrySet().forEach(e -> {
String texture = e.getValue().getAsString();
if (texture.contains(":")) texture = Identifier.of(texture).getPath();
texturesMap.put(e.getKey(), texture);
});
return new ModelData(object.get("parent").getAsString(), texturesMap);
return JsonHelper.GSON.fromJson(object, ModelData.class);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private void handle(GeyserDefineCustomItemsEvent event, Path packRoot) {
ItemStack itemStack = item.getPolymerItemStack(realItem.getDefaultStack(), TooltipType.BASIC, PacketContext.get());
Identifier model = itemStack.get(DataComponentTypes.ITEM_MODEL);

if (model == null || model.getNamespace().equals("minecraft")) return;
if (model == null || model.getNamespace().equals("minecraft")) return; // FIXME: some people (cough me cough) store their models in the minecraft namespace

CustomItemOptions.Builder itemOptions = CustomItemOptions.builder();

Expand Down Expand Up @@ -123,9 +123,9 @@ private void handle(GeyserDefineCustomItemsEvent event, Path packRoot) {
Identifier modelId = Identifier.of(itemDescription.get("model").getAsJsonObject().get("model").getAsString());

JsonObject modelObject = ResourceHelper.readJsonResource(modelId.getNamespace(), "models/" + modelId.getPath() + ".json");
String modelType = modelObject.get("parent").getAsString();
Identifier modelType = Identifier.of(modelObject.get("parent").getAsString());

if (modelType.equals("minecraft:item/generated")) {
if (modelType.equals(BedframeConstants.GENERATED_IDENTIFIER) || modelType.equals(BedframeConstants.HANDHELD_IDENTIFIER)) {
Identifier textureId = Identifier.of(modelObject.get("textures").getAsJsonObject().get("layer0").getAsString());

String texturePath = "textures/" + textureId.getPath();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package lol.sylvie.bedframe.mixin;

import eu.pb4.polymer.blocks.api.BlockResourceCreator;
import eu.pb4.polymer.blocks.api.PolymerBlockModel;
import net.minecraft.block.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.util.Map;

@Mixin(value = BlockResourceCreator.class, remap = false)
public interface BlockResourceCreatorAccessor {
@Accessor
Map<BlockState, PolymerBlockModel[]> getModels();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lol.sylvie.bedframe.mixin;

import eu.pb4.polymer.blocks.api.BlockResourceCreator;
import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(value = PolymerBlockResourceUtils.class, remap = false)
public interface PolymerBlockResourceUtilsAccessor {
@Accessor
static BlockResourceCreator getCREATOR() {
throw new AssertionError();
}
}
4 changes: 4 additions & 0 deletions src/main/java/lol/sylvie/bedframe/util/BedframeConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.gson.GsonBuilder;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.metadata.ModMetadata;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -14,4 +15,7 @@ public class BedframeConstants {
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);

public static final ModMetadata METADATA = FabricLoader.getInstance().getModContainer(MOD_ID).orElseThrow().getMetadata();

public static final Identifier GENERATED_IDENTIFIER = Identifier.ofVanilla("item/generated");
public static final Identifier HANDHELD_IDENTIFIER = Identifier.ofVanilla("item/handheld");
}
27 changes: 27 additions & 0 deletions src/main/java/lol/sylvie/bedframe/util/JsonHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package lol.sylvie.bedframe.util;

import com.google.gson.*;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import net.minecraft.util.Identifier;

import java.lang.reflect.Type;

public class JsonHelper {
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(Identifier.class, new SimpleCodecDeserializer<>(Identifier.CODEC))
.create();

public static class SimpleCodecDeserializer<T> implements JsonDeserializer<T> {
private final Codec<T> codec;

public SimpleCodecDeserializer(Codec<T> codec) {
this.codec = codec;
}

@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return codec.parse(JsonOps.INSTANCE, json).getOrThrow(error -> new JsonParseException("Failed to deserialize using Codec: " + error));
}
}
}
5 changes: 5 additions & 0 deletions src/main/java/lol/sylvie/bedframe/util/ZipHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public class ZipHelper {
// https://stackoverflow.com/questions/57997257/how-can-i-zip-a-complete-directory-with-all-subfolders-in-java
public static void zipFolder(Path source, File destination) {
try {
var parent = Path.of(destination.getParent());
if (!Files.exists(parent)) {
Files.createDirectory(parent); // this is just quickly hacked together, the dir has to exist in order to write the file
}

ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(destination));
Files.walkFileTree(source, new SimpleFileVisitor<>() {
@Override
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/bedframe.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"package": "lol.sylvie.bedframe.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"BlockResourceCreatorAccessor",
"CustomItemRegistryPopulatorMixin",
"PolymerBlockResourceUtilsAccessor",
"PolymerItemMixin",
"PolymerItemUtilsMixin"
],
Expand Down