feat: SkylightProjection implementation

This commit is contained in:
xtex 2023-07-01 08:40:28 +08:00
parent 12ee6eae37
commit fa0403b3c8
Signed by: xtex
GPG Key ID: B918086ED8045B91
7 changed files with 71 additions and 10 deletions

View File

@ -0,0 +1,40 @@
package quaedam.mixin;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import org.joml.Math;
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 quaedam.projection.SkylightProjection;
import quaedam.projection.SkylightProjectionEffect;
import quaedam.projector.Projector;
import java.util.List;
@Mixin(ClientLevel.class)
public class MixinClientLevel {
@Inject(at = @At("RETURN"), method = "getSkyColor(Lnet/minecraft/world/phys/Vec3;F)Lnet/minecraft/world/phys/Vec3;", cancellable = true)
public void getSkyColor(Vec3 pos, float f, CallbackInfoReturnable<Vec3> cir) {
ClientLevel this0 = (ClientLevel) (Object) this;
List<SkylightProjectionEffect> projections = Projector.INSTANCE.findNearbyProjections(this0,
new BlockPos((int) pos.x, (int) pos.y, (int) pos.z), SkylightProjection.INSTANCE.getEffect().get());
if (!projections.isEmpty()) {
Vec3 color = cir.getReturnValue();
if (color.x == 0 || color.y == 0 || color.z == 0) {
// scale compensate
color = color.add(0.1, 0.1, 0.1);
}
for (SkylightProjectionEffect effect : projections) {
double factor = effect.getFactor();
color = color.multiply(factor, factor, factor);
}
color = new Vec3(Math.min(color.x, 1.0), Math.min(color.y, 1.0), Math.min(color.z, 1.0));
cir.setReturnValue(color);
}
}
}

View File

@ -23,7 +23,7 @@ abstract class ProjectionBlock<P : ProjectionEffect>(properties: Properties = cr
fun findNearbyProjectors(level: Level, pos: BlockPos) = level.getChunksNearby(pos, 1)
.flatMap {
it.blockEntities.filter { (k, v) -> v is ProjectorBlockEntity }
it.blockEntities.filter { (_, v) -> v is ProjectorBlockEntity }
.keys
.filterNotNull()
}

View File

@ -22,7 +22,7 @@ object SkylightProjection {
}!!
val effect = Quaedam.projectionEffects.register(ID) {
ProjectionEffectType { SkylightProjectionEffect }
ProjectionEffectType { SkylightProjectionEffect() }
}!!
}
@ -33,19 +33,21 @@ object SkylightProjectionBlock : ProjectionBlock<SkylightProjectionEffect>(creat
level: ServerLevel,
state: BlockState,
pos: BlockPos
) = SkylightProjectionEffect
) = SkylightProjectionEffect()
}
object SkylightProjectionEffect : ProjectionEffect() {
data class SkylightProjectionEffect(var factor: Double = 2.0) : ProjectionEffect() {
override val type
get() = SkylightProjection.effect.get()!!
override fun toNbt(tag: CompoundTag) {
tag.putDouble("Factor", factor)
}
override fun fromNbt(tag: CompoundTag) {
factor = tag.getDouble("Factor")
}
}

View File

@ -1,13 +1,19 @@
package quaedam.projector
import net.minecraft.core.BlockPos
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.Item
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntityType
import quaedam.Quaedam
import quaedam.projection.ProjectionEffect
import quaedam.projection.ProjectionEffectType
import quaedam.utils.getChunksNearby
object Projector {
const val ID = "projector"
const val EFFECT_RADIUS = 4
val block = Quaedam.blocks.register(ID) { ProjectorBlock }!!
@ -23,4 +29,18 @@ object Projector {
BlockEntityType.Builder.of(::ProjectorBlockEntity, block.get()).build(null)
}!!
fun findNearbyProjectors(level: Level, pos: BlockPos) = level.getChunksNearby(pos, EFFECT_RADIUS)
.flatMap {
it.blockEntities.filter { (_, v) -> v is ProjectorBlockEntity }
.keys
.filterNotNull()
}
.toSet()
@Suppress("UNCHECKED_CAST")
fun <T : ProjectionEffect> findNearbyProjections(level: Level, pos: BlockPos, type: ProjectionEffectType<T>) =
findNearbyProjectors(level, pos)
.map { level.getBlockEntity(it) as ProjectorBlockEntity }
.mapNotNull { it.effects[type] as T? }
}

View File

@ -20,14 +20,10 @@ import quaedam.utils.sendBlockUpdated
class ProjectorBlockEntity(pos: BlockPos, state: BlockState) :
BlockEntity(Projector.blockEntity.get(), pos, state) {
companion object {
const val EFFECT_RADIUS = 4
}
val effectAreaChunk by lazy {
val chunk = level!!.getChunk(pos).pos
ChunkPos(chunk.x - EFFECT_RADIUS, chunk.z - EFFECT_RADIUS) to
ChunkPos(chunk.x + EFFECT_RADIUS, chunk.z + EFFECT_RADIUS)
ChunkPos(chunk.x - Projector.EFFECT_RADIUS, chunk.z - Projector.EFFECT_RADIUS) to
ChunkPos(chunk.x + Projector.EFFECT_RADIUS, chunk.z + Projector.EFFECT_RADIUS)
}
val effectArea: BoundingBox by lazy {

View File

@ -2,7 +2,9 @@
"required": true,
"package": "quaedam.mixin",
"compatibilityLevel": "JAVA_17",
"minVersion": "0.8",
"client": [
"MixinClientLevel"
],
"mixins": [
"MixinBuiltInRegistries"

View File

@ -2,6 +2,7 @@
"required": true,
"package": "quaedam.mixin.forge",
"compatibilityLevel": "JAVA_17",
"minVersion": "0.8",
"client": [
],
"mixins": [