mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-29 08:27:03 +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() {
|
private void initializeLight() {
|
||||||
|
if (beltLength > 0) {
|
||||||
light = new byte[beltLength * 2];
|
light = new byte[beltLength * 2];
|
||||||
|
|
||||||
Vec3i vec = getBeltFacing().getDirectionVec();
|
Vec3i vec = getBeltFacing().getDirectionVec();
|
||||||
|
@ -562,6 +563,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList
|
||||||
pos.move(vec.getX(), verticality, vec.getZ());
|
pos.move(vec.getX(), verticality, vec.getZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateBlockLight() {
|
private void updateBlockLight() {
|
||||||
Vec3i vec = getBeltFacing().getDirectionVec();
|
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 net.minecraft.world.World;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.lwjgl.opengl.GL;
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
@ -26,16 +27,15 @@ public class Backend {
|
||||||
public static final Boolean SHADER_DEBUG_OUTPUT = true;
|
public static final Boolean SHADER_DEBUG_OUTPUT = true;
|
||||||
|
|
||||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
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<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
|
||||||
static final Map<ProgramSpec<?>, ProgramGroup<?>> programs = new HashMap<>();
|
static final Map<ProgramSpec<?>, ProgramGroup<?>> programs = new HashMap<>();
|
||||||
|
|
||||||
private static boolean enabled;
|
|
||||||
|
|
||||||
public static GLCapabilities capabilities;
|
|
||||||
public static GlFeatureCompat compat;
|
|
||||||
|
|
||||||
public Backend() {
|
public Backend() {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,7 @@ public class Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canUseInstancing() {
|
public static boolean canUseInstancing() {
|
||||||
return enabled &&
|
return enabled && instancingAvailable;
|
||||||
compat.vertexArrayObjectsSupported() &&
|
|
||||||
compat.drawInstancedSupported() &&
|
|
||||||
compat.instancedArraysSupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canUseVBOs() {
|
public static boolean canUseVBOs() {
|
||||||
|
@ -98,7 +95,14 @@ public class Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void refresh() {
|
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();
|
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.Matrix3f;
|
||||||
import net.minecraft.client.renderer.Matrix4f;
|
import net.minecraft.client.renderer.Matrix4f;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
|
|
||||||
public class RenderUtil {
|
public class RenderUtil {
|
||||||
public static int nextPowerOf2(int a) {
|
public static int nextPowerOf2(int a) {
|
||||||
|
@ -17,9 +16,12 @@ public class RenderUtil {
|
||||||
return b == 0 && n != 0;
|
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[] {
|
return new float[] {
|
||||||
model.a00,
|
model.a00,
|
||||||
model.a10,
|
model.a10,
|
||||||
|
@ -48,4 +50,25 @@ public class RenderUtil {
|
||||||
normal.a22,
|
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) {
|
static void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
||||||
if (predicate.test(VanillaResourceType.SHADERS)) {
|
if (predicate.test(VanillaResourceType.SHADERS)) {
|
||||||
Backend.capabilities = GL.createCapabilities();
|
|
||||||
Backend.compat = new GlFeatureCompat(Backend.capabilities);
|
|
||||||
|
|
||||||
OptifineHandler.refresh();
|
OptifineHandler.refresh();
|
||||||
Backend.refresh();
|
Backend.refresh();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simibubi.create.foundation.render.backend.gl;
|
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 com.simibubi.create.foundation.render.backend.gl.shader.ProgramFogMode;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
@ -53,9 +54,6 @@ public class BasicProgram extends GlProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void uploadMatrixUniform(int uniform, Matrix4f mat) {
|
protected static void uploadMatrixUniform(int uniform, Matrix4f mat) {
|
||||||
Backend.MATRIX_BUFFER.position(0);
|
GL20.glUniformMatrix4fv(uniform, false, RenderUtil.writeMatrix(mat));
|
||||||
mat.write(Backend.MATRIX_BUFFER);
|
|
||||||
Backend.MATRIX_BUFFER.rewind();
|
|
||||||
GL20.glUniformMatrix4fv(uniform, false, Backend.MATRIX_BUFFER);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@ package com.simibubi.create.foundation.render.backend.instancing;
|
||||||
|
|
||||||
public interface IDynamicInstance {
|
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();
|
void beginFrame();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,9 @@ package com.simibubi.create.foundation.render.backend.instancing;
|
||||||
|
|
||||||
public interface ITickableInstance {
|
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();
|
void tick();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,6 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
public abstract void registerMaterials();
|
public abstract void registerMaterials();
|
||||||
|
|
||||||
public void tick() {
|
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)
|
if (tickableInstances.size() > 0)
|
||||||
tickableInstances.values().forEach(ITickableInstance::tick);
|
tickableInstances.values().forEach(ITickableInstance::tick);
|
||||||
}
|
}
|
||||||
|
@ -187,16 +179,13 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clean() {
|
|
||||||
instances.keySet().removeIf(TileEntity::isRemoved);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
for (RenderMaterial<?, ?> material : materials.values()) {
|
for (RenderMaterial<?, ?> material : materials.values()) {
|
||||||
material.delete();
|
material.delete();
|
||||||
}
|
}
|
||||||
instances.clear();
|
instances.clear();
|
||||||
dynamicInstances.clear();
|
dynamicInstances.clear();
|
||||||
|
tickableInstances.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canCreateInstance(TileEntity tile) {
|
public boolean canCreateInstance(TileEntity tile) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class ModelData extends BasicData {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelData setTransform(MatrixStack stack) {
|
public ModelData setTransform(MatrixStack stack) {
|
||||||
matrices = RenderUtil.bufferMatrices(stack.peek().getModel(), stack.peek().getNormal());
|
matrices = RenderUtil.writeMatrixStack(stack);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,19 @@
|
||||||
"package": "com.simibubi.create.foundation.mixin",
|
"package": "com.simibubi.create.foundation.mixin",
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"refmap": "create.refmap.json",
|
"refmap": "create.refmap.json",
|
||||||
"client": ["AddRemoveTileMixin", "CancelTileEntityRenderMixin", "FogColorTrackerMixin", "LightUpdateMixin", "NetworkLightUpdateMixin", "RenderHooksMixin", "ShaderCloseMixin"],
|
"mixins": ["StepSoundMixin"],
|
||||||
|
"client": [
|
||||||
|
"TileAddMixin",
|
||||||
|
"CancelTileEntityRenderMixin",
|
||||||
|
"FogColorTrackerMixin",
|
||||||
|
"LightUpdateMixin",
|
||||||
|
"NetworkLightUpdateMixin",
|
||||||
|
"RenderHooksMixin",
|
||||||
|
"ShaderCloseMixin",
|
||||||
|
"TileRemoveMixin"
|
||||||
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
},
|
},
|
||||||
"minVersion": "0.8", "mixins": ["StepSoundMixin"]
|
"minVersion": "0.8"
|
||||||
}
|
}
|
Loading…
Reference in a new issue