Moving light updates

- Better system for moving objects that want to receive light updates
 - LightProvider interface to better abstract light lookups
 - All light listeners use GridAlignedBBs
 - More utility in GridAlignedBB
This commit is contained in:
Jozufozu 2021-09-04 16:40:40 -07:00
parent 7ca4ea5c3e
commit fe304041c5
19 changed files with 191 additions and 168 deletions

View file

@ -4,6 +4,7 @@ import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.config.FlwPackets;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.DistExecutor;
@ -28,7 +29,11 @@ public class Flywheel {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> FlywheelClient::clientInit);
}
private void setup(final FMLCommonSetupEvent event) {
public static ResourceLocation rl(String path) {
return new ResourceLocation(ID, path);
}
private void setup(final FMLCommonSetupEvent event) {
FlwPackets.registerPackets();
}
}

View file

@ -5,6 +5,7 @@ import com.jozufozu.flywheel.core.AtlasStitcher;
import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.light.debug.DebugView;
import com.jozufozu.flywheel.vanilla.VanillaInstances;
import net.minecraftforge.eventbus.api.IEventBus;

View file

@ -8,11 +8,10 @@ import com.jozufozu.flywheel.backend.material.MaterialManager;
import com.jozufozu.flywheel.core.materials.IFlatLight;
import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.ILightUpdateListener;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.light.LightProvider;
import com.jozufozu.flywheel.light.ListenerStatus;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
@ -23,7 +22,7 @@ import net.minecraft.world.World;
public abstract class AbstractInstance implements IInstance, ILightUpdateListener {
protected final MaterialManager materialManager;
protected final World world;
public final World world;
public AbstractInstance(MaterialManager materialManager, World world) {
this.materialManager = materialManager;
@ -74,7 +73,7 @@ public abstract class AbstractInstance implements IInstance, ILightUpdateListene
}
@Override
public void onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed) {
public void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed) {
updateLight();
}

View file

@ -11,6 +11,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.material.MaterialManager;
import com.jozufozu.flywheel.backend.material.MaterialManagerImpl;
import com.jozufozu.flywheel.light.LightUpdater;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.client.renderer.ActiveRenderInfo;
@ -285,7 +286,7 @@ public abstract class InstanceManager<T> implements MaterialManagerImpl.OriginSh
if (renderer != null) {
renderer.updateLight();
renderer.startListening();
LightUpdater.get(renderer.world).addListener(renderer);
instances.put(obj, renderer);
if (renderer instanceof IDynamicInstance) dynamicInstances.put(obj, (IDynamicInstance) renderer);

View file

@ -1,19 +1,18 @@
package com.jozufozu.flywheel.backend.instancing.entity;
import java.util.Arrays;
import java.util.stream.Stream;
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.ITickableInstance;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import com.jozufozu.flywheel.backend.material.MaterialManager;
import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.ILightUpdateListener;
import com.jozufozu.flywheel.light.ListenerStatus;
import com.jozufozu.flywheel.light.Volume;
import com.jozufozu.flywheel.light.IMovingListener;
import com.jozufozu.flywheel.light.LightProvider;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d;
@ -35,25 +34,33 @@ import net.minecraft.util.math.vector.Vector3i;
*
* @param <E> The type of {@link Entity} your class is an instance of.
*/
public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements ILightUpdateListener {
public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements ILightUpdateListener, IMovingListener {
protected final E entity;
protected final GridAlignedBB bounds;
public EntityInstance(MaterialManager materialManager, E entity) {
super(materialManager, entity.level);
this.entity = entity;
startListening();
bounds = GridAlignedBB.from(entity.getBoundingBox());
}
@Override
public Volume.Box getVolume() {
return Volume.box(entity.getBoundingBox());
public GridAlignedBB getVolume() {
return bounds;
}
@Override
public ListenerStatus status() {
return ListenerStatus.UPDATE;
public boolean update(LightProvider provider) {
AxisAlignedBB boundsNow = entity.getBoundingBox();
if (bounds.sameAs(boundsNow)) return false;
bounds.assign(boundsNow);
updateLight();
return true;
}
/**

View file

@ -9,7 +9,6 @@ import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.materials.ModelData;
import com.jozufozu.flywheel.core.materials.OrientedData;
import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.Volume;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
@ -85,7 +84,7 @@ public abstract class TileEntityInstance<T extends TileEntity> extends AbstractI
}
@Override
public Volume.Block getVolume() {
return Volume.block(pos);
public GridAlignedBB getVolume() {
return GridAlignedBB.from(pos);
}
}

View file

@ -11,7 +11,6 @@ import net.minecraft.client.world.ClientWorld;
import net.minecraft.world.IWorld;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@ -51,7 +50,7 @@ public class ForgeEvents {
@SubscribeEvent
public static void rwle(TickEvent.ClientTickEvent e) {
if (e.phase == TickEvent.Phase.END && Backend.isGameActive())
LightUpdater.getInstance().tick();
LightUpdater.get(Minecraft.getInstance().level).tick();
}
}

View file

@ -0,0 +1,30 @@
package com.jozufozu.flywheel.light;
import java.util.Map;
import java.util.WeakHashMap;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.LightType;
public class BasicProvider implements LightProvider {
private static final Map<IBlockDisplayReader, BasicProvider> wrappers = new WeakHashMap<>();
public static BasicProvider get(IBlockDisplayReader world) {
return wrappers.computeIfAbsent(world, BasicProvider::new);
}
private final BlockPos.Mutable pos = new BlockPos.Mutable();
private final IBlockDisplayReader reader;
public BasicProvider(IBlockDisplayReader reader) {
this.reader = reader;
}
@Override
public int getLight(LightType type, int x, int y, int z) {
return reader.getBrightness(type, pos.set(x, y, z));
}
}

View file

@ -75,6 +75,15 @@ public class GridAlignedBB {
return minX == other.minX && minY == other.minY && minZ == other.minZ && maxX == other.maxX && maxY == other.maxY && maxZ == other.maxZ;
}
public boolean sameAs(AxisAlignedBB other) {
return minX == Math.floor(other.minX)
&& minY == Math.floor(other.minY)
&& minZ == Math.floor(other.minZ)
&& maxX == Math.ceil(other.maxX)
&& maxY == Math.ceil(other.maxY)
&& maxZ == Math.ceil(other.maxZ);
}
public void fixMinMax() {
int minX = Math.min(this.minX, this.maxX);
int minY = Math.min(this.minY, this.maxY);
@ -245,6 +254,24 @@ public class GridAlignedBB {
this.maxZ = Math.max(this.maxZ, (int) Math.ceil(other.maxZ));
}
public void assign(AxisAlignedBB other) {
this.minX = (int) Math.floor(other.minX);
this.minY = (int) Math.floor(other.minY);
this.minZ = (int) Math.floor(other.minZ);
this.maxX = (int) Math.ceil(other.maxX);
this.maxY = (int) Math.ceil(other.maxY);
this.maxZ = (int) Math.ceil(other.maxZ);
}
public void assign(GridAlignedBB other) {
this.minX = other.minX;
this.minY = other.minY;
this.minZ = other.minZ;
this.maxX = other.maxX;
this.maxY = other.maxY;
this.maxZ = other.maxZ;
}
public boolean intersects(GridAlignedBB other) {
return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ);
}
@ -297,5 +324,4 @@ public class GridAlignedBB {
result = 31 * result + maxZ;
return result;
}
}

View file

@ -1,32 +1,23 @@
package com.jozufozu.flywheel.light;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.LightType;
/**
* Anything can implement this, implementors should call {@link #startListening}
* appropriately to make sure they get the updates they want.
*/
public interface ILightUpdateListener {
Volume getVolume();
GridAlignedBB getVolume();
ListenerStatus status();
default void startListening() {
LightUpdater.getInstance().addListener(this);
}
/**
* Called when a light updates in a chunk the implementor cares about.
*/
void onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed);
void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed);
/**
* Called when the server sends light data to the client.
*
*/
default void onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) {
default void onLightPacket(LightProvider world, int chunkX, int chunkZ) {
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
onLightUpdate(world, LightType.BLOCK, changedVolume);

View file

@ -0,0 +1,5 @@
package com.jozufozu.flywheel.light;
public interface IMovingListener extends ILightUpdateListener {
boolean update(LightProvider provider);
}

View file

@ -0,0 +1,12 @@
package com.jozufozu.flywheel.light;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.world.LightType;
public interface LightProvider {
int getLight(LightType type, int x, int y, int z);
default int getPackedLight(int x, int y, int z) {
return LightTexture.pack(getLight(LightType.BLOCK, x, y, z), getLight(LightType.SKY, x, y, z));
}
}

View file

@ -1,42 +1,42 @@
package com.jozufozu.flywheel.light;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import com.jozufozu.flywheel.util.WeakHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.SectionPos;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.LightType;
/**
* Keeps track of what chunks/sections each listener is in so we can update exactly what needs to be updated.
*/
public class LightUpdater {
private static LightUpdater instance;
public static LightUpdater getInstance() {
if (instance == null) instance = new LightUpdater();
return instance;
private static final Map<IBlockDisplayReader, LightUpdater> light = new HashMap<>();
public static LightUpdater get(IBlockDisplayReader world) {
return light.computeIfAbsent(world, LightUpdater::new);
}
private final WeakHashSet<ILightUpdateListener> allListeners;
private final WeakContainmentMultiMap<ILightUpdateListener> sections;
private final WeakContainmentMultiMap<ILightUpdateListener> chunks;
private final LightProvider provider;
public LightUpdater() {
allListeners = new WeakHashSet<>();
sections = new WeakContainmentMultiMap<>();
chunks = new WeakContainmentMultiMap<>();
private final WeakHashSet<IMovingListener> movingListeners = new WeakHashSet<>();
private final WeakContainmentMultiMap<ILightUpdateListener> sections = new WeakContainmentMultiMap<>();
private final WeakContainmentMultiMap<ILightUpdateListener> chunks = new WeakContainmentMultiMap<>();
public LightUpdater(IBlockDisplayReader world) {
provider = BasicProvider.get(world);
}
public void tick() {
for (ILightUpdateListener listener : allListeners) {
if (listener.status() == ListenerStatus.UPDATE) {
for (IMovingListener listener : movingListeners) {
if (listener.update(provider)) {
addListener(listener);
listener.onLightUpdate(Minecraft.getInstance().level, LightType.BLOCK, null);
}
}
}
@ -47,55 +47,41 @@ public class LightUpdater {
* @param listener The object that wants to receive light update notifications.
*/
public void addListener(ILightUpdateListener listener) {
allListeners.add(listener);
if (listener instanceof IMovingListener)
movingListeners.add(((IMovingListener) listener));
Volume volume = listener.getVolume();
GridAlignedBB box = listener.getVolume();
LongSet sections = this.sections.getAndResetContainment(listener);
LongSet chunks = this.chunks.getAndResetContainment(listener);
if (volume instanceof Volume.Block) {
BlockPos pos = ((Volume.Block) volume).pos;
long sectionPos = blockToSection(pos);
this.sections.put(sectionPos, listener);
sections.add(sectionPos);
int minX = SectionPos.blockToSectionCoord(box.minX);
int minY = SectionPos.blockToSectionCoord(box.minY);
int minZ = SectionPos.blockToSectionCoord(box.minZ);
int maxX = SectionPos.blockToSectionCoord(box.maxX);
int maxY = SectionPos.blockToSectionCoord(box.maxY);
int maxZ = SectionPos.blockToSectionCoord(box.maxZ);
long chunkPos = sectionToChunk(sectionPos);
this.chunks.put(chunkPos, listener);
chunks.add(chunkPos);
} else if (volume instanceof Volume.Box) {
GridAlignedBB box = ((Volume.Box) volume).box;
int minX = SectionPos.blockToSectionCoord(box.minX);
int minY = SectionPos.blockToSectionCoord(box.minY);
int minZ = SectionPos.blockToSectionCoord(box.minZ);
int maxX = SectionPos.blockToSectionCoord(box.maxX);
int maxY = SectionPos.blockToSectionCoord(box.maxY);
int maxZ = SectionPos.blockToSectionCoord(box.maxZ);
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
long sectionPos = SectionPos.asLong(x, y, z);
this.sections.put(sectionPos, listener);
sections.add(sectionPos);
}
long chunkPos = SectionPos.asLong(x, 0, z);
this.chunks.put(chunkPos, listener);
chunks.add(chunkPos);
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
long sectionPos = SectionPos.asLong(x, y, z);
this.sections.put(sectionPos, listener);
sections.add(sectionPos);
}
long chunkPos = SectionPos.asLong(x, 0, z);
this.chunks.put(chunkPos, listener);
chunks.add(chunkPos);
}
}
}
/**
* Dispatch light updates to all registered {@link ILightUpdateListener}s.
*
* @param world The world in which light was updated.
* @param type The type of light that changed.
* @param sectionPos A long representing the section position where light changed.
*/
public void onLightUpdate(IBlockDisplayReader world, LightType type, long sectionPos) {
public void onLightUpdate(LightType type, long sectionPos) {
Set<ILightUpdateListener> set = sections.get(sectionPos);
if (set == null || set.isEmpty()) return;
@ -105,7 +91,7 @@ public class LightUpdater {
GridAlignedBB chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos));
for (ILightUpdateListener listener : set) {
listener.onLightUpdate(world, type, chunkBox.copy());
listener.onLightUpdate(provider, type, chunkBox.copy());
}
}
@ -113,9 +99,8 @@ public class LightUpdater {
* Dispatch light updates to all registered {@link ILightUpdateListener}s
* when the server sends lighting data for an entire chunk.
*
* @param world The world in which light was updated.
*/
public void onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) {
public void onLightPacket(int chunkX, int chunkZ) {
long chunkPos = SectionPos.asLong(chunkX, 0, chunkZ);
Set<ILightUpdateListener> set = chunks.get(chunkPos);
@ -125,7 +110,7 @@ public class LightUpdater {
set.removeIf(l -> l.status().shouldRemove());
for (ILightUpdateListener listener : set) {
listener.onLightPacket(world, chunkX, chunkZ);
listener.onLightPacket(provider, chunkX, chunkZ);
}
}
@ -136,4 +121,12 @@ public class LightUpdater {
public static long sectionToChunk(long sectionPos) {
return sectionPos & 0xFFFFFFFFFFF_00000L;
}
public Stream<GridAlignedBB> getAllBoxes() {
return chunks.stream().map(ILightUpdateListener::getVolume);
}
public boolean isEmpty() {
return chunks.isEmpty();
}
}

View file

@ -124,11 +124,12 @@ public class LightVolume {
if (removed) return;
if (textureVolume.contains(newSampleVolume)) {
BasicProvider basicProvider = BasicProvider.get(world);
if (newSampleVolume.intersects(sampleVolume)) {
GridAlignedBB newArea = newSampleVolume.intersect(sampleVolume);
sampleVolume = newSampleVolume;
copyLight(world, newArea);
copyLight(basicProvider, newArea);
} else {
sampleVolume = newSampleVolume;
initialize(world);
@ -143,7 +144,7 @@ public class LightVolume {
}
}
public void notifyLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changedVolume) {
public void notifyLightUpdate(LightProvider world, LightType type, GridAlignedBB changedVolume) {
if (removed) return;
if (!changedVolume.intersects(sampleVolume)) return;
@ -153,7 +154,7 @@ public class LightVolume {
else if (type == LightType.SKY) copySky(world, changedVolume);
}
public void notifyLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) {
public void notifyLightPacket(LightProvider world, int chunkX, int chunkZ) {
if (removed) return;
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
@ -193,17 +194,13 @@ public class LightVolume {
*
* @param worldVolume the region in the world to copy data from.
*/
public void copyBlock(IBlockDisplayReader world, GridAlignedBB worldVolume) {
BlockPos.Mutable pos = new BlockPos.Mutable();
public void copyBlock(LightProvider world, GridAlignedBB worldVolume) {
int xShift = textureVolume.minX;
int yShift = textureVolume.minY;
int zShift = textureVolume.minZ;
worldVolume.forEachContained((x, y, z) -> {
pos.set(x, y, z);
int light = world.getBrightness(LightType.BLOCK, pos);
int light = world.getLight(LightType.BLOCK, x, y, z);
writeBlock(x - xShift, y - yShift, z - zShift, light);
});
@ -216,17 +213,13 @@ public class LightVolume {
*
* @param worldVolume the region in the world to copy data from.
*/
public void copySky(IBlockDisplayReader world, GridAlignedBB worldVolume) {
BlockPos.Mutable pos = new BlockPos.Mutable();
public void copySky(LightProvider world, GridAlignedBB worldVolume) {
int xShift = textureVolume.minX;
int yShift = textureVolume.minY;
int zShift = textureVolume.minZ;
worldVolume.forEachContained((x, y, z) -> {
pos.set(x, y, z);
int light = world.getBrightness(LightType.SKY, pos);
int light = world.getLight(LightType.SKY, x, y, z);
writeSky(x - xShift, y - yShift, z - zShift, light);
});
@ -239,7 +232,7 @@ public class LightVolume {
*
* @param worldVolume the region in the world to copy data from.
*/
public void copyLight(IBlockDisplayReader world, GridAlignedBB worldVolume) {
public void copyLight(LightProvider world, GridAlignedBB worldVolume) {
BlockPos.Mutable pos = new BlockPos.Mutable();
int xShift = textureVolume.minX;
@ -249,8 +242,8 @@ public class LightVolume {
worldVolume.forEachContained((x, y, z) -> {
pos.set(x, y, z);
int block = world.getBrightness(LightType.BLOCK, pos);
int sky = world.getBrightness(LightType.SKY, pos);
int block = world.getLight(LightType.BLOCK, x, y, z);
int sky = world.getLight(LightType.SKY, x, y, z);
writeLight(x - xShift, y - yShift, z - zShift, block, sky);
});

View file

@ -1,35 +0,0 @@
package com.jozufozu.flywheel.light;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
public class Volume {
public static Volume.Block block(BlockPos pos) {
return new Block(pos);
}
public static Volume.Box box(GridAlignedBB box) {
return new Box(box);
}
public static Volume.Box box(AxisAlignedBB box) {
return new Box(GridAlignedBB.from(box));
}
public static class Block extends Volume {
public final BlockPos pos;
public Block(BlockPos pos) {
this.pos = pos;
}
}
public static class Box extends Volume {
public final GridAlignedBB box;
public Box(GridAlignedBB box) {
this.box = box;
}
}
}

View file

@ -1,5 +1,8 @@
package com.jozufozu.flywheel.light;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.function.LongConsumer;
@ -11,7 +14,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongRBTreeSet;
import it.unimi.dsi.fastutil.longs.LongSet;
public class WeakContainmentMultiMap<T> {
public class WeakContainmentMultiMap<T> extends AbstractCollection<T> {
private final Long2ObjectMap<WeakHashSet<T>> forward;
private final WeakHashMap<T, LongSet> reverse;
@ -53,4 +56,14 @@ public class WeakContainmentMultiMap<T> {
public void put(long sectionPos, T listener) {
forward.computeIfAbsent(sectionPos, $ -> new WeakHashSet<>()).add(listener);
}
@Override
public Iterator<T> iterator() {
return reverse.keySet().iterator();
}
@Override
public int size() {
return reverse.size();
}
}

View file

@ -1,25 +1,17 @@
package com.jozufozu.flywheel.mixin.light;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
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.light.LightUpdater;
import com.jozufozu.flywheel.util.ChunkUtil;
import net.minecraft.client.multiplayer.ClientChunkProvider;
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.world.LightType;
import net.minecraft.world.chunk.AbstractChunkProvider;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@ -38,7 +30,7 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
ClientChunkProvider thi = ((ClientChunkProvider) (Object) this);
ClientWorld world = (ClientWorld) thi.getLevel();
LightUpdater.getInstance()
.onLightUpdate(world, type, pos.asLong());
LightUpdater.get(world)
.onLightUpdate(type, pos.asLong());
}
}

View file

@ -1,25 +1,17 @@
package com.jozufozu.flywheel.mixin.light;
import java.util.Arrays;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.backend.RenderWork;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.light.LightUpdater;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.play.ClientPlayNetHandler;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.network.play.server.SUpdateLightPacket;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.world.chunk.Chunk;
@Mixin(ClientPlayNetHandler.class)
public class NetworkLightUpdateMixin {
@ -34,8 +26,8 @@ public class NetworkLightUpdateMixin {
int chunkX = packet.getX();
int chunkZ = packet.getZ();
LightUpdater.getInstance()
.onLightPacket(world, chunkX, chunkZ);
LightUpdater.get(world)
.onLightPacket(chunkX, chunkZ);
});
}
}

View file

@ -31,6 +31,7 @@ import net.minecraft.util.math.vector.Vector3f;
public class ChestInstance<T extends TileEntity & IChestLid> extends TileEntityInstance<T> implements IDynamicInstance {
private final MatrixTransformStack stack = new MatrixTransformStack();
private final OrientedData body;
private final ModelData lid;
@ -91,9 +92,8 @@ public class ChestInstance<T extends TileEntity & IChestLid> extends TileEntityI
float angleX = -(progress * ((float) Math.PI / 2F));
MatrixTransformStack stack = new MatrixTransformStack();
stack.translate(getInstancePosition())
stack.setIdentity()
.translate(getInstancePosition())
.translate(0, 9f/16f, 0)
.centre()
.multiply(baseRotation)