Some semblance of immersive portals compat.

- Each world gets its own KineticRenderer now.
This commit is contained in:
JozsefA 2021-03-15 15:58:41 -07:00
parent 52eed2bab3
commit e1c16d869d
10 changed files with 92 additions and 45 deletions

View file

@ -14,10 +14,13 @@ import com.simibubi.create.foundation.item.CustomItemModels;
import com.simibubi.create.foundation.item.CustomRenderedItems;
import com.simibubi.create.foundation.ponder.content.PonderIndex;
import com.simibubi.create.foundation.ponder.elements.WorldSectionElement;
import com.simibubi.create.foundation.render.AllProgramSpecs;
import com.simibubi.create.foundation.render.KineticRenderer;
import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.render.backend.OptifineHandler;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.utility.WorldAttached;
import com.simibubi.create.foundation.utility.ghost.GhostBlocks;
import com.simibubi.create.foundation.utility.outliner.Outliner;
import net.minecraft.block.Block;
@ -30,6 +33,7 @@ import net.minecraft.item.Item;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.IWorld;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
@ -37,6 +41,7 @@ import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -48,7 +53,7 @@ public class CreateClient {
public static SchematicHandler schematicHandler;
public static SchematicAndQuillHandler schematicAndQuillHandler;
public static SuperByteBufferCache bufferCache;
public static KineticRenderer kineticRenderer;
public static WorldAttached<KineticRenderer> kineticRenderer;
public static final Outliner outliner = new Outliner();
public static GhostBlocks ghostBlocks;
@ -70,7 +75,8 @@ public class CreateClient {
}
public static void clientInit(FMLClientSetupEvent event) {
kineticRenderer = new KineticRenderer();
AllProgramSpecs.init();
kineticRenderer = new WorldAttached<>(KineticRenderer::new);
schematicSender = new ClientSchematicLoader();
schematicHandler = new SchematicHandler();
@ -192,8 +198,18 @@ public class CreateClient {
}
public static void invalidateRenderers() {
CreateClient.bufferCache.invalidate();
CreateClient.kineticRenderer.invalidate();
invalidateRenderers(null);
}
public static void invalidateRenderers(@Nullable IWorld world) {
bufferCache.invalidate();
if (world != null) {
kineticRenderer.get(world).invalidate();
} else {
kineticRenderer.forEach(InstancedTileRenderer::invalidate);
}
ContraptionRenderDispatcher.invalidateAll();
}
}

View file

@ -534,12 +534,6 @@ public abstract class KineticTileEntity extends SmartTileEntity
return block.hasIntegratedCogwheel(world, pos, state);
}
@Override
public void onChunkUnloaded() {
if (world != null && world.isRemote)
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.remove(this));
}
@Override
public void requestModelDataUpdate() {
super.requestModelDataUpdate();

View file

@ -27,6 +27,7 @@ import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.LeftClickPacket;
import com.simibubi.create.foundation.ponder.PonderTooltipHandler;
import com.simibubi.create.foundation.render.KineticRenderer;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.render.backend.RenderWork;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
@ -125,7 +126,9 @@ public class ClientEvents {
if (world.isRemote() && world instanceof ClientWorld) {
CreateClient.invalidateRenderers();
AnimationTickHolder.reset();
((ClientWorld) world).loadedTileEntityList.forEach(CreateClient.kineticRenderer::add);
KineticRenderer renderer = CreateClient.kineticRenderer.get(world);
renderer.invalidate();
((ClientWorld) world).loadedTileEntityList.forEach(renderer::add);
}
/*
@ -139,7 +142,7 @@ public class ClientEvents {
@SubscribeEvent
public static void onUnloadWorld(WorldEvent.Unload event) {
if (event.getWorld().isRemote()) {
CreateClient.invalidateRenderers();
CreateClient.invalidateRenderers(event.getWorld());
AnimationTickHolder.reset();
}
}

View file

@ -1,5 +1,6 @@
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;
@ -17,12 +18,16 @@ 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(World.class)
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,
@ -30,11 +35,28 @@ public class AddRemoveTileMixin {
*/
@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) CreateClient.kineticRenderer.remove(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) CreateClient.kineticRenderer.queueAdd(te);
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);
}
}
}
}

View file

@ -3,6 +3,7 @@ package com.simibubi.create.foundation.mixin;
import java.util.Map;
import com.simibubi.create.CreateClient;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -33,6 +34,7 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
@Inject(at = @At("HEAD"), method = "markLightChanged")
private void onLightUpdate(LightType type, SectionPos pos, CallbackInfo ci) {
ClientChunkProvider thi = ((ClientChunkProvider) (Object) this);
ClientWorld world = (ClientWorld) thi.getWorld();
Chunk chunk = thi.getChunk(pos.getSectionX(), pos.getSectionZ(), false);
@ -43,14 +45,15 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
.entrySet()
.stream()
.filter(entry -> SectionPos.toChunk(entry.getKey().getY()) == sectionY)
.map(Map.Entry::getValue).forEach(tile -> {
CreateClient.kineticRenderer.onLightUpdate(tile);
.map(Map.Entry::getValue)
.forEach(tile -> {
CreateClient.kineticRenderer.get(world).onLightUpdate(tile);
if (tile instanceof ILightListener)
((ILightListener) tile).onChunkLightUpdate();
});
}
ContraptionRenderDispatcher.notifyLightUpdate((ILightReader) thi.getWorld(), type, pos);
ContraptionRenderDispatcher.notifyLightUpdate(world, type, pos);
}
}

View file

@ -1,5 +1,6 @@
package com.simibubi.create.foundation.mixin;
import com.simibubi.create.foundation.render.KineticRenderer;
import net.minecraft.client.renderer.*;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.opengl.GL20;
@ -52,17 +53,20 @@ public class RenderHooksMixin {
double camY = cameraPos.getY();
double camZ = cameraPos.getZ();
CreateClient.kineticRenderer.beginFrame(camX, camY, camZ);
CreateClient.kineticRenderer.get(world).beginFrame(camX, camY, camZ);
ContraptionRenderDispatcher.beginFrame(camX, camY, camZ);
}
@Inject(at = @At("TAIL"), method = "loadRenderers")
private void refresh(CallbackInfo ci) {
CreateClient.kineticRenderer.invalidate();
ContraptionRenderDispatcher.invalidateAll();
OptifineHandler.refresh();
Backend.refresh();
if (Backend.canUseInstancing() && world != null) world.loadedTileEntityList.forEach(CreateClient.kineticRenderer::add);
if (Backend.canUseInstancing() && world != null) {
KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world);
kineticRenderer.invalidate();
world.loadedTileEntityList.forEach(kineticRenderer::add);
}
}
}

View file

@ -19,6 +19,10 @@ import com.simibubi.create.foundation.render.backend.gl.shader.ShaderConstants;
import net.minecraft.util.ResourceLocation;
public class AllProgramSpecs {
public static void init() {
// noop, make sure the static field are loaded.
}
public static final ProgramSpec<BasicProgram> MODEL = register(ProgramSpec.builder("model", BasicProgram::new)
.addAttributes(ModelVertexAttributes.class)
.addAttributes(InstanceVertexAttributes.class)
@ -90,10 +94,6 @@ public class AllProgramSpecs {
.setFrag(Locations.CONTRAPTION)
.createProgramSpec());
public static class Contraption {
}
public static class Locations {
public static final ResourceLocation MODEL_FRAG = loc("model.frag");

View file

@ -19,6 +19,7 @@ import net.minecraft.client.renderer.RenderType;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
public class KineticRenderer extends InstancedTileRenderer<BasicProgram> {
public static int MAX_ORIGIN_DISTANCE = 100;
@ -40,30 +41,27 @@ public class KineticRenderer extends InstancedTileRenderer<BasicProgram> {
}
@Override
public void tick() {
super.tick();
public void beginFrame(double cameraX, double cameraY, double cameraZ) {
int cX = MathHelper.floor(cameraX);
int cY = MathHelper.floor(cameraY);
int cZ = MathHelper.floor(cameraZ);
Minecraft mc = Minecraft.getInstance();
Entity renderViewEntity = mc.renderViewEntity;
if (renderViewEntity == null) return;
BlockPos renderViewPosition = renderViewEntity.getPosition();
int dX = Math.abs(renderViewPosition.getX() - originCoordinate.getX());
int dY = Math.abs(renderViewPosition.getY() - originCoordinate.getY());
int dZ = Math.abs(renderViewPosition.getZ() - originCoordinate.getZ());
int dX = Math.abs(cX - originCoordinate.getX());
int dY = Math.abs(cY - originCoordinate.getY());
int dZ = Math.abs(cZ - originCoordinate.getZ());
if (dX > MAX_ORIGIN_DISTANCE ||
dY > MAX_ORIGIN_DISTANCE ||
dZ > MAX_ORIGIN_DISTANCE) {
dY > MAX_ORIGIN_DISTANCE ||
dZ > MAX_ORIGIN_DISTANCE) {
originCoordinate = renderViewPosition;
originCoordinate = new BlockPos(cX, cY, cZ);
ArrayList<TileEntity> instancedTiles = new ArrayList<>(instances.keySet());
invalidate();
instancedTiles.forEach(this::add);
}
super.beginFrame(cameraX, cameraY, cameraZ);
}
@Override

View file

@ -2,13 +2,11 @@ package com.simibubi.create.foundation.render.backend;
import java.util.concurrent.ConcurrentHashMap;
import org.lwjgl.opengl.GL11;
import com.simibubi.create.foundation.render.KineticRenderer;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.KineticDebugger;
import com.simibubi.create.content.schematics.SchematicWorld;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.WorldAttached;
@ -41,14 +39,15 @@ public class FastRenderDispatcher {
public static void tick() {
ClientWorld world = Minecraft.getInstance().world;
CreateClient.kineticRenderer.tick();
KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world);
kineticRenderer.tick();
ConcurrentHashMap.KeySetView<TileEntity, Boolean> map = queuedUpdates.get(world);
map
.forEach(te -> {
map.remove(te);
CreateClient.kineticRenderer.update(te);
kineticRenderer.update(te);
});
}
@ -71,9 +70,12 @@ public class FastRenderDispatcher {
public static void renderLayer(RenderType layer, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) {
if (!Backend.canUseInstancing()) return;
ClientWorld world = Minecraft.getInstance().world;
KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world);
layer.startDrawing();
CreateClient.kineticRenderer.render(layer, viewProjection, cameraX, cameraY, cameraZ);
kineticRenderer.render(layer, viewProjection, cameraX, cameraY, cameraZ);
layer.endDrawing();
}

View file

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.annotation.Nullable;
@ -39,5 +40,9 @@ public class WorldAttached<T> {
public void put(IWorld world, T entry) {
attached.put(world, entry);
}
public void forEach(Consumer<T> consumer) {
attached.values().forEach(consumer);
}
}