Skip to content

Commit

Permalink
1.18 lucentcompat (#112)
Browse files Browse the repository at this point in the history
Addresses #105
  • Loading branch information
Nick1st authored May 11, 2023
1 parent 212719f commit 56783a2
Show file tree
Hide file tree
Showing 11 changed files with 253 additions and 2 deletions.
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ allprojects {
maven {
url = "https://modmaven.dev/"
}
maven {
name "Modding Legacy Maven"
url "https://maven.moddinglegacy.com/artifactory/modding-legacy/"
}


flatDir {
dirs 'deps'
Expand Down Expand Up @@ -84,6 +89,8 @@ allprojects {
api fg.deobf("curse.maven:mekanism-268560:${project.mekanism_fileid}")
// Immersive Engineering
api fg.deobf("curse.maven:immersiveengineering-231951:${project.immersiveengineering_fileid}")
// Lucent
api fg.deobf("com.legacy:lucent:${project.lucent_version}")

compileOnly 'com.demonwav.mcdev:annotations:1.0'
}
Expand Down
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ org.gradle.parallel=false
org.gradle.daemon=false

# Mod Properties
mod_version=1.4.15
mod_version=1.4.17
maven_group=qouteall
archives_base_name=immersive-portals

Expand All @@ -28,3 +28,4 @@ mantle_fileid=4353120
sereneseasons_fileid=3693807
mekanism_fileid=3875976
immersiveengineering_fileid=4412849
lucent_version=1.18.2-1.2.2
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,23 @@ public static ClientLevel getWorld(ResourceKey<Level> dimension) {

return clientWorldMap.get(dimension);
}

/**
* Get the client world and create if missing.
* If the dimension id is invalid, it will throw an error
* Use {@link #getWorld(ResourceKey)} instead if possible.
*/
public static synchronized ClientLevel getWorldAsync(ResourceKey<Level> dimension) {
Validate.notNull(dimension);

initializeIfNeeded();

if (!clientWorldMap.containsKey(dimension)) {
return createSecondaryClientWorld(dimension);
}

return clientWorldMap.get(dimension);
}

/**
* Get the client world and create if missing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
boolean flywheelLoaded = LoadingModList.get().getModFileById("flywheel") != null;
return flywheelLoaded;
}

if (mixinClassName.contains("Lucent")) {
boolean lucentLoaded = LoadingModList.get().getModFileById("lucent") != null;
return lucentLoaded;
}

return false;
}
Expand All @@ -66,4 +71,5 @@ public void preApply(String targetClassName, ClassNode targetClass, String mixin
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package qouteall.imm_ptl.core.compat;

import com.legacy.lucent.api.plugin.ILucentPlugin;
import com.legacy.lucent.api.plugin.LucentPlugin;
import com.legacy.lucent.api.registry.EntityLightSourcePosRegistry;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.phys.Vec3;
import qouteall.imm_ptl.core.platform_specific.IPModEntry;
import qouteall.imm_ptl.core.render.context_management.RenderStates;

@LucentPlugin
public class LucentCompat implements ILucentPlugin {

@Override
public String ownerModID() {
return IPModEntry.MODID;
}

@Override
public int getPriority() {
return 10;
}

@Override
public void registerEntityLightSourcePositionGetter(EntityLightSourcePosRegistry registry) {
registry.register(EntityType.PLAYER, player -> new Vec3(RenderStates.originalPlayerPos.x(),
RenderStates.originalPlayerBoundingBox.getYsize() / 2.0 + RenderStates.originalPlayerPos.y(),
RenderStates.originalPlayerPos.z()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package qouteall.imm_ptl.core.compat.mixin;

import com.legacy.lucent.api.LucentData;
import com.legacy.lucent.core.dynamic_lighting.DynamicLightingEngine;
import com.legacy.lucent.core.dynamic_lighting.LightData;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.SectionPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import qouteall.imm_ptl.core.ClientWorldLoader;
import qouteall.imm_ptl.core.render.context_management.RenderStates;

import java.util.List;
import java.util.Map;

// TODO @Nick1st Optimize this, by reducing the mixins if possible, as they add some overhead.
@Mixin(value = DynamicLightingEngine.class, remap = false)
public abstract class MixinLucent {

@Shadow
private static VoxelShape getShape(BlockState state, BlockPos pos, Direction dir) {
return null;
}


@Shadow private static Map<BlockPos, LightData> lightData;

// Make sure the getShape Helper method gets the right level
@Inject(method = "getShape", at = @At("HEAD"), cancellable = true)
private static void patchedGetShape(BlockState state, BlockPos pos, Direction dir, CallbackInfoReturnable<VoxelShape> cir) {
ClientLevel level = ClientWorldLoader.getWorldAsync(RenderStates.originalPlayerDimension);
VoxelShape shape = (state.getLightBlock(level, pos) < 15 && !state.canOcclude())
|| !state.getMaterial().isSolid() ? Shapes.empty() : state.getFaceOcclusionShape(level, pos, dir);
cir.setReturnValue(shape);
cir.cancel();
}

// Make sure the can lightPass occlusion test runs in the right level
@Inject(method = "canLightPass", at = @At("HEAD"), cancellable = true)
private static void patchedCanLightPass(BlockPos currentPos, BlockPos relativePos, Direction dir, CallbackInfoReturnable<Boolean> cir) {
ClientLevel level = ClientWorldLoader.getWorldAsync(RenderStates.originalPlayerDimension);
boolean canLightPass = !Shapes.faceShapeOccludes(getShape(level.getBlockState(currentPos), currentPos, dir), getShape(level.getBlockState(relativePos), relativePos, dir.getOpposite()));
cir.setReturnValue(canLightPass);
cir.cancel();
}

// Make sure Lucent gets the entities from the right level
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;"), remap = true)
private static List<Entity> getAllEntitiesFromTheRightDimension(ClientLevel instance, Class<Entity> entityClass, AABB aabb) {
aabb = RenderStates.originalPlayerBoundingBox.inflate(LucentData.maxVisibleDistance);
List<Entity> allEntities = ClientWorldLoader.getWorldAsync(RenderStates.originalPlayerDimension).getEntitiesOfClass(entityClass, aabb);
if (!allEntities.contains(Minecraft.getInstance().player)) {
allEntities.add(Minecraft.getInstance().player);
}
return allEntities;
}

//Give Lucent the correct player position
@ModifyArg(method = "getEntityLightLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ClipContext;<init>(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/level/ClipContext$Block;Lnet/minecraft/world/level/ClipContext$Fluid;Lnet/minecraft/world/entity/Entity;)V"), index = 0)
private static Vec3 truePlayerEyePosition(Vec3 pFrom) {
return new Vec3(RenderStates.originalPlayerPos.x, RenderStates.originalPlayerPos.y + Minecraft.getInstance().player.getEyeY(), RenderStates.originalPlayerPos.z); // TODO @Nick1st Make sure I can get the EyeHeight like this
}

// Give Lucent the correct level to clip
@Redirect(method = "getEntityLightLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;clip(Lnet/minecraft/world/level/ClipContext;)Lnet/minecraft/world/phys/BlockHitResult;"), remap = true)
private static BlockHitResult clipWithRightPosition(Level instance, ClipContext clipContext) {
return ClientWorldLoader.getWorldAsync(RenderStates.originalPlayerDimension).clip(clipContext);
}

// Calculate the distance correctly.
@Redirect(method = "getEntityLightLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;distanceTo(Lnet/minecraft/world/entity/Entity;)F"), remap = true)
private static float correctAlwaysVisibleDistanceCheck(LocalPlayer instance, Entity entity) {
Vec3 entityPos = new Vec3(entity.getX(), entity.getY(), entity.getZ());
if (entity instanceof LocalPlayer) {
entityPos = RenderStates.originalPlayerPos;
}
return (float) RenderStates.originalPlayerPos.distanceTo(entityPos);
}

// Calculate the correct Skylight value
@Redirect(method = "getEntityLightLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;getBrightness(Lnet/minecraft/world/level/LightLayer;Lnet/minecraft/core/BlockPos;)I"), remap = true)
private static int correctSkyLight(ClientLevel instance, LightLayer lightLayer, BlockPos blockPos) {
return ClientWorldLoader.getWorldAsync(RenderStates.originalPlayerDimension).getBrightness(lightLayer, blockPos);
}

// Set the player level renderer dirty instead of a random one
@Inject(method = "setDirty", at = @At(value = "INVOKE", target = "Lcom/legacy/lucent/core/LucentClient;setDirty(Lnet/minecraft/core/SectionPos;)V"), cancellable = true)
private static void setDirtyPatched(SectionPos section, CallbackInfo ci) {
ClientWorldLoader.getWorldRenderer(RenderStates.originalPlayerDimension).setSectionDirty(section.getX(), section.getY(), section.getZ());
ci.cancel();
}

// Fixes the level used to query the skylight
@ModifyVariable(method = "calcLight", at = @At(value = "HEAD"), argsOnly = true)
private static BlockAndTintGetter getCorrectSkylightLevel(BlockAndTintGetter level) {
return ClientWorldLoader.getWorldAsync(RenderStates.originalPlayerDimension);
}

// Fix a race condition if the Renderstate originalPlayerDimension is not yet set.
@Inject(method = "blockChanged", at = @At("HEAD"), cancellable = true)
private static void injectNullCheck(BlockPos pos, CallbackInfo ci) {
if (RenderStates.originalPlayerDimension == null) {
ci.cancel();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package qouteall.imm_ptl.core.compat.mixin;

import com.legacy.lucent.core.asm_hooks.ChunkRenderDispatcherHooks;
import net.minecraft.core.SectionPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import qouteall.imm_ptl.core.ClientWorldLoader;
import qouteall.imm_ptl.core.render.context_management.RenderStates;

@Mixin(value = ChunkRenderDispatcherHooks.class, remap = false)
public class MixinLucentChunkRenderDispatcherHooks {

// Set the correct levelRenderer dirty
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lcom/legacy/lucent/core/LucentClient;setDirty(Lnet/minecraft/core/SectionPos;)V"))
private static void setDirty(SectionPos section) {
ClientWorldLoader.getWorldRenderer(RenderStates.originalPlayerDimension).setSectionDirty(section.getX(), section.getY(), section.getZ());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package qouteall.imm_ptl.core.compat.mixin;

import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.chunk.RenderChunkRegion;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
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.CallbackInfoReturnable;
import qouteall.imm_ptl.core.render.context_management.RenderStates;

@OnlyIn(Dist.CLIENT)
@Mixin(value = LevelRenderer.class, priority = 900)
public class MixinLucentLevelRenderer {

// Inject before Lucent and return if the level doesn't fit.
@Inject(at = @At(value = "RETURN", ordinal = 1), method = "getLightColor(Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)I", cancellable = true)
private static void blockLightDimensionCheck(BlockAndTintGetter level, BlockState state, BlockPos pos, CallbackInfoReturnable<Integer> cir)
{
ClientLevel clientLevel = null;
if (level instanceof ClientLevel) {
clientLevel = (ClientLevel) level;
} else if (level instanceof RenderChunkRegion renderChunkRegion) {
clientLevel = (ClientLevel) renderChunkRegion.level;
}

if (clientLevel == null || clientLevel.dimension() != RenderStates.originalPlayerDimension) {
cir.cancel();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$Chu

public-f net.minecraft.client.renderer.chunk.ChunkRenderDispatcher f_112674_ #freeBuffers

public net.minecraft.client.renderer.chunk.RenderChunkRegion f_112908_ # level




Expand Down
8 changes: 7 additions & 1 deletion imm_ptl_core/src/main/resources/imm_ptl_compat.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@
"MixinSodiumShaderLoader",
"MixinSodiumWorldRenderer"
],
"client": [
"MixinLucent",
"MixinLucentChunkRenderDispatcherHooks",
"MixinLucentLevelRenderer"
],
"injectors": {
"defaultRequire": 1
}
},
"refmap": "mixins.imm_ptl.refmap.json"
}
2 changes: 2 additions & 0 deletions src/main/resources/META-INF/accesstransformer.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ public net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$Chu
public-f net.minecraft.client.renderer.chunk.ChunkRenderDispatcher f_112674_ #freeBuffers

public net.minecraft.server.level.ChunkMap$TrackedEntity

public net.minecraft.client.renderer.chunk.RenderChunkRegion f_112908_ # level

0 comments on commit 56783a2

Please sign in to comment.