Skip to content

Commit

Permalink
Start BlockState Json File Redirections Work
Browse files Browse the repository at this point in the history
  • Loading branch information
FirstMegaGame4 committed Feb 11, 2024
1 parent 3f4e495 commit 5364732
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package fr.firstmegagame4.env.driven.assets.client.blockstate;

import fr.firstmegagame4.env.json.api.EnvJson;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.block.BlockModels;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;

import java.util.Map;
import java.util.function.Function;

public class BlockStateManager {

public final Map<Block, EnvJson> envJsonBlocks = new Object2ObjectOpenHashMap<>();

public final Map<Identifier, BlockStateModelProvider> modelProviders = new Object2ObjectOpenHashMap<>();

public EnvJson getStateEnvJson(BlockState state) {
return this.envJsonBlocks.get(state.getBlock());
}

public BlockStateModelProvider getProvider(Identifier identifier) {
return this.modelProviders.get(identifier);
}

public void appendBlock(Block block, EnvJson envJson) {
this.envJsonBlocks.put(block, envJson);
}

public void provideIdentifiers(Block block, Function<Map<BlockState, ModelIdentifier>, Map<BlockState, BakedModel>> baker) {
if (this.envJsonBlocks.containsKey(block)) {
EnvJson envJson = this.envJsonBlocks.get(block);
envJson.members().forEach(member -> {
BlockStateModelProvider.Builder builder = new BlockStateModelProvider.Builder();
Map<BlockState, ModelIdentifier> map = new Object2ObjectOpenHashMap<>();
block.getStateManager().getStates().forEach(state -> map.put(state, BlockModels.getModelId(member.result(), state)));
builder.append(baker.apply(map));
this.modelProviders.put(member.result(), builder.build());
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package fr.firstmegagame4.env.driven.assets.client.blockstate;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;

import java.util.Map;

public class BlockStateModelProvider {

private final Map<BlockState, BakedModel> provider = new Object2ObjectOpenHashMap<>();

private BlockStateModelProvider() {}

public BakedModel apply(BlockState state) {
return this.provider.get(state);
}

public static class Builder {

private final Map<BlockState, BakedModel> elements = new Object2ObjectOpenHashMap<>();

public Builder append(BlockState state, BakedModel model) {
this.elements.put(state, model);
return this;
}

public Builder append(Map<BlockState, BakedModel> elements) {
this.elements.putAll(elements);
return this;
}

public BlockStateModelProvider build() {
BlockStateModelProvider provider = new BlockStateModelProvider();
provider.provider.putAll(this.elements);
return provider;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package fr.firstmegagame4.env.driven.assets.client.duck;


import fr.firstmegagame4.env.json.api.EnvJson;

// Yeah, it's very awkward, I know
public interface JsonObjectDuckInterface {

EnvJson env_driven_assets$getEnvJson();

void env_driven_assets$setEnvJson(EnvJson envJson);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package fr.firstmegagame4.env.driven.assets.client.injected;

import fr.firstmegagame4.env.driven.assets.client.blockstate.BlockStateManager;
import fr.firstmegagame4.env.driven.assets.client.model.ModelManager;

public interface ModelManagerContainer {
public interface ManagerContainer {

default BlockStateManager getBlockStateManager() {
throw new IllegalStateException();
}

default ModelManager getModelManager() {
throw new IllegalStateException();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package fr.firstmegagame4.env.driven.assets.client.model;

import fr.firstmegagame4.env.driven.assets.client.EDAEnvJsonVisitors;
import fr.firstmegagame4.env.driven.assets.client.blockstate.BlockStateModelProvider;
import fr.firstmegagame4.env.driven.assets.client.duck.BakedModelDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.duck.ModelLoaderDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.injected.ManagerContainer;
import fr.firstmegagame4.env.json.api.EnvJson;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.api.renderer.v1.model.WrapperBakedModel;
Expand All @@ -22,11 +23,11 @@

public class EDABakedModel extends ForwardingBakedModel {

private final ModelManager manager;
private final ManagerContainer container;
private final ModelBakeSettings settings;

public EDABakedModel(ModelLoader loader, BakedModel wrapped, ModelBakeSettings settings) {
this.manager = ((ModelLoaderDuckInterface) loader).env_driven_assets$getModelManager();
this.container = loader;
this.wrapped = wrapped;
this.settings = settings;
}
Expand All @@ -43,10 +44,19 @@ public boolean shouldAllowItemRedirection(ItemStack stack, Supplier<Random> rand

@Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
EnvJson envJson = this.container.getBlockStateManager().getStateEnvJson(state);
if (envJson != null) {
Identifier identifier = this.getEnvJson().apply(EDAEnvJsonVisitors.blockVisitor(blockView, pos));
if (identifier != null) {
BlockStateModelProvider provider = this.container.getBlockStateManager().getProvider(identifier);
provider.apply(state).emitBlockQuads(blockView, state, pos, randomSupplier, context);
return;
}
}
if (this.getEnvJson() != null) {
Identifier identifier = this.getEnvJson().apply(EDAEnvJsonVisitors.blockVisitor(blockView, pos));
if (identifier != null) {
this.manager.changeModelWithSettings(identifier, this.settings).emitBlockQuads(blockView, state, pos, randomSupplier, context, true);
this.container.getModelManager().changeModelWithSettings(identifier, this.settings).emitBlockQuads(blockView, state, pos, randomSupplier, context, true);
return;
}
}
Expand All @@ -58,7 +68,7 @@ public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, Rend
if (this.getEnvJson() != null) {
Identifier identifier = this.getEnvJson().apply(EDAEnvJsonVisitors.clientVisitor(MinecraftClient.getInstance()));
if (identifier != null) {
this.manager.changeModelWithSettings(identifier, this.settings).emitItemQuads(stack, randomSupplier, context, true);
this.container.getModelManager().changeModelWithSettings(identifier, this.settings).emitItemQuads(stack, randomSupplier, context, true);
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package fr.firstmegagame4.env.driven.assets.mixin.client;

import com.google.gson.JsonObject;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.datafixers.util.Pair;
import fr.firstmegagame4.env.driven.assets.client.EDAUtils;
import fr.firstmegagame4.env.driven.assets.client.injected.ModelManagerContainer;
import fr.firstmegagame4.env.driven.assets.client.blockstate.BlockStateManager;
import fr.firstmegagame4.env.driven.assets.client.duck.JsonObjectDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.duck.JsonUnbakedModelDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.duck.ModelLoaderDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.injected.ManagerContainer;
import fr.firstmegagame4.env.driven.assets.client.model.ModelManager;
import fr.firstmegagame4.env.json.api.resource.ExtendedResource;
import fr.firstmegagame4.env.json.api.resource.ExtendedResourceReader;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.resource.Resource;
Expand All @@ -21,16 +24,20 @@
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.io.IOException;
import java.io.Reader;
import java.util.Map;

@Mixin(BakedModelManager.class)
public class BakedModelManagerMixin implements ModelManagerContainer {
public class BakedModelManagerMixin implements ManagerContainer {

@Unique
private ModelLoader modelLoader = null;

// This mixin works, MCDev is just doing weird checks
@SuppressWarnings("UnresolvedMixinReference")
@WrapOperation(method = "method_45898", at = @At(value = "INVOKE", target = "Lcom/mojang/datafixers/util/Pair;of(Ljava/lang/Object;Ljava/lang/Object;)Lcom/mojang/datafixers/util/Pair;"))
private static <F, S> Pair<F, S> mutateModelValue(F first, S second, Operation<Pair<F, S>> original, @Local Map.Entry<Identifier, Resource> entry) {
private static <F, S> Pair<F, S> mutateModelValue(F first, S second, Operation<Pair<F, S>> original, @Local(argsOnly = true) Map.Entry<Identifier, Resource> entry) {
ExtendedResource resource = ExtendedResource.of(entry.getValue());
try {
if (resource.getEnvJson() != null) {
Expand All @@ -45,14 +52,35 @@ private static <F, S> Pair<F, S> mutateModelValue(F first, S second, Operation<P
return original.call(first, second);
}

@SuppressWarnings("DataFlowIssue")
@WrapOperation(method = "method_45890", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/JsonHelper;deserialize(Ljava/io/Reader;)Lcom/google/gson/JsonObject;"))
private static JsonObject hideEnvJson(Reader reader, Operation<JsonObject> original) {
JsonObject jsonObject = original.call(reader);
ExtendedResourceReader extended = (ExtendedResourceReader) reader;
// May need some logs here
try {
JsonObjectDuckInterface ducked = (JsonObjectDuckInterface) (Object) jsonObject;
ducked.env_driven_assets$setEnvJson(extended.getExtendedResource().getEnvJson());
} catch (IOException e) {
throw new RuntimeException(e);
}
return jsonObject;
}

@Inject(method = "upload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/ModelLoader;getBakedModelMap()Ljava/util/Map;"))
private void hookModelLoader(BakedModelManager.BakingResult bakingResult, Profiler profiler, CallbackInfo ci) {
this.modelLoader = bakingResult.modelLoader();
}

@Override
@SuppressWarnings("AddedMixinMembersNamePattern")
public BlockStateManager getBlockStateManager() {
return this.modelLoader.getBlockStateManager();
}

@Override
@SuppressWarnings("AddedMixinMembersNamePattern")
public ModelManager getModelManager() {
return ((ModelLoaderDuckInterface) this.modelLoader).env_driven_assets$getModelManager();
return this.modelLoader.getModelManager();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package fr.firstmegagame4.env.driven.assets.mixin.client;

import com.google.gson.JsonObject;
import fr.firstmegagame4.env.driven.assets.client.duck.JsonObjectDuckInterface;
import fr.firstmegagame4.env.json.api.EnvJson;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;

@Mixin(JsonObject.class)
public class JsonObjectMixin implements JsonObjectDuckInterface {

@Unique
private EnvJson envJson = null;

@Override
public EnvJson env_driven_assets$getEnvJson() {
return this.envJson;
}

@Override
public void env_driven_assets$setEnvJson(EnvJson envJson) {
this.envJson = envJson;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import fr.firstmegagame4.env.driven.assets.client.EDAUtils;
import fr.firstmegagame4.env.driven.assets.client.blockstate.BlockStateManager;
import fr.firstmegagame4.env.driven.assets.client.duck.JsonObjectDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.duck.JsonUnbakedModelDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.duck.ModelLoaderDuckInterface;
import fr.firstmegagame4.env.driven.assets.client.injected.ManagerContainer;
import fr.firstmegagame4.env.driven.assets.client.model.ModelManager;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.render.model.*;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.Profiler;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
Expand All @@ -21,14 +26,18 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

@Mixin(ModelLoader.class)
public abstract class ModelLoaderMixin implements ModelLoaderDuckInterface {
public abstract class ModelLoaderMixin implements ManagerContainer {

@Unique
private final ModelManager manager = new ModelManager();
private final BlockStateManager blockStateManager = new BlockStateManager();

@Unique
private final ModelManager modelManager = new ModelManager();

@Shadow
@Final
Expand All @@ -41,9 +50,15 @@ public abstract class ModelLoaderMixin implements ModelLoaderDuckInterface {
@Shadow
public abstract UnbakedModel getOrLoadModel(Identifier id);

@Override
public ModelManager env_driven_assets$getModelManager() {
return this.manager;
@Inject(method = "<init>", at = @At("TAIL"))
private void computeStatesIntoManager(BlockColors blockColors, Profiler profiler, Map<Identifier, JsonUnbakedModel> jsonUnbakedModels, Map<Identifier, List<ModelLoader.SourceTrackedData>> blockStates, CallbackInfo ci) {
Registries.BLOCK.streamEntries().forEach(ref -> {
Identifier stateId = ModelLoader.BLOCK_STATES_FINDER.toResourcePath(ref.registryKey().getValue());
JsonObjectDuckInterface ducked = (JsonObjectDuckInterface) blockStates.get(stateId);
if (ducked.env_driven_assets$getEnvJson() != null) {
this.blockStateManager.appendBlock(ref.value(), ducked.env_driven_assets$getEnvJson());
}
});
}

@Inject(method = "addModel", at = @At("TAIL"))
Expand All @@ -55,6 +70,18 @@ private void addEnvJsonModels(ModelIdentifier modelId, CallbackInfo ci, @Local U
});
}

@Override
@SuppressWarnings("AddedMixinMembersNamePattern")
public BlockStateManager getBlockStateManager() {
return this.blockStateManager;
}

@Override
@SuppressWarnings("AddedMixinMembersNamePattern")
public ModelManager getModelManager() {
return this.modelManager;
}

@Unique
private void addEnvJsonModel(Identifier identifier) {
UnbakedModel unbakedModel = this.getOrLoadModel(identifier);
Expand Down Expand Up @@ -88,7 +115,7 @@ private JsonUnbakedModel passToItem(JsonUnbakedModel original, @Local UnbakedMod

@Inject(method = "bake", at = @At("RETURN"))
private void hookToCache(Identifier id, ModelBakeSettings settings, CallbackInfoReturnable<BakedModel> cir, @Local ModelLoader.BakedModelCacheKey bakedModelCacheKey) {
((ModelLoaderDuckInterface) this.field_40571).env_driven_assets$getModelManager().appendModel(bakedModelCacheKey, cir.getReturnValue());
this.field_40571.getModelManager().appendModel(bakedModelCacheKey, cir.getReturnValue());
}

@Inject(method = "bake", at = @At("TAIL"))
Expand All @@ -97,7 +124,7 @@ private void bakeEnvJsonModels(Identifier id, ModelBakeSettings settings, Callba
jum.env_driven_assets$getEnvJson().members().forEach(member -> {
UnbakedModel envJsonModel = this.field_40571.getOrLoadModel(member.result());
BakedModel bakedModel = envJsonModel.bake((Baker) this, this.textureGetter, settings, member.result());
((ModelLoaderDuckInterface) this.field_40571).env_driven_assets$getModelManager().appendModel(
this.field_40571.getModelManager().appendModel(
BakedModelCacheKeyAccessor.env_driven_assets$init(member.result(), settings.getRotation(), settings.isUvLocked()),
bakedModel
);
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/env_driven_assets.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"plugin": "fr.firstmegagame4.env.driven.assets.plugin.mixin.client.EDAMixinPlugin",
"mixins": [
"client.ChunkedBlockRegionMixin",
"client.JsonObjectMixin",
"client.MappedBlockAndTintGetterMixin",
"client.WorldSliceAccessor"
],
Expand Down
Loading

0 comments on commit 5364732

Please sign in to comment.