Add multi-model support for multiparts
This commit is contained in:
parent
83a2a2e852
commit
0f8d9f1353
|
@ -13,11 +13,8 @@ import net.minecraft.util.Identifier;
|
|||
import net.minecraft.util.math.Direction;
|
||||
import net.shadowfacts.simplemultipart.SimpleMultipart;
|
||||
import net.shadowfacts.simplemultipart.container.MultipartContainerBlockState;
|
||||
import net.shadowfacts.simplemultipart.multipart.MultipartSlot;
|
||||
import net.shadowfacts.simplemultipart.multipart.MultipartState;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -42,7 +39,16 @@ public class MultipartContainerBakedModel implements BakedModel {
|
|||
if (model instanceof MultipartBakedModel) {
|
||||
return ((MultipartBakedModel)model).getMultipartQuads(partState, side, random).stream();
|
||||
} else {
|
||||
return model.getQuads(null, side, random).stream();
|
||||
BlockState fakeState = null;
|
||||
|
||||
// Need to use the same fake block state as used when loading multi-models
|
||||
// otherwise MultipartBakedModel will return no quads for a null state
|
||||
MultipartFakeBlock fakeBlock = MultipartFakeBlock.fakeBlocks.get(partId);
|
||||
if (fakeBlock != null) {
|
||||
fakeState = fakeBlock.getFakeState(partState);
|
||||
}
|
||||
|
||||
return model.getQuads(fakeState, side, random).stream();
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
@ -65,7 +71,7 @@ public class MultipartContainerBakedModel implements BakedModel {
|
|||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return MinecraftClient.getInstance().getSpriteAtlas().getSprite("blocks/stone");
|
||||
return MinecraftClient.getInstance().getSpriteAtlas().getSprite("block/stone");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package net.shadowfacts.simplemultipart.client;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.state.StateFactory;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.shadowfacts.simplemultipart.SimpleMultipart;
|
||||
import net.shadowfacts.simplemultipart.multipart.Multipart;
|
||||
import net.shadowfacts.simplemultipart.multipart.MultipartState;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
public class MultipartFakeBlock extends Block {
|
||||
|
||||
public static final Map<Identifier, MultipartFakeBlock> fakeBlocks = new HashMap<>();
|
||||
|
||||
private final Multipart multipart;
|
||||
private final StateFactory<Block, BlockState> fakeStateFactory;
|
||||
|
||||
public MultipartFakeBlock(Multipart multipart) {
|
||||
super(Settings.of(Material.AIR));
|
||||
|
||||
this.multipart = multipart;
|
||||
this.fakeStateFactory = createFakeStateFactory();
|
||||
|
||||
setDefaultState(fakeStateFactory.getDefaultState());
|
||||
|
||||
Identifier partId = SimpleMultipart.MULTIPART.getId(multipart);
|
||||
fakeBlocks.put(partId, this);
|
||||
}
|
||||
|
||||
private StateFactory<Block, BlockState> createFakeStateFactory() {
|
||||
StateFactory.Builder<Block, BlockState> builder = new StateFactory.Builder<>(this);
|
||||
multipart.getStateFactory().getProperties().forEach(builder::with);
|
||||
return builder.build(BlockState::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateFactory<Block, BlockState> getStateFactory() {
|
||||
return fakeStateFactory;
|
||||
}
|
||||
|
||||
public BlockState getFakeState(MultipartState state) {
|
||||
BlockState fakeState = getDefaultState();
|
||||
for (Map.Entry<Property<?>, Comparable<?>> e : state.getEntries().entrySet()) {
|
||||
fakeState = with(fakeState, e.getKey(), e.getValue());
|
||||
}
|
||||
return fakeState;
|
||||
}
|
||||
|
||||
private static BlockState with(BlockState state, Property prop, Comparable value) {
|
||||
return state.with(prop, value);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ package net.shadowfacts.simplemultipart.client;
|
|||
|
||||
import net.fabricmc.fabric.api.client.model.ModelProvider;
|
||||
import net.fabricmc.fabric.api.client.model.ModelProviderException;
|
||||
import net.minecraft.class_816;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.block.BlockModels;
|
||||
import net.minecraft.client.render.model.UnbakedModel;
|
||||
|
@ -68,40 +69,63 @@ public class MultipartModelProvider implements ModelProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private UnbakedModel getOrLoadPartModel(ModelIdentifier id) throws ModelProviderException, IOException {
|
||||
UnbakedModel existing = unbakedModels.get(id);
|
||||
private UnbakedModel getOrLoadPartModel(ModelIdentifier modelId) throws ModelProviderException, IOException {
|
||||
UnbakedModel existing = unbakedModels.get(modelId);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
return loadModel(id);
|
||||
return loadPartModel(modelId);
|
||||
}
|
||||
|
||||
private UnbakedModel loadModel(ModelIdentifier id) throws ModelProviderException, IOException {
|
||||
Identifier partStateId = new Identifier(id.getNamespace(), "multipartstates/" + id.getPath() + ".json");
|
||||
ModelVariantMap variantMap = loadVariantMap(partStateId);
|
||||
private UnbakedModel loadPartModel(ModelIdentifier modelId) throws ModelProviderException, IOException {
|
||||
Identifier partId = new Identifier(modelId.getNamespace(), modelId.getPath());
|
||||
Identifier partStateDefId = new Identifier(partId.getNamespace(), "multipartstates/" + partId.getPath() + ".json");
|
||||
|
||||
Multipart part = SimpleMultipart.MULTIPART.get(partId);
|
||||
MultipartFakeBlock blockAdapter = new MultipartFakeBlock(part);
|
||||
|
||||
ModelVariantMap variantMap = loadPartVariantMap(blockAdapter, partStateDefId);
|
||||
|
||||
if (variantMap.method_3422()) {
|
||||
class_816 multipartUnbakedModel = variantMap.method_3421();
|
||||
part.getStateFactory().getStates().forEach(state -> {
|
||||
ModelIdentifier stateModelId = new ModelIdentifier(partId, BlockModels.propertyMapToString(state.getEntries()));
|
||||
unbakedModels.put(stateModelId, multipartUnbakedModel);
|
||||
});
|
||||
} else {
|
||||
Map<String, WeightedUnbakedModel> variants = variantMap.method_3423();
|
||||
variants.forEach((variant, model) -> {
|
||||
unbakedModels.put(new ModelIdentifier(new Identifier(id.getNamespace(), id.getPath()), variant), model);
|
||||
unbakedModels.put(new ModelIdentifier(partId, variant), model);
|
||||
});
|
||||
}
|
||||
|
||||
UnbakedModel model = unbakedModels.get(id);
|
||||
UnbakedModel model = unbakedModels.get(modelId);
|
||||
if (model == null) {
|
||||
throw new ModelProviderException("Loaded multipart state " + partStateId + " for model " + id + " but still missing model");
|
||||
throw new ModelProviderException("Loaded multipart state " + partStateDefId + " for model " + modelId + " but still missing model");
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
private ModelVariantMap loadVariantMap(Identifier id) throws IOException {
|
||||
// private StateFactory<Block, BlockState> getStateFactory(class_816 multipartUnbakedModel) {
|
||||
// try {
|
||||
// Field f = class_816.class.getDeclaredField("field_4329");
|
||||
// f.setAccessible(true);
|
||||
// return (StateFactory<Block, BlockState>)f.get(multipartUnbakedModel);
|
||||
// } catch (ReflectiveOperationException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// }
|
||||
|
||||
private ModelVariantMap loadPartVariantMap(MultipartFakeBlock blockAdapter, Identifier partStateDefId) throws IOException {
|
||||
Resource resource = null;
|
||||
Reader reader = null;
|
||||
try {
|
||||
resource = MinecraftClient.getInstance().getResourceManager().getResource(id);
|
||||
resource = MinecraftClient.getInstance().getResourceManager().getResource(partStateDefId);
|
||||
reader = new InputStreamReader(resource.getInputStream());
|
||||
|
||||
ModelVariantMap.class_791 context = new ModelVariantMap.class_791();
|
||||
// context.stateFactory =
|
||||
// TODO: ^ blockstate translation
|
||||
context.method_3426(blockAdapter.getStateFactory());
|
||||
return ModelVariantMap.method_3424(context, reader);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(reader);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"textures": {
|
||||
"texture": "block/diamond_block"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [6, 6, 6],
|
||||
"to": [10, 10, 10],
|
||||
"faces": {
|
||||
"down": { "texture": "#texture" },
|
||||
"up": { "texture": "#texture" },
|
||||
"north": { "texture": "#texture" },
|
||||
"south": { "texture": "#texture" },
|
||||
"west": { "texture": "#texture" },
|
||||
"east": { "texture": "#texture" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
{
|
||||
"variants": {
|
||||
"slot=bottom": { "model": "multipart_test:multipart/bottom" },
|
||||
"slot=top": { "model": "multipart_test:multipart/bottom", "x": 180 },
|
||||
"slot=north": { "model": "multipart_test:multipart/vertical" },
|
||||
"slot=south": { "model": "multipart_test:multipart/vertical", "y": 180 },
|
||||
"slot=east": { "model": "multipart_test:multipart/vertical", "y": 90 },
|
||||
"slot=west": { "model": "multipart_test:multipart/vertical", "y": 270 },
|
||||
"inventory": { "model": "multipart_test:multipart/vertical", "y": 180 }
|
||||
"multipart": [
|
||||
{
|
||||
"apply": { "model": "multipart_test:multipart/center" }
|
||||
},
|
||||
{
|
||||
"when": { "slot": "bottom" },
|
||||
"apply": { "model": "multipart_test:multipart/bottom" }
|
||||
},
|
||||
{
|
||||
"when": { "slot": "north" },
|
||||
"apply": { "model": "multipart_test:multipart/vertical" }
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"variants": {
|
||||
"slot=bottom": { "model": "multipart_test:multipart/bottom" },
|
||||
"slot=top": { "model": "multipart_test:multipart/bottom", "x": 180 },
|
||||
"slot=north": { "model": "multipart_test:multipart/vertical" },
|
||||
"slot=south": { "model": "multipart_test:multipart/vertical", "y": 180 },
|
||||
"slot=east": { "model": "multipart_test:multipart/vertical", "y": 90 },
|
||||
"slot=west": { "model": "multipart_test:multipart/vertical", "y": 270 },
|
||||
"inventory": { "model": "multipart_test:multipart/vertical", "y": 180 }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue