Crash fix and refactor

- Check that sectionY is within the bounds of the chunk's section array, fixes #2
 - Refactor usages of Tile and Entity InstanceManagers to refer to the base class InstanceManager<>
This commit is contained in:
Jozsef 2021-07-02 13:12:33 -07:00
parent 5da6a56be5
commit c79c41c16f
6 changed files with 47 additions and 13 deletions

View file

@ -41,6 +41,7 @@ minecraft {
property 'forge.logging.markers', '' property 'forge.logging.markers', ''
property 'forge.logging.console.level', 'debug' property 'forge.logging.console.level', 'debug'
property 'fml.earlyprogresswindow', 'false'
arg "-mixin.config=flywheel.mixins.json" arg "-mixin.config=flywheel.mixins.json"

View file

@ -50,8 +50,8 @@ import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(Dist.CLIENT) @Mod.EventBusSubscriber(Dist.CLIENT)
public class InstancedRenderDispatcher { public class InstancedRenderDispatcher {
private static final WorldAttached<EntityInstanceManager> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(Contexts.WORLD.getMaterialManager(world))); private static final WorldAttached<InstanceManager<Entity>> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(Contexts.WORLD.getMaterialManager(world)));
private static final WorldAttached<TileInstanceManager> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(Contexts.WORLD.getMaterialManager(world))); private static final WorldAttached<InstanceManager<TileEntity>> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(Contexts.WORLD.getMaterialManager(world)));
private static final LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> { private static final LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> {
Vector<CrumblingInstanceManager> renderers = new Vector<>(10); Vector<CrumblingInstanceManager> renderers = new Vector<>(10);
@ -62,12 +62,12 @@ public class InstancedRenderDispatcher {
}); });
@Nonnull @Nonnull
public static TileInstanceManager getTiles(IWorld world) { public static InstanceManager<TileEntity> getTiles(IWorld world) {
return tileInstanceManager.get(world); return tileInstanceManager.get(world);
} }
@Nonnull @Nonnull
public static EntityInstanceManager getEntities(IWorld world) { public static InstanceManager<Entity> getEntities(IWorld world) {
return entityInstanceManager.get(world); return entityInstanceManager.get(world);
} }
@ -190,10 +190,10 @@ public class InstancedRenderDispatcher {
Contexts.WORLD.getMaterialManager(world) Contexts.WORLD.getMaterialManager(world)
.delete(); .delete();
TileInstanceManager tiles = tileInstanceManager.replace(world); InstanceManager<TileEntity> tiles = tileInstanceManager.replace(world);
world.loadedTileEntityList.forEach(tiles::add); world.loadedTileEntityList.forEach(tiles::add);
EntityInstanceManager entities = entityInstanceManager.replace(world); InstanceManager<Entity> entities = entityInstanceManager.replace(world);
world.getAllEntities() world.getAllEntities()
.forEach(entities::add); .forEach(entities::add);
} }

View file

@ -10,6 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
@ -46,7 +47,7 @@ public class TileWorldHookMixin {
@Inject(at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", ordinal = 0), method = "tickBlockEntities") @Inject(at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", ordinal = 0), method = "tickBlockEntities")
private void onChunkUnload(CallbackInfo ci) { private void onChunkUnload(CallbackInfo ci) {
if (isRemote) { if (isRemote) {
TileInstanceManager kineticRenderer = InstancedRenderDispatcher.getTiles(self); InstanceManager<TileEntity> kineticRenderer = InstancedRenderDispatcher.getTiles(self);
for (TileEntity tile : tileEntitiesToBeRemoved) { for (TileEntity tile : tileEntitiesToBeRemoved) {
kineticRenderer.remove(tile); kineticRenderer.remove(tile);
} }

View file

@ -7,11 +7,17 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.util.ChunkUtil;
import net.minecraft.client.multiplayer.ClientChunkProvider; import net.minecraft.client.multiplayer.ClientChunkProvider;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.SectionPos; import net.minecraft.util.math.SectionPos;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
import net.minecraft.world.chunk.AbstractChunkProvider; import net.minecraft.world.chunk.AbstractChunkProvider;
@ -38,17 +44,19 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
int sectionY = pos.getSectionY(); int sectionY = pos.getSectionY();
if (chunk != null) { if (ChunkUtil.isValidSection(chunk, sectionY)) {
InstanceManager<TileEntity> tiles = InstancedRenderDispatcher.getTiles(world);
InstanceManager<Entity> entities = InstancedRenderDispatcher.getEntities(world);
chunk.getTileEntityMap() chunk.getTileEntityMap()
.entrySet() .entrySet()
.stream() .stream()
.filter(entry -> SectionPos.toChunk(entry.getKey() .filter(entry -> SectionPos.toChunk(entry.getKey()
.getY()) == sectionY) .getY()) == sectionY)
.map(Map.Entry::getValue) .map(Map.Entry::getValue)
.forEach(InstancedRenderDispatcher.getTiles(world)::onLightUpdate); .forEach(tiles::onLightUpdate);
if (sectionY >= 0) // TODO: 1.17 chunk.getEntityLists()[sectionY].forEach(entities::onLightUpdate);
chunk.getEntityLists()[sectionY].forEach(InstancedRenderDispatcher.getEntities(world)::onLightUpdate);
} }
LightUpdater.getInstance() LightUpdater.getInstance()

View file

@ -8,13 +8,16 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.RenderWork;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.LightUpdater;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.network.play.ClientPlayNetHandler; import net.minecraft.client.network.play.ClientPlayNetHandler;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.network.play.server.SUpdateLightPacket; import net.minecraft.network.play.server.SUpdateLightPacket;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ClassInheritanceMultiMap; import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
@ -35,13 +38,16 @@ public class NetworkLightUpdateMixin {
.getChunk(chunkX, chunkZ, false); .getChunk(chunkX, chunkZ, false);
if (chunk != null) { if (chunk != null) {
InstanceManager<TileEntity> tiles = InstancedRenderDispatcher.getTiles(world);
InstanceManager<Entity> entities = InstancedRenderDispatcher.getEntities(world);
chunk.getTileEntityMap() chunk.getTileEntityMap()
.values() .values()
.forEach(InstancedRenderDispatcher.getTiles(world)::onLightUpdate); .forEach(tiles::onLightUpdate);
Arrays.stream(chunk.getEntityLists()) Arrays.stream(chunk.getEntityLists())
.flatMap(ClassInheritanceMultiMap::stream) .flatMap(ClassInheritanceMultiMap::stream)
.forEach(InstancedRenderDispatcher.getEntities(world)::onLightUpdate); .forEach(entities::onLightUpdate);
} }
LightUpdater.getInstance() LightUpdater.getInstance()

View file

@ -0,0 +1,18 @@
package com.jozufozu.flywheel.util;
import javax.annotation.Nullable;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkSection;
public class ChunkUtil {
public static boolean isValidSection(@Nullable Chunk chunk, int sectionY) {
if (chunk == null) return false;
// TODO: 1.17
ChunkSection[] sections = chunk.getSections();
return sectionY >= 0 && sectionY < sections.length;
}
}