Compare commits

..

1 Commits

Author SHA1 Message Date
Sebastian Hartte 2216c33f12 Be less defensive about copying item stacks in simulated extractions (but still catch obviously broken implementations).
Also fix looping over the same slot while simulating, and try to heuristically guess the maximum extraction from the slot given what getStackInSlot returned.
2020-10-10 20:13:36 +02:00
9 changed files with 72 additions and 126 deletions
-7
View File
@@ -1,10 +1,3 @@
This is a fork of AE2 i made for trying to solve issues for the [Omnifactory](https://www.curseforge.com/minecraft/modpacks/omnifactory) modpack.
See https://github.com/PrototypeTrousers/Applied-Energistics-2/tree/AE2-Omnifactory branch for commits
and
https://github.com/PrototypeTrousers/Applied-Energistics-2/releases for the compiled jars.
[![Build master](https://img.shields.io/github/workflow/status/AppliedEnergistics/Applied-Energistics-2/Build%20master?style=flat-square)](https://github.com/AppliedEnergistics/Applied-Energistics-2/actions?query=workflow%3A%22Build+master%22)
[![Latest Release](https://img.shields.io/github/v/release/AppliedEnergistics/Applied-Energistics-2?style=flat-square&label=Release)](https://github.com/AppliedEnergistics/Applied-Energistics-2/releases)
[![Latest PreRelease](https://img.shields.io/github/v/release/AppliedEnergistics/Applied-Energistics-2?include_prereleases&style=flat-square&label=Pre)](https://github.com/AppliedEnergistics/Applied-Energistics-2/releases)
@@ -142,7 +142,6 @@ public class CableBusBakedModel implements IBakedModel {
}
}
}
this.facadeBuilder.buildFacadeQuads(layer, renderState, rand, quads, this.partModels::get);
return quads;
@@ -328,12 +327,12 @@ public class CableBusBakedModel implements IBakedModel {
@Override
public boolean isGui3d() {
return false; // This model is never used in an UI
return false;
}
@Override
public boolean isSideLit() {
return false; // This model is never used in an UI
return false;// TODO
}
@Override
@@ -18,9 +18,7 @@
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
@@ -39,7 +37,6 @@ import net.minecraftforge.client.model.IModelConfiguration;
import appeng.api.util.AEColor;
import appeng.client.render.BasicUnbakedModel;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.features.registries.PartModels;
/**
@@ -47,8 +44,6 @@ import appeng.core.features.registries.PartModels;
*/
public class CableBusModel implements BasicUnbakedModel<CableBusModel> {
public static final ResourceLocation TRANSLUCENT_FACADE_MODEL = AppEng.makeId("part/translucent_facade");
private final PartModels partModels;
public CableBusModel(PartModels partModels) {
@@ -58,9 +53,7 @@ public class CableBusModel implements BasicUnbakedModel<CableBusModel> {
@Override
public Collection<ResourceLocation> getModelDependencies() {
partModels.setInitialized(true);
List<ResourceLocation> models = new ArrayList<>(partModels.getModels());
models.add(TRANSLUCENT_FACADE_MODEL);
return models;
return partModels.getModels();
}
@Override
@@ -75,11 +68,7 @@ public class CableBusModel implements BasicUnbakedModel<CableBusModel> {
Map<ResourceLocation, IBakedModel> partModels = this.loadPartModels(bakery, spriteGetter, modelTransform);
CableBuilder cableBuilder = new CableBuilder(spriteGetter);
IBakedModel translucentFacadeModel = bakery.getBakedModel(TRANSLUCENT_FACADE_MODEL, modelTransform,
spriteGetter);
FacadeBuilder facadeBuilder = new FacadeBuilder(translucentFacadeModel);
FacadeBuilder facadeBuilder = new FacadeBuilder();
// This should normally not be used, but we *have* to provide a particle texture
// or otherwise damage models will
@@ -20,7 +20,6 @@ package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -30,8 +29,6 @@ import java.util.function.Function;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
@@ -91,9 +88,6 @@ public class FacadeBuilder {
new AxisAlignedBB(0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0),
new AxisAlignedBB(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) };
// Pre-rotated transparent facade quads
private final Map<Direction, List<BakedQuad>> transparentFacadeQuads;
private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder()
// Clamper is responsible for clamping the vertex to the bounds specified.
.addElement("clamper", QuadClamper.FACTORY)
@@ -110,29 +104,6 @@ public class FacadeBuilder {
);
private final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
public FacadeBuilder() {
// This constructor is used for item models where transparent facades are not a
// concern
this.transparentFacadeQuads = new EnumMap<>(Direction.class);
for (Direction facing : Direction.values()) {
this.transparentFacadeQuads.put(facing, Collections.emptyList());
}
}
public FacadeBuilder(IBakedModel transparentFacadeModel) {
// Pre-rotate the transparent facade model to all possible sides so that we can
// add it quicker later
List<BakedQuad> partQuads = transparentFacadeModel.getQuads(null, null, new Random(), EmptyModelData.INSTANCE);
this.transparentFacadeQuads = new EnumMap<>(Direction.class);
for (Direction facing : Direction.values()) {
// Rotate quads accordingly
QuadRotator rotator = new QuadRotator();
List<BakedQuad> rotated = rotator.rotateQuads(partQuads, facing, Direction.UP);
this.transparentFacadeQuads.put(facing, ImmutableList.copyOf(rotated));
}
}
public void buildFacadeQuads(RenderType layer, CableBusRenderState renderState, Random rand, List<BakedQuad> quads,
Function<ResourceLocation, IBakedModel> modelLookup) {
BakedPipeline pipeline = this.pipelines.get();
@@ -159,20 +130,14 @@ public class FacadeBuilder {
Direction.UP));
}
}
// When we're forcing transparent facades, add a "border" model that indicates
// where the facade is,
// But otherwise skip the rest.
if (transparent) {
if (layer != RenderType.getCutout()) {
quads.addAll(transparentFacadeQuads.get(side));
}
// If we are forcing transparency and this isn't the Translucent layer.
if (transparent && layer != RenderType.getTranslucent()) {
continue;
}
BlockState blockState = facadeRenderState.getSourceBlock();
// If we aren't forcing transparency let the block decide if it should render.
if (layer != null) {
if (!transparent && layer != null) {
if (!RenderTypeLookup.canRenderInLayer(blockState, layer)) {
continue;
}
@@ -233,7 +198,7 @@ public class FacadeBuilder {
List<BakedQuad> modelQuads = new ArrayList<>();
// If we are forcing transparent facades, fake the render layer, and grab all
// quads.
if (layer == null) {
if (transparent || layer == null) {
for (RenderType forcedLayer : RenderType.getBlockRenderTypes()) {
// Check if the block renders on the layer we want to force.
if (RenderTypeLookup.canRenderInLayer(blockState, forcedLayer)) {
@@ -122,6 +122,15 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
do {
extracted = this.itemHandler.extractItem(i, remainingCurrentSlot, simulate);
if (!extracted.isEmpty()) {
// In order to guard against broken IItemHandler implementations, we'll
// try to guess if the returned stack (especially in simulate mode) is
// the same that was returned by getStackInSlot. This is obviously not a
// precise science, but it would catch the previous Forge bug:
// https://github.com/MinecraftForge/MinecraftForge/pull/6580
if (extracted == stackInInventorySlot) {
extracted = extracted.copy();
}
if (extracted.getCount() > remainingCurrentSlot) {
// Something broke. It should never return more than we requested...
// We're going to silently eat the remainder
@@ -131,19 +140,28 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
extracted.setCount(remainingCurrentSlot);
}
// Heuristic for simulation: looping in case of simulations is pointless, since
// the
// state of the underlying inventory does not change after a simulated
// extraction
// To still support inventories that report stacks that are larger than
// maxStackSize,
// we use this heuristic
if (simulate && extracted.getCount() == extracted.getMaxStackSize()
&& remainingCurrentSlot > extracted.getMaxStackSize()) {
extracted.setCount(remainingCurrentSlot);
}
// We're just gonna use the first stack we get our hands on as the template for
// the rest.
// In case some stupid itemhandler (aka forge) returns an internal state we have
// to do a second
// expensive copy again.
if (gathered.isEmpty()) {
gathered = extracted.copy();
gathered = extracted;
} else {
gathered.grow(extracted.getCount());
}
remainingCurrentSlot -= extracted.getCount();
}
} while (!extracted.isEmpty() && remainingCurrentSlot > 0);
} while (!simulate && !extracted.isEmpty() && remainingCurrentSlot > 0);
remainingSize -= stackSizeCurrentSlot - remainingCurrentSlot;
@@ -55,7 +55,8 @@ import appeng.core.AppEng;
@OnlyIn(Dist.CLIENT)
public class MolecularAssemblerRenderer extends TileEntityRenderer<MolecularAssemblerTileEntity> {
public static final ResourceLocation LIGHTS_MODEL = AppEng.makeId("block/molecular_assembler_lights");
public static final ResourceLocation LIGHTS_MODEL = new ResourceLocation(AppEng.MOD_ID,
"block/molecular_assembler_lights");
private static final RenderType MC_161917_RENDERTYPE_FIX = createRenderType();
@@ -0,0 +1,39 @@
{
"textures": {
"0": "appliedenergistics2:part/cable_anchor",
"particle": "appliedenergistics2:part/cable_anchor"
},
"elements": [
{
"name": "Element",
"from": [7.0, 7.0, 1.0],
"to": [9.0, 9.0, 6.0],
"faces": {
"north": {
"texture": "#0",
"uv": [0.0, 0.0, 2.0, 2.0]
},
"east": {
"texture": "#0",
"uv": [0.0, 0.0, 5.0, 2.0]
},
"south": {
"texture": "#0",
"uv": [0.0, 0.0, 2.0, 2.0]
},
"west": {
"texture": "#0",
"uv": [0.0, 0.0, 5.0, 2.0]
},
"up": {
"texture": "#0",
"uv": [0.0, 0.0, 2.0, 5.0]
},
"down": {
"texture": "#0",
"uv": [0.0, 0.0, 2.0, 5.0]
}
}
}
]
}
@@ -1,58 +0,0 @@
{
"textures": {
"facade": "appliedenergistics2:part/translucent_facade"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 0.25, 0.25],
"faces": {
"north": { "uv": [0, 15.75, 16, 16], "texture": "#facade" },
"east": { "uv": [15.75, 15.75, 16, 16], "texture": "#facade" },
"south": { "uv": [0, 15.75, 16, 16], "texture": "#facade" },
"west": { "uv": [0, 15.75, 1, 16], "texture": "#facade" },
"up": { "uv": [0, 0, 16, 1], "texture": "#facade" },
"down": { "uv": [0, 15.75, 16, 16], "texture": "#facade" }
}
},
{
"from": [0, 15.75, 0],
"to": [16, 16, 0.25],
"rotation": { "angle": 0, "axis": "y", "origin": [8, 23, 8] },
"faces": {
"north": { "uv": [0, 0, 16, 1], "texture": "#facade" },
"east": { "uv": [15.75, 0, 16, 1], "texture": "#facade" },
"south": { "uv": [0, 0, 16, 1], "texture": "#facade" },
"west": { "uv": [0, 0, 1, 1], "texture": "#facade" },
"up": { "uv": [0, 0, 16, 1], "texture": "#facade" },
"down": { "uv": [0, 15.75, 16, 16], "texture": "#facade" }
}
},
{
"from": [0, 0.25, 0],
"to": [0.25, 15.75, 0.25],
"rotation": { "angle": 0, "axis": "y", "origin": [8, 23, 8] },
"faces": {
"north": { "uv": [15.75, 1, 16, 15.75], "texture": "#facade" },
"east": { "uv": [15.75, 1, 16, 15.75], "texture": "#facade" },
"south": { "uv": [0, 1, 1, 15.75], "texture": "#facade" },
"west": { "uv": [0, 1, 1, 15.75], "texture": "#facade" },
"up": { "uv": [0, 0, 1, 1], "texture": "#facade" },
"down": { "uv": [0, 15.75, 1, 16], "texture": "#facade" }
}
},
{
"from": [15.75, 0.25, 0],
"to": [16, 15.75, 0.25],
"rotation": { "angle": 0, "axis": "y", "origin": [23, 23, 8] },
"faces": {
"north": { "uv": [0, 1, 1, 15.75], "texture": "#facade" },
"east": { "uv": [15.75, 1, 16, 15.75], "texture": "#facade" },
"south": { "uv": [15.75, 1, 16, 15.75], "texture": "#facade" },
"west": { "uv": [0, 1, 1, 15.75], "texture": "#facade" },
"up": { "uv": [15.75, 0, 16, 1], "texture": "#facade" },
"down": { "uv": [15.75, 15.75, 16, 16], "texture": "#facade" }
}
}
]
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B