Skip to content

Commit

Permalink
add shimmer support
Browse files Browse the repository at this point in the history
  • Loading branch information
Rushmead committed Aug 16, 2024
1 parent aee30f1 commit 16fa921
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 186 deletions.
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ allprojects {
name = 'Rushmead'
url = 'https://mvn.imabad.dev/repository/maven-releases/'
}
// For Shimmer
maven {
url "https://maven.firstdarkdev.xyz/snapshots"
}
maven { url 'https://jitpack.io' }
mavenCentral()
mavenLocal()
// Add repositories to retrieve artifacts from in here.
Expand Down
3 changes: 3 additions & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ dependencies {
//YAML
implementation "org.yaml:snakeyaml:${rootProject.snakeyaml_version}"
shadowCommon "org.yaml:snakeyaml:${rootProject.snakeyaml_version}"

// Shimmer
modImplementation "com.lowdragmc.shimmer:Shimmer-common:${minecraft_version}-${shimmer_version}"
}

publishing {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ public static String getModVersion() {
throw new AssertionError();
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dev.imabad.theatrical.api;

import dev.imabad.theatrical.lighting.LightManager;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import org.joml.Vector3f;

public interface DynamicLightProvider {

BlockPos getOwnerPos();
Vector3f getLightPos();
Level getLevel();
default boolean isLightEnabled() {
return LightManager.containsLightSource(this);
}
default void setLightEnabled(boolean enabled) {
resetLight();
if(enabled){
LightManager.addLightSource(this);
} else {
LightManager.removeLightSource(this);
}
}
void resetLight();
int getLightLuminance();
void lightTick();
boolean shouldUpdateLight();
boolean updateDynamicLight(LevelRenderer renderer);
void scheduleTrackedChunksRebuild(LevelRenderer renderer);
int getLightColour();
int getLightSpread();
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package dev.imabad.theatrical.blockentities.light;

import dev.imabad.theatrical.api.DynamicLightProvider;
import dev.imabad.theatrical.api.Fixture;
import dev.imabad.theatrical.api.FixtureProvider;
import dev.imabad.theatrical.api.Support;
import dev.imabad.theatrical.blockentities.ClientSyncBlockEntity;
import dev.imabad.theatrical.blocks.HangableBlock;
import dev.imabad.theatrical.blocks.light.BaseLightBlock;
import dev.imabad.theatrical.config.TheatricalConfig;
import dev.imabad.theatrical.lighting.LambDynamicLight;
import dev.imabad.theatrical.lighting.LambDynamicLightUtil;
import dev.imabad.theatrical.lighting.LightManager;
import dev.imabad.theatrical.mixin.ClipContextAccessor;
Expand All @@ -28,14 +29,15 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import org.joml.Vector3f;

import java.util.Optional;

public abstract class BaseLightBlockEntity extends ClientSyncBlockEntity implements FixtureProvider, LambDynamicLight {
public abstract class BaseLightBlockEntity extends ClientSyncBlockEntity implements FixtureProvider, DynamicLightProvider {
AABB INFINITE_EXTENT_AABB = new AABB(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
private double distance = 0;
protected int pan, tilt, focus, intensity, red, green, blue = 0;
protected int prevTilt, prevPan, prevFocus, prevIntensity, prevRed, prevGreen, prevBlue = 0;
protected int prevTilt, prevPan, prevFocus, prevIntensity, prevRed, prevGreen, prevBlue, prevColour, prevSpread = 0;
private long tickTimer = 0;
private BlockPos emissionBlock, prevEmissionBlock;
private int prevLuminance;
Expand Down Expand Up @@ -93,6 +95,34 @@ public AABB getRenderBoundingBox(){
return INFINITE_EXTENT_AABB;
}

public BlockPos getEmissionBlock(){
return emissionBlock;
}

public BlockPos getPrevEmissionBlock() {
return prevEmissionBlock;
}

public void setPrevEmissionBlock(BlockPos prevEmissionBlock) {
this.prevEmissionBlock = prevEmissionBlock;
}

public int getPrevLuminance() {
return prevLuminance;
}

public void setPrevLuminance(int prevLuminance) {
this.prevLuminance = prevLuminance;
}

public LongOpenHashSet getTrackedLitChunkPos() {
return trackedLitChunkPos;
}

public void setTrackedLitChunkPos(LongOpenHashSet trackedLitChunkPos) {
this.trackedLitChunkPos = trackedLitChunkPos;
}

protected boolean storePrev(){
boolean hasChanged = false;
if(tilt != prevTilt){
Expand Down Expand Up @@ -167,9 +197,9 @@ public static <T extends BlockEntity> void tick(Level level, BlockPos pos, Block
}
if (level.isClientSide() && LightManager.shouldUpdateDynamicLight()) {
if (tile.isRemoved()) {
tile.setDynamicLightEnabled(false);
tile.setLightEnabled(false);
} else {
tile.dynamicLightTick();
tile.lightTick();
LightManager.updateTracking(tile);
}
}
Expand Down Expand Up @@ -237,6 +267,14 @@ public int getPrevColor(){
return (getPrevRed() << 16) | (getPrevGreen() << 8) | getPrevBlue();
}

public int getPrevColour() {
return prevColour;
}

public void setPrevColour(int prevColour) {
this.prevColour = prevColour;
}

public Optional<BlockState> getSupportingStructure(){
if(getLevel() != null){
BlockState blockState = getLevel().getBlockState(getBlockPos()
Expand Down Expand Up @@ -366,7 +404,7 @@ public double doRayTrace() {
@Override
public void setRemoved() {
if(emissionBlock != null){
this.setDynamicLightEnabled(false);
this.setLightEnabled(false);
emissionBlock = null;
}
super.setRemoved();
Expand All @@ -383,96 +421,72 @@ public void setPan(int pan){
}

@Override
public double getDynamicLightX() {
return emissionBlock.getX();
}

@Override
public double getDynamicLightY() {
return emissionBlock.getY();
public int getLightLuminance() {
float newVal = intensity / 255f;
return (int) (newVal * 15f);
}

@Override
public double getDynamicLightZ() {
return emissionBlock.getZ();
public Vector3f getLightPos() {
return Vec3.atCenterOf(emissionBlock).toVector3f();
}

@Override
public Level getDynamicLightWorld() {
return this.getLevel();
public boolean isLightEnabled() {
return DynamicLightProvider.super.isLightEnabled();
}

@Override
public void resetDynamicLight() {
public void resetLight() {

}
@Override
public int getLuminance() {
float newVal = intensity / 255f;
return (int) (newVal * 15f);
}

@Override
public void dynamicLightTick() {
public void lightTick() {

}

@Override
public boolean shouldUpdateDynamicLight() {
public boolean shouldUpdateLight() {
return LightManager.shouldUpdateDynamicLight() && emitsLight() && emissionBlock != null;
}

@Override
public boolean lambdynlights$updateDynamicLight(LevelRenderer renderer) {
if (!this.shouldUpdateDynamicLight())
public boolean updateDynamicLight(LevelRenderer renderer) {
if (!this.shouldUpdateLight())
return false;
int luminance = this.getLuminance();

if(!emissionBlock.equals(prevEmissionBlock) || luminance != prevLuminance){
this.prevEmissionBlock = emissionBlock;
this.prevLuminance = luminance;
var newPos = new LongOpenHashSet();

if (luminance > 0) {
var entityChunkPos = new ChunkPos(emissionBlock);
var chunkPos = new BlockPos.MutableBlockPos(entityChunkPos.x, LambDynamicLightUtil.getSectionCoord(emissionBlock.getY()), entityChunkPos.z);

LightManager.scheduleChunkRebuild(renderer, chunkPos);
LightManager.updateTrackedChunks(chunkPos, this.trackedLitChunkPos, newPos);

var directionX = (emissionBlock.getX() & 15) >= 8 ? Direction.EAST : Direction.WEST;
var directionY = (emissionBlock.getY() & 15) >= 8 ? Direction.UP : Direction.DOWN;
var directionZ = (emissionBlock.getZ() & 15) >= 8 ? Direction.SOUTH : Direction.NORTH;

for (int i = 0; i < 7; i++) {
if (i % 4 == 0) {
chunkPos.move(directionX); // X
} else if (i % 4 == 1) {
chunkPos.move(directionZ); // XZ
} else if (i % 4 == 2) {
chunkPos.move(directionX.getOpposite()); // Z
} else {
chunkPos.move(directionZ.getOpposite()); // origin
chunkPos.move(directionY); // Y
}
LightManager.scheduleChunkRebuild(renderer, chunkPos);
LightManager.updateTrackedChunks(chunkPos, this.trackedLitChunkPos, newPos);
}
}
// Schedules the rebuild of removed chunks.
this.lambdynlights$scheduleTrackedChunksRebuild(renderer);
// Update tracked lit chunks.
this.trackedLitChunkPos = newPos;
return true;
}
return false;
return LightManager.updateDynamicLight(this, renderer);
}

@Override
public void lambdynlights$scheduleTrackedChunksRebuild(LevelRenderer renderer) {
if (Minecraft.getInstance().level == this.level)
public void scheduleTrackedChunksRebuild(LevelRenderer renderer) {
if (Minecraft.getInstance().level == this.level) {
for (long pos : this.trackedLitChunkPos) {
LightManager.scheduleChunkRebuild(renderer, pos);
}
}
}

@Override
public BlockPos getOwnerPos() {
return getBlockPos();
}

@Override
public int getLightColour() {
return ((int)getIntensity() << 24) | getColour();
}

public int getPrevSpread() {
return prevSpread;
}

public void setPrevSpread(int prevSpread) {
this.prevSpread = prevSpread;
}

@Override
public int getLightSpread() {
return (getFocus() / 255) * 8;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.imabad.theatrical.compat;

import dev.architectury.platform.Platform;

public class ModCompat {

public static final boolean SHIMMER = Platform.isModLoaded("shimmer");

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package dev.imabad.theatrical.compat;

import com.lowdragmc.shimmer.client.light.ColorPointLight;
import com.lowdragmc.shimmer.client.light.LightManager;
import dev.imabad.theatrical.api.DynamicLightProvider;
import dev.imabad.theatrical.blockentities.light.BaseLightBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import org.joml.Vector3f;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ShimmerCompat {

private static final Map<BlockPos, ColorPointLight> pos2PointLight = new ConcurrentHashMap<>();
private final static ReentrantReadWriteLock lightSourcesLock = new ReentrantReadWriteLock();

public static void setup(){}

public static void addLight(DynamicLightProvider dynamicLightProvider){
if(!ModCompat.SHIMMER) return;
lightSourcesLock.writeLock().lock();
ColorPointLight light = LightManager.INSTANCE.addLight(dynamicLightProvider.getLightPos(), dynamicLightProvider.getLightColour(), 8);

if(light != null){
pos2PointLight.put(dynamicLightProvider.getOwnerPos(), light);
}
lightSourcesLock.writeLock().unlock();
}

public static void removeLight(BlockPos fixturePos){
if(!ModCompat.SHIMMER) return;
lightSourcesLock.writeLock().lock();
if(pos2PointLight.containsKey(fixturePos)){
pos2PointLight.get(fixturePos).remove();
}
pos2PointLight.remove(fixturePos);
lightSourcesLock.writeLock().unlock();
}

public static void worldClose(){
if(!ModCompat.SHIMMER) return;
lightSourcesLock.writeLock().lock();
pos2PointLight.forEach((blockPos, colorPointLight) -> {
colorPointLight.remove();
});
pos2PointLight.clear();
lightSourcesLock.writeLock().unlock();
}

public static void handleLightUpdate(BaseLightBlockEntity light){
if(!pos2PointLight.containsKey(light.getBlockPos())) return;
ColorPointLight colorPointLight = pos2PointLight.get(light.getBlockPos());
Vector3f lightPos = light.getLightPos();
colorPointLight.setPos(lightPos.x, lightPos.y, lightPos.z);
colorPointLight.setColor(light.getLightColour());
colorPointLight.setEnable(light.isLightEnabled());
colorPointLight.update();
}
}
Loading

0 comments on commit 16fa921

Please sign in to comment.