Skip to content

Commit 8f6c6f2

Browse files
authored
Fix #194: Continuity causes tesla and chainer models to be unable to load (#247)
1 parent faacc7b commit 8f6c6f2

File tree

4 files changed

+125
-41
lines changed

4 files changed

+125
-41
lines changed

src/main/java/net/swedz/extended_industrialization/client/ber/chainer/MachineChainerBlockEntityRenderer.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import net.neoforged.neoforge.client.model.pipeline.QuadBakingVertexConsumer;
2020
import net.swedz.extended_industrialization.EI;
2121
import net.swedz.extended_industrialization.client.model.chainer.MachineChainerBakedModel;
22+
import net.swedz.extended_industrialization.compat.continuity.ContinuityModelUnwrapper;
2223
import net.swedz.extended_industrialization.machines.blockentity.MachineChainerMachineBlockEntity;
2324

2425
/**
@@ -62,15 +63,14 @@ private BakedQuad getCachedQuad(MachineModelClientData data, Direction direction
6263

6364
private MachineChainerBakedModel getMachineModel(BlockState state)
6465
{
65-
if(blockModels.getBlockModel(state) instanceof MachineChainerBakedModel mbm)
66+
var model = blockModels.getBlockModel(state);
67+
model = ContinuityModelUnwrapper.unwrap(model);
68+
if(model instanceof MachineChainerBakedModel machineModel)
6669
{
67-
return mbm;
68-
}
69-
else
70-
{
71-
EI.LOGGER.warn("Model {} should have been a MachineChainerBakedModel, but was {}", state, blockModels.getBlockModel(state).getClass());
72-
return null;
70+
return machineModel;
7371
}
72+
EI.LOGGER.warn("Model {} should have been a MachineChainerBakedModel, but was {}", state, model.getClass());
73+
return null;
7474
}
7575

7676
@Override

src/main/java/net/swedz/extended_industrialization/client/ber/tesla/TeslaPartRenderer.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import net.swedz.extended_industrialization.client.ber.tesla.behavior.TeslaArcInstance;
3333
import net.swedz.extended_industrialization.client.ber.tesla.behavior.TeslaBehavior;
3434
import net.swedz.extended_industrialization.client.model.tesla.TeslaBakedModel;
35+
import net.swedz.extended_industrialization.compat.continuity.ContinuityModelUnwrapper;
3536
import net.swedz.extended_industrialization.machines.blockentity.tesla.TeslaParticleGeneratorMachineBlockEntity;
3637
import net.swedz.extended_industrialization.machines.component.tesla.network.TeslaNetworkPart;
3738
import net.swedz.tesseract.neoforge.api.WorldPos;
@@ -111,7 +112,7 @@ public static TeslaArcInstance getArcInstance(BlockPos pos)
111112
machine instanceof TeslaBehavior behavior)
112113
{
113114
var tesla = getTeslaModel(behavior.getTeslaModelLocation());
114-
if(tesla.arcs() != null)
115+
if(tesla != null && tesla.arcs() != null)
115116
{
116117
return TESLA_ARCS.computeIfAbsent(
117118
pos,
@@ -129,11 +130,14 @@ public static TeslaArcInstance getArcInstance(BlockPos pos)
129130
private static TeslaBakedModel getTeslaModel(ResourceLocation location)
130131
{
131132
var modelManager = Minecraft.getInstance().getModelManager();
132-
if(modelManager.getModel(ModelResourceLocation.standalone(location)) instanceof TeslaBakedModel model)
133+
var model = modelManager.getModel(ModelResourceLocation.standalone(location));
134+
model = ContinuityModelUnwrapper.unwrap(model);
135+
if(model instanceof TeslaBakedModel teslaModel)
133136
{
134-
return model;
137+
return teslaModel;
135138
}
136-
throw new IllegalArgumentException("Model \"%s\" is not a tesla model".formatted(location));
139+
EI.LOGGER.warn("Model {} should have been a TeslaBakedModel, but was {}", location, model.getClass());
140+
return null;
137141
}
138142

139143
private static void renderArcBounds(MachineBlockEntity machine, TeslaBakedModel tesla, PoseStack matrices, MultiBufferSource buffer)
@@ -253,12 +257,15 @@ static void render(MachineBlockEntity machine, float partialTick, PoseStack matr
253257
if(renderDistance == 0 || Minecraft.getInstance().player.position().closerThan(machine.getBlockPos().getCenter(), renderDistance))
254258
{
255259
var tesla = getTeslaModel(behavior.getTeslaModelLocation());
256-
var color = behavior.getTeslaColor();
257-
renderArcBounds(machine, tesla, matrices, buffer);
258-
if(behavior.shouldTeslaRender())
260+
if(tesla != null)
259261
{
260-
renderArcs(machine, tesla, color, partialTick, matrices, buffer, light, overlay);
261-
renderPlasma(machine, tesla, color, partialTick, matrices, buffer, light, overlay);
262+
var color = behavior.getTeslaColor();
263+
renderArcBounds(machine, tesla, matrices, buffer);
264+
if(behavior.shouldTeslaRender())
265+
{
266+
renderArcs(machine, tesla, color, partialTick, matrices, buffer, light, overlay);
267+
renderPlasma(machine, tesla, color, partialTick, matrices, buffer, light, overlay);
268+
}
262269
}
263270
}
264271
}

src/main/java/net/swedz/extended_industrialization/client/ber/tesla/behavior/TeslaArcInstance.java

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,14 @@ private TeslaBakedModel tesla()
4545

4646
public Vec3 closestOrigin(Vec3 target)
4747
{
48+
var tesla = this.tesla();
49+
if(tesla == null)
50+
{
51+
return null;
52+
}
4853
Vec3 closest = null;
4954
double closestDistance = 0;
50-
for(Vec3 origin : this.tesla().arcs().worldOrigins(worldPosition, facingDirection.get()))
55+
for(Vec3 origin : tesla.arcs().worldOrigins(worldPosition, facingDirection.get()))
5156
{
5257
double distance = origin.distanceTo(target);
5358
if(closest == null || distance < closestDistance)
@@ -66,6 +71,15 @@ public List<TeslaArcBuilder> getTrails()
6671

6772
private void createArc(Vec3 worldOrigin, Vec3 target, int duration, int segments, int segmentSplits)
6873
{
74+
if(worldOrigin == null)
75+
{
76+
return;
77+
}
78+
var tesla = this.tesla();
79+
if(tesla == null)
80+
{
81+
return;
82+
}
6983
TeslaArcBuilder builder = TeslaArcBuilder.create(duration);
7084
Vec3 origin = worldOrigin.subtract(worldPosition).add(0.5, 0.5, 0.5);
7185
Vec3 direction = target.subtract(worldOrigin).normalize();
@@ -75,7 +89,7 @@ private void createArc(Vec3 worldOrigin, Vec3 target, int duration, int segments
7589
for(int i = 0; i < segments; i++)
7690
{
7791
Vec3 direct = direction.scale(segmentLength * i).add(origin);
78-
Vec3 tangent = i == segments - 1 ? Vec3.ZERO : randomTangent(RANDOM, direction).scale(this.tesla().arcs().randomVariance(RANDOM));
92+
Vec3 tangent = i == segments - 1 ? Vec3.ZERO : randomTangent(RANDOM, direction).scale(tesla.arcs().randomVariance(RANDOM));
7993
tangent = tangent.add(offset);
8094
double x = direct.x();
8195
double y = direct.y();
@@ -93,7 +107,12 @@ private void createArc(Vec3 worldOrigin, Vec3 target, int duration, int segments
93107

94108
public void createArc(Vec3 origin, Vec3 target)
95109
{
96-
var arcs = this.tesla().arcs();
110+
var tesla = this.tesla();
111+
if(tesla == null)
112+
{
113+
return;
114+
}
115+
var arcs = tesla.arcs();
97116
this.createArc(origin, target, arcs.duration(), RANDOM.nextInt(arcs.minSegments(), arcs.maxSegments() + 1), arcs.segmentSplits());
98117
}
99118

@@ -115,33 +134,36 @@ public void tick()
115134
});
116135

117136
var tesla = this.tesla();
118-
var arcs = tesla.arcs();
119-
if(arcs != null)
137+
if(tesla != null)
120138
{
121-
if(arcs.attachesToNearbyEntities())
139+
var arcs = tesla.arcs();
140+
if(arcs != null)
122141
{
123-
var level = Minecraft.getInstance().level;
124-
var box = arcs.worldNearbyEntitiesBounds(worldPosition, facingDirection.get());
125-
var entities = level.getEntities(
126-
(Entity) null,
127-
box,
128-
(entity) -> entity.isAlive() && entity instanceof LivingEntity && !(entity instanceof Player)
129-
);
130-
for(var entity : entities)
142+
if(arcs.attachesToNearbyEntities())
131143
{
132-
Vec3 target = entity.getBoundingBox().getCenter();
133-
this.createArc(this.closestOrigin(target), target);
144+
var level = Minecraft.getInstance().level;
145+
var box = arcs.worldNearbyEntitiesBounds(worldPosition, facingDirection.get());
146+
var entities = level.getEntities(
147+
(Entity) null,
148+
box,
149+
(entity) -> entity.isAlive() && entity instanceof LivingEntity && !(entity instanceof Player)
150+
);
151+
for(var entity : entities)
152+
{
153+
Vec3 target = entity.getBoundingBox().getCenter();
154+
this.createArc(this.closestOrigin(target), target);
155+
}
134156
}
135-
}
136-
137-
if(arcs.hasRandomBounds() && trails.size() < arcs.count())
138-
{
139-
int maxCreate = arcs.count() - trails.size();
140-
int create = Math.max(Math.min(arcs.count() / 2, maxCreate), 1);
141-
for(int i = 0; i < create; i++)
157+
158+
if(arcs.hasRandomBounds() && trails.size() < arcs.count())
142159
{
143-
Vec3 target = tesla.arcs().worldRandomPointInBounds(RANDOM, worldPosition, facingDirection.get());
144-
this.createArc(this.closestOrigin(target), target);
160+
int maxCreate = arcs.count() - trails.size();
161+
int create = Math.max(Math.min(arcs.count() / 2, maxCreate), 1);
162+
for(int i = 0; i < create; i++)
163+
{
164+
Vec3 target = tesla.arcs().worldRandomPointInBounds(RANDOM, worldPosition, facingDirection.get());
165+
this.createArc(this.closestOrigin(target), target);
166+
}
145167
}
146168
}
147169
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package net.swedz.extended_industrialization.compat.continuity;
2+
3+
import com.mojang.logging.LogUtils;
4+
import net.minecraft.client.resources.model.BakedModel;
5+
import net.neoforged.fml.ModList;
6+
7+
import java.lang.invoke.MethodHandle;
8+
import java.lang.invoke.MethodHandles;
9+
10+
/**
11+
* <p>This is a bit of a hack to safely unwrap models wrapped by Continuity. Without unwrapping the model, there can
12+
* be issues with mismatching model instances.</p>
13+
*
14+
* <p>This is taken from Modern Industrialization's
15+
* {@link aztech.modern_industrialization.machines.MachineBlockEntityRenderer}.</p>
16+
*/
17+
public final class ContinuityModelUnwrapper
18+
{
19+
private static final MethodHandle UNWRAP_BAKED_MODEL;
20+
21+
static
22+
{
23+
MethodHandle unwrapBakedModel = null;
24+
if(ModList.get().isLoaded("fabric_renderer_api_v1"))
25+
{
26+
try
27+
{
28+
var wrapperBakedModel = Class.forName("net.fabricmc.fabric.api.renderer.v1.model.WrapperBakedModel");
29+
var unwrap = wrapperBakedModel.getMethod("unwrap", BakedModel.class);
30+
unwrapBakedModel = MethodHandles.lookup().unreflect(unwrap);
31+
}
32+
catch (ReflectiveOperationException ex)
33+
{
34+
LogUtils.getLogger().error("Failed to reflect WrapperBakedModel.unwrap method", ex);
35+
}
36+
}
37+
UNWRAP_BAKED_MODEL = unwrapBakedModel;
38+
}
39+
40+
public static BakedModel unwrap(BakedModel model)
41+
{
42+
if(UNWRAP_BAKED_MODEL != null)
43+
{
44+
try
45+
{
46+
model = (BakedModel) UNWRAP_BAKED_MODEL.invokeExact(model);
47+
}
48+
catch (Throwable ex)
49+
{
50+
throw new RuntimeException("Failed to unwrap model", ex);
51+
}
52+
}
53+
return model;
54+
}
55+
}

0 commit comments

Comments
 (0)