mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
Little things.
- Quark magnets don't crash (already fixed). - Fix quark magnet leaving behind ghost instances. - Fix crash with belt lighting after being placed by contraptions. - Simplify tile add/remove mixins and avoid conflict with Performant. - Avoid FloatBuffer detour when uploading matrix uniforms. - InstancedTileRenderer no longer has to clean up. - Properly let go of tickable instances.
This commit is contained in:
parent
7eafbe5757
commit
b18993ed26
13 changed files with 300 additions and 290 deletions
|
@ -548,6 +548,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList
|
|||
}
|
||||
|
||||
private void initializeLight() {
|
||||
if (beltLength > 0) {
|
||||
light = new byte[beltLength * 2];
|
||||
|
||||
Vec3i vec = getBeltFacing().getDirectionVec();
|
||||
|
@ -562,6 +563,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList
|
|||
pos.move(vec.getX(), verticality, vec.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBlockLight() {
|
||||
Vec3i vec = getBeltFacing().getDirectionVec();
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
package com.simibubi.create.foundation.mixin;
|
||||
|
||||
import com.simibubi.create.foundation.render.KineticRenderer;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import com.simibubi.create.CreateClient;
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mixin(value = World.class, priority = 1042)
|
||||
public class AddRemoveTileMixin {
|
||||
|
||||
@Shadow @Final public boolean isRemote;
|
||||
|
||||
@Shadow @Final protected Set<TileEntity> tileEntitiesToBeRemoved;
|
||||
|
||||
/**
|
||||
* JUSTIFICATION: This method is called whenever a tile entity is removed due
|
||||
* to a change in block state, even on the client. By hooking into this method,
|
||||
* we gain easy access to the information while having no impact on performance.
|
||||
*/
|
||||
@Inject(at = @At(
|
||||
value = "INVOKE_ASSIGN",
|
||||
target = "Lnet/minecraft/world/World;getTileEntity(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/tileentity/TileEntity;"
|
||||
),
|
||||
method = "removeTileEntity",
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onRemoveTile(BlockPos pos, CallbackInfo ci, TileEntity te) {
|
||||
if (isRemote) {
|
||||
World thi = (World)(Object) this;
|
||||
CreateClient.kineticRenderer.get(thi).remove(te);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "addTileEntity")
|
||||
private void onAddTile(TileEntity te, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (isRemote) {
|
||||
World thi = (World)(Object) this;
|
||||
CreateClient.kineticRenderer.get(thi).queueAdd(te);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Ljava/util/Set;clear()V", ordinal = 0
|
||||
),
|
||||
method = "tickBlockEntities")
|
||||
private void onChunkUnload(CallbackInfo ci) {
|
||||
if (isRemote) {
|
||||
World thi = (World)(Object) this;
|
||||
KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(thi);
|
||||
for (TileEntity tile : tileEntitiesToBeRemoved) {
|
||||
kineticRenderer.remove(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.simibubi.create.foundation.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.simibubi.create.CreateClient;
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mixin(World.class)
|
||||
public class TileAddMixin {
|
||||
|
||||
@Shadow @Final public boolean isRemote;
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "addTileEntity")
|
||||
private void onAddTile(TileEntity te, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (isRemote) {
|
||||
CreateClient.kineticRenderer.get((World)(Object) this).queueAdd(te);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.simibubi.create.foundation.mixin;
|
||||
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import com.simibubi.create.CreateClient;
|
||||
|
||||
@Mixin(TileEntity.class)
|
||||
public class TileRemoveMixin {
|
||||
|
||||
@Shadow @Nullable protected World world;
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "remove")
|
||||
private void onRemove(CallbackInfo ci) {
|
||||
if (world instanceof ClientWorld)
|
||||
CreateClient.kineticRenderer.get(this.world).remove((TileEntity) (Object) this);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
|||
import net.minecraft.world.World;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
|
@ -26,16 +27,15 @@ public class Backend {
|
|||
public static final Boolean SHADER_DEBUG_OUTPUT = true;
|
||||
|
||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
||||
public static final FloatBuffer MATRIX_BUFFER = MemoryUtil.memAllocFloat(16);
|
||||
public static GLCapabilities capabilities;
|
||||
public static GlFeatureCompat compat;
|
||||
|
||||
private static boolean instancingAvailable;
|
||||
private static boolean enabled;
|
||||
|
||||
static final Map<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
|
||||
static final Map<ProgramSpec<?>, ProgramGroup<?>> programs = new HashMap<>();
|
||||
|
||||
private static boolean enabled;
|
||||
|
||||
public static GLCapabilities capabilities;
|
||||
public static GlFeatureCompat compat;
|
||||
|
||||
public Backend() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
@ -66,10 +66,7 @@ public class Backend {
|
|||
}
|
||||
|
||||
public static boolean canUseInstancing() {
|
||||
return enabled &&
|
||||
compat.vertexArrayObjectsSupported() &&
|
||||
compat.drawInstancedSupported() &&
|
||||
compat.instancedArraysSupported();
|
||||
return enabled && instancingAvailable;
|
||||
}
|
||||
|
||||
public static boolean canUseVBOs() {
|
||||
|
@ -98,7 +95,14 @@ public class Backend {
|
|||
}
|
||||
|
||||
public static void refresh() {
|
||||
capabilities = GL.createCapabilities();
|
||||
|
||||
compat = new GlFeatureCompat(capabilities);
|
||||
|
||||
instancingAvailable = compat.vertexArrayObjectsSupported() &&
|
||||
compat.drawInstancedSupported() &&
|
||||
compat.instancedArraysSupported();
|
||||
|
||||
enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@ package com.simibubi.create.foundation.render.backend;
|
|||
import net.minecraft.client.renderer.Matrix3f;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
public class RenderUtil {
|
||||
public static int nextPowerOf2(int a) {
|
||||
|
@ -17,9 +16,12 @@ public class RenderUtil {
|
|||
return b == 0 && n != 0;
|
||||
}
|
||||
|
||||
// GPUs want matrices in column major order.
|
||||
public static float[] writeMatrixStack(MatrixStack stack) {
|
||||
return writeMatrixStack(stack.peek().getModel(), stack.peek().getNormal());
|
||||
}
|
||||
|
||||
public static float[] bufferMatrices(Matrix4f model, Matrix3f normal) {
|
||||
// GPUs want matrices in column major order.
|
||||
public static float[] writeMatrixStack(Matrix4f model, Matrix3f normal) {
|
||||
return new float[] {
|
||||
model.a00,
|
||||
model.a10,
|
||||
|
@ -48,4 +50,25 @@ public class RenderUtil {
|
|||
normal.a22,
|
||||
};
|
||||
}
|
||||
|
||||
public static float[] writeMatrix(Matrix4f model) {
|
||||
return new float[]{
|
||||
model.a00,
|
||||
model.a10,
|
||||
model.a20,
|
||||
model.a30,
|
||||
model.a01,
|
||||
model.a11,
|
||||
model.a21,
|
||||
model.a31,
|
||||
model.a02,
|
||||
model.a12,
|
||||
model.a22,
|
||||
model.a32,
|
||||
model.a03,
|
||||
model.a13,
|
||||
model.a23,
|
||||
model.a33,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,9 +35,6 @@ public class ShaderLoader {
|
|||
|
||||
static void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
||||
if (predicate.test(VanillaResourceType.SHADERS)) {
|
||||
Backend.capabilities = GL.createCapabilities();
|
||||
Backend.compat = new GlFeatureCompat(Backend.capabilities);
|
||||
|
||||
OptifineHandler.refresh();
|
||||
Backend.refresh();
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.foundation.render.backend.gl;
|
||||
|
||||
import com.simibubi.create.foundation.render.backend.RenderUtil;
|
||||
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramFogMode;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
|
@ -53,9 +54,6 @@ public class BasicProgram extends GlProgram {
|
|||
}
|
||||
|
||||
protected static void uploadMatrixUniform(int uniform, Matrix4f mat) {
|
||||
Backend.MATRIX_BUFFER.position(0);
|
||||
mat.write(Backend.MATRIX_BUFFER);
|
||||
Backend.MATRIX_BUFFER.rewind();
|
||||
GL20.glUniformMatrix4fv(uniform, false, Backend.MATRIX_BUFFER);
|
||||
GL20.glUniformMatrix4fv(uniform, false, RenderUtil.writeMatrix(mat));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ package com.simibubi.create.foundation.render.backend.instancing;
|
|||
|
||||
public interface IDynamicInstance {
|
||||
/**
|
||||
* Called every frame, this can be used to make more dynamic animations.
|
||||
* Called every frame. This can be used to smoothly change instance data
|
||||
* to allow for fancy animations that could not be achieved on the GPU alone.
|
||||
*/
|
||||
void beginFrame();
|
||||
}
|
||||
|
|
|
@ -2,5 +2,9 @@ package com.simibubi.create.foundation.render.backend.instancing;
|
|||
|
||||
public interface ITickableInstance {
|
||||
|
||||
/**
|
||||
* Called every tick. This is useful for things that don't have to be smooth,
|
||||
* or to recalculate something that would only change after a game tick.
|
||||
*/
|
||||
void tick();
|
||||
}
|
||||
|
|
|
@ -39,14 +39,6 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
|||
public abstract void registerMaterials();
|
||||
|
||||
public void tick() {
|
||||
int ticks = AnimationTickHolder.getTicks();
|
||||
|
||||
// Clean up twice a second. This doesn't have to happen every tick,
|
||||
// but this does need to be run to ensure we don't miss anything.
|
||||
if (ticks % 10 == 0) {
|
||||
clean();
|
||||
}
|
||||
|
||||
if (tickableInstances.size() > 0)
|
||||
tickableInstances.values().forEach(ITickableInstance::tick);
|
||||
}
|
||||
|
@ -187,16 +179,13 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
|||
return renderer;
|
||||
}
|
||||
|
||||
private void clean() {
|
||||
instances.keySet().removeIf(TileEntity::isRemoved);
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
for (RenderMaterial<?, ?> material : materials.values()) {
|
||||
material.delete();
|
||||
}
|
||||
instances.clear();
|
||||
dynamicInstances.clear();
|
||||
tickableInstances.clear();
|
||||
}
|
||||
|
||||
public boolean canCreateInstance(TileEntity tile) {
|
||||
|
|
|
@ -16,7 +16,7 @@ public class ModelData extends BasicData {
|
|||
}
|
||||
|
||||
public ModelData setTransform(MatrixStack stack) {
|
||||
matrices = RenderUtil.bufferMatrices(stack.peek().getModel(), stack.peek().getNormal());
|
||||
matrices = RenderUtil.writeMatrixStack(stack);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,19 @@
|
|||
"package": "com.simibubi.create.foundation.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"refmap": "create.refmap.json",
|
||||
"client": ["AddRemoveTileMixin", "CancelTileEntityRenderMixin", "FogColorTrackerMixin", "LightUpdateMixin", "NetworkLightUpdateMixin", "RenderHooksMixin", "ShaderCloseMixin"],
|
||||
"mixins": ["StepSoundMixin"],
|
||||
"client": [
|
||||
"TileAddMixin",
|
||||
"CancelTileEntityRenderMixin",
|
||||
"FogColorTrackerMixin",
|
||||
"LightUpdateMixin",
|
||||
"NetworkLightUpdateMixin",
|
||||
"RenderHooksMixin",
|
||||
"ShaderCloseMixin",
|
||||
"TileRemoveMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"minVersion": "0.8", "mixins": ["StepSoundMixin"]
|
||||
"minVersion": "0.8"
|
||||
}
|
Loading…
Reference in a new issue