feat: bare projection shell
This commit is contained in:
parent
899eac954e
commit
d88f110fe5
24
common/src/main/java/quaedam/mixin/MixinMinecraftServer.java
Normal file
24
common/src/main/java/quaedam/mixin/MixinMinecraftServer.java
Normal file
@ -0,0 +1,24 @@
|
||||
package quaedam.mixin;
|
||||
|
||||
import net.minecraft.core.GlobalPos;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import quaedam.mixininterface.ProjectionShellMutexAccessor;
|
||||
import quaedam.shell.ProjectionShellMutex;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Mixin(MinecraftServer.class)
|
||||
public class MixinMinecraftServer implements ProjectionShellMutexAccessor {
|
||||
|
||||
private LinkedHashMap<GlobalPos, ProjectionShellMutex.Lock> quaedam$projectionShellMutex;
|
||||
|
||||
@Override
|
||||
public LinkedHashMap<GlobalPos, ProjectionShellMutex.Lock> quaedam$getProjectionShellMutex() {
|
||||
if (quaedam$projectionShellMutex == null) {
|
||||
quaedam$projectionShellMutex = new LinkedHashMap<>();
|
||||
}
|
||||
return quaedam$projectionShellMutex;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package quaedam.mixininterface;
|
||||
|
||||
import net.minecraft.core.GlobalPos;
|
||||
import quaedam.shell.ProjectionShellMutex;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public interface ProjectionShellMutexAccessor {
|
||||
|
||||
LinkedHashMap<GlobalPos, ProjectionShellMutex.Lock> quaedam$getProjectionShellMutex();
|
||||
|
||||
}
|
@ -17,6 +17,7 @@ import quaedam.projection.misc.SkylightProjection
|
||||
import quaedam.projection.misc.SoundProjection
|
||||
import quaedam.projection.swarm.SwarmProjection
|
||||
import quaedam.projector.Projector
|
||||
import quaedam.shell.ProjectionShell
|
||||
|
||||
object Quaedam {
|
||||
|
||||
@ -50,6 +51,7 @@ object Quaedam {
|
||||
NoiseProjection
|
||||
ProjectionCommand
|
||||
SimpleProjectionUpdate
|
||||
ProjectionShell
|
||||
|
||||
creativeModeTabs.register()
|
||||
items.register()
|
||||
|
@ -8,10 +8,12 @@ import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import quaedam.shell.ProjectionEffectShell
|
||||
import quaedam.shell.ProjectionShellBlock
|
||||
import quaedam.utils.sendBlockUpdated
|
||||
|
||||
abstract class EntityProjectionBlock<P : ProjectionEffect>(properties: Properties = createProperties()) :
|
||||
ProjectionBlock<P>(properties), EntityBlock {
|
||||
ProjectionBlock<P>(properties), EntityBlock, ProjectionShellBlock {
|
||||
|
||||
companion object {
|
||||
fun createProperties(): Properties = ProjectionBlock.createProperties()
|
||||
@ -40,4 +42,11 @@ abstract class EntityProjectionBlock<P : ProjectionEffect>(properties: Propertie
|
||||
}
|
||||
}
|
||||
|
||||
override fun getProjectionEffectForShell(level: Level, pos: BlockPos) =
|
||||
(getBlockEntity(level, pos).cloneProjection() as ProjectionEffectShell.Provider).createShell()
|
||||
|
||||
override fun applyFromShell(level: Level, pos: BlockPos, shell: ProjectionEffectShell) = applyChange(level, pos) {
|
||||
fromNbt(shell.effect.toNbt())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,20 +1,15 @@
|
||||
package quaedam.projection.misc
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import quaedam.Quaedam
|
||||
import quaedam.projection.EntityProjectionBlock
|
||||
import quaedam.projection.ProjectionEffect
|
||||
import quaedam.projection.ProjectionEffectType
|
||||
import quaedam.projection.SimpleProjectionEntity
|
||||
import quaedam.shell.ProjectionEffectShell
|
||||
import quaedam.shell.buildProjectionEffectShell
|
||||
import kotlin.math.min
|
||||
|
||||
object SkylightProjection {
|
||||
@ -47,7 +42,7 @@ object SkylightProjectionBlock : EntityProjectionBlock<SkylightProjectionEffect>
|
||||
|
||||
}
|
||||
|
||||
data class SkylightProjectionEffect(var factor: Double = 2.0) : ProjectionEffect() {
|
||||
data class SkylightProjectionEffect(var factor: Double = 2.0) : ProjectionEffect(), ProjectionEffectShell.Provider {
|
||||
|
||||
companion object {
|
||||
const val TAG_FACTOR = "Factor"
|
||||
@ -67,4 +62,8 @@ data class SkylightProjectionEffect(var factor: Double = 2.0) : ProjectionEffect
|
||||
}
|
||||
}
|
||||
|
||||
override fun createShell() = buildProjectionEffectShell(this) {
|
||||
doubleSlider("quaedam.shell.skylight.factor", ::factor, 0.0..5.0, 0.1)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
package quaedam.shell
|
||||
|
||||
import net.minecraft.client.gui.components.AbstractSliderButton
|
||||
import net.minecraft.client.gui.components.CycleButton
|
||||
import net.minecraft.client.gui.components.StringWidget
|
||||
import net.minecraft.client.gui.layouts.LayoutElement
|
||||
import net.minecraft.network.chat.Component
|
||||
import quaedam.projection.ProjectionEffect
|
||||
import kotlin.math.floor
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
class ProjectionEffectShell(val effect: ProjectionEffect) {
|
||||
|
||||
interface Provider {
|
||||
|
||||
fun createShell(): ProjectionEffectShell
|
||||
|
||||
}
|
||||
|
||||
val rows = mutableListOf<Row>()
|
||||
val width = 150
|
||||
val height = 20
|
||||
|
||||
data class Row(val text: Component, val renderer: ShellRenderer)
|
||||
|
||||
fun row(key: String, renderer: ShellRenderer) {
|
||||
rows += Row(Component.translatable(key), renderer)
|
||||
}
|
||||
|
||||
fun text(key: String, value: Component) = row(key) { StringWidget(value, it.font) }
|
||||
|
||||
fun doubleSlider(key: String, property: KMutableProperty0<Double>, range: ClosedRange<Double>, step: Double) =
|
||||
row(key) {
|
||||
object : AbstractSliderButton(
|
||||
0, 0, width, height,
|
||||
Component.literal(property.get().toString()), property.get()
|
||||
) {
|
||||
override fun updateMessage() {
|
||||
message = Component.literal(value.toString())
|
||||
}
|
||||
|
||||
override fun applyValue() {
|
||||
value = floor(value / step) * step
|
||||
property.set(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun intCycle(key: String, property: KMutableProperty0<Int>, range: IntProgression) =
|
||||
row(key) {
|
||||
CycleButton.builder<Int> { Component.literal(it.toString()) }
|
||||
.displayOnlyValue()
|
||||
.withValues(range.toList())
|
||||
.create(0, 0, width, height, Component.translatable(key))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline fun buildProjectionEffectShell(effect: ProjectionEffect, builder: ProjectionEffectShell.() -> Unit) =
|
||||
ProjectionEffectShell(effect).apply(builder)
|
||||
|
||||
data class ShellRenderContext(val screen: ProjectionShellScreen) {
|
||||
val font get() = screen.getFont()
|
||||
}
|
||||
|
||||
typealias ShellRenderer = (ctx: ShellRenderContext) -> LayoutElement
|
26
common/src/main/kotlin/quaedam/shell/ProjectionShell.kt
Normal file
26
common/src/main/kotlin/quaedam/shell/ProjectionShell.kt
Normal file
@ -0,0 +1,26 @@
|
||||
package quaedam.shell
|
||||
|
||||
import dev.architectury.networking.NetworkChannel
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import quaedam.Quaedam
|
||||
import quaedam.shell.network.ClientboundPSHLockResultPacket
|
||||
import quaedam.shell.network.ClientboundPSHLockRevokePacket
|
||||
import quaedam.shell.network.ServerboundPSHLockAcquirePacket
|
||||
import quaedam.shell.network.ServerboundPSHLockReleasePacket
|
||||
|
||||
object ProjectionShell {
|
||||
|
||||
const val ID = "projection_shell"
|
||||
|
||||
val item = Quaedam.items.register(ID) { ProjectionShellItem }!!
|
||||
|
||||
val channel = NetworkChannel.create(ResourceLocation("quaedam", ID))
|
||||
|
||||
init {
|
||||
ServerboundPSHLockAcquirePacket
|
||||
ServerboundPSHLockReleasePacket
|
||||
ClientboundPSHLockRevokePacket
|
||||
ClientboundPSHLockResultPacket
|
||||
}
|
||||
|
||||
}
|
12
common/src/main/kotlin/quaedam/shell/ProjectionShellBlock.kt
Normal file
12
common/src/main/kotlin/quaedam/shell/ProjectionShellBlock.kt
Normal file
@ -0,0 +1,12 @@
|
||||
package quaedam.shell
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.Level
|
||||
|
||||
interface ProjectionShellBlock {
|
||||
|
||||
fun getProjectionEffectForShell(level: Level, pos: BlockPos): ProjectionEffectShell
|
||||
|
||||
fun applyFromShell(level: Level, pos: BlockPos, shell: ProjectionEffectShell)
|
||||
|
||||
}
|
24
common/src/main/kotlin/quaedam/shell/ProjectionShellItem.kt
Normal file
24
common/src/main/kotlin/quaedam/shell/ProjectionShellItem.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package quaedam.shell
|
||||
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.context.UseOnContext
|
||||
import quaedam.Quaedam
|
||||
import quaedam.shell.network.ServerboundPSHLockAcquirePacket
|
||||
|
||||
object ProjectionShellItem : Item(
|
||||
Properties()
|
||||
.stacksTo(1)
|
||||
.`arch$tab`(Quaedam.creativeModeTab)
|
||||
) {
|
||||
|
||||
override fun useOn(context: UseOnContext): InteractionResult {
|
||||
val block = context.level.getBlockState(context.clickedPos).block
|
||||
if (block is ProjectionShellBlock && context.level.isClientSide) {
|
||||
ProjectionShell.channel.sendToServer(ServerboundPSHLockAcquirePacket(context.clickedPos))
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
return InteractionResult.PASS
|
||||
}
|
||||
|
||||
}
|
49
common/src/main/kotlin/quaedam/shell/ProjectionShellMutex.kt
Normal file
49
common/src/main/kotlin/quaedam/shell/ProjectionShellMutex.kt
Normal file
@ -0,0 +1,49 @@
|
||||
package quaedam.shell
|
||||
|
||||
import dev.architectury.event.events.common.TickEvent
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.GlobalPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import quaedam.mixininterface.ProjectionShellMutexAccessor
|
||||
import quaedam.shell.network.ClientboundPSHLockRevokePacket
|
||||
|
||||
object ProjectionShellMutex {
|
||||
|
||||
init {
|
||||
TickEvent.SERVER_POST.register { server ->
|
||||
val mutex = (server as ProjectionShellMutexAccessor).`quaedam$getProjectionShellMutex`()
|
||||
val currentTime = System.currentTimeMillis()
|
||||
mutex.forEach { pos, lock ->
|
||||
if (currentTime - lock.time > 60 * 1000) {
|
||||
mutex.remove(pos)
|
||||
ProjectionShell.channel.sendToPlayer(lock.player, ClientboundPSHLockRevokePacket)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tryLock(level: ServerLevel, pos: BlockPos, player: ServerPlayer): Boolean {
|
||||
val mutex = (level.server as ProjectionShellMutexAccessor).`quaedam$getProjectionShellMutex`()
|
||||
val gPos = GlobalPos.of(level.dimension(), pos)
|
||||
if (mutex.values.any { it.player == player }) {
|
||||
return false
|
||||
}
|
||||
if (gPos !in mutex) {
|
||||
mutex[gPos] = Lock(player, System.currentTimeMillis())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun release(level: ServerLevel, pos: BlockPos, player: ServerPlayer) {
|
||||
val mutex = (level.server as ProjectionShellMutexAccessor).`quaedam$getProjectionShellMutex`()
|
||||
val gPos = GlobalPos.of(level.dimension(), pos)
|
||||
if (mutex[gPos]?.player == player) {
|
||||
mutex.remove(gPos)
|
||||
}
|
||||
}
|
||||
|
||||
data class Lock(val player: ServerPlayer, val time: Long)
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package quaedam.shell
|
||||
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.StringWidget
|
||||
import net.minecraft.client.gui.layouts.GridLayout
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.level.Level
|
||||
import quaedam.shell.network.ServerboundPSHLockReleasePacket
|
||||
|
||||
class ProjectionShellScreen(val level: Level, val pos: BlockPos, val shell: ProjectionEffectShell) :
|
||||
Screen(Component.translatable("quaedam.screen.projection_shell")) {
|
||||
|
||||
val layout = GridLayout()
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
layout.spacing(4)
|
||||
val rows = layout.createRowHelper(2)
|
||||
val renderContext = ShellRenderContext(this)
|
||||
shell.rows.forEach {
|
||||
rows.addChild(StringWidget(150, 20, it.text, font))
|
||||
rows.addChild(it.renderer(renderContext))
|
||||
}
|
||||
run { // Buttons
|
||||
rows.addChild(StringWidget(Component.empty(), font))
|
||||
rows.addChild(Button.builder(Component.translatable("quaedam.screen.projection_shell.save")) {
|
||||
val block = level.getBlockState(pos).block
|
||||
if (block is ProjectionShellBlock) {
|
||||
block.applyFromShell(level, pos, shell)
|
||||
}
|
||||
}.build())
|
||||
}
|
||||
layout.arrangeElements()
|
||||
layout.visitWidgets(::addRenderableWidget)
|
||||
}
|
||||
|
||||
fun getFont() = font
|
||||
|
||||
override fun renderBackground(guiGraphics: GuiGraphics) {
|
||||
super.renderBackground(guiGraphics)
|
||||
guiGraphics.blit(AbstractContainerScreen.INVENTORY_LOCATION, width / 2, height / 2, 0, 0, 176, 166)
|
||||
}
|
||||
|
||||
override fun removed() {
|
||||
super.removed()
|
||||
ProjectionShell.channel.sendToServer(ServerboundPSHLockReleasePacket(pos))
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package quaedam.shell.network
|
||||
|
||||
import dev.architectury.networking.NetworkManager.PacketContext
|
||||
import dev.architectury.utils.GameInstance
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import quaedam.Quaedam
|
||||
import quaedam.shell.ProjectionShell
|
||||
import quaedam.shell.ProjectionShellBlock
|
||||
import quaedam.shell.ProjectionShellScreen
|
||||
import java.util.function.Supplier
|
||||
|
||||
data class ClientboundPSHLockResultPacket(val pos: BlockPos, val result: Boolean) {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
ProjectionShell.channel.register(
|
||||
ClientboundPSHLockResultPacket::class.java,
|
||||
ClientboundPSHLockResultPacket::encode,
|
||||
::ClientboundPSHLockResultPacket,
|
||||
ClientboundPSHLockResultPacket::apply
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(buf: FriendlyByteBuf) : this(buf.readBlockPos(), buf.readBoolean())
|
||||
|
||||
fun encode(buf: FriendlyByteBuf) {
|
||||
buf.writeBlockPos(pos)
|
||||
buf.writeBoolean(result)
|
||||
}
|
||||
|
||||
fun apply(context: Supplier<PacketContext>) {
|
||||
val ctx = context.get()
|
||||
if (ctx.player.level().isClientSide) {
|
||||
val client = GameInstance.getClient()
|
||||
if (result) {
|
||||
val level = ctx.player.level()
|
||||
val block = level.getBlockState(pos).block
|
||||
if (block is ProjectionShellBlock) {
|
||||
ctx.queue {
|
||||
try {
|
||||
client.setScreen(
|
||||
ProjectionShellScreen(
|
||||
level,
|
||||
pos,
|
||||
block.getProjectionEffectForShell(level, pos)
|
||||
)
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
Quaedam.logger.error("Failed to open projection shell screen", e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Quaedam.logger.warn("ClientboundPSHLockResultPacket with non-shell-provider block received")
|
||||
}
|
||||
} else {
|
||||
ctx.queue {
|
||||
client.setScreen(null)
|
||||
client.gui.setOverlayMessage(
|
||||
Component.translatable("quaedam.screen.projection_shell.lock_failed"),
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package quaedam.shell.network
|
||||
|
||||
import dev.architectury.networking.NetworkManager.PacketContext
|
||||
import dev.architectury.utils.GameInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import quaedam.shell.ProjectionShell
|
||||
import quaedam.shell.ProjectionShellScreen
|
||||
import java.util.function.Supplier
|
||||
|
||||
object ClientboundPSHLockRevokePacket {
|
||||
|
||||
init {
|
||||
ProjectionShell.channel.register(
|
||||
ClientboundPSHLockRevokePacket::class.java,
|
||||
{ _, _ -> },
|
||||
{ ClientboundPSHLockRevokePacket },
|
||||
{ _, ctx -> apply(ctx) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun apply(context: Supplier<PacketContext>) {
|
||||
val ctx = context.get()
|
||||
if (ctx.player.level().isClientSide) {
|
||||
ctx.queue {
|
||||
val client = GameInstance.getClient()
|
||||
if (client.screen is ProjectionShellScreen) {
|
||||
client.setScreen(null)
|
||||
client.gui.setOverlayMessage(
|
||||
Component.translatable("quaedam.screen.projection_shell.lock_revoked"),
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package quaedam.shell.network
|
||||
|
||||
import dev.architectury.networking.NetworkManager.PacketContext
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import quaedam.shell.ProjectionShell
|
||||
import quaedam.shell.ProjectionShellMutex
|
||||
import java.util.function.Supplier
|
||||
|
||||
data class ServerboundPSHLockAcquirePacket(val pos: BlockPos) {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
ProjectionShell.channel.register(
|
||||
ServerboundPSHLockAcquirePacket::class.java,
|
||||
ServerboundPSHLockAcquirePacket::encode,
|
||||
::ServerboundPSHLockAcquirePacket,
|
||||
ServerboundPSHLockAcquirePacket::apply
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(buf: FriendlyByteBuf) : this(buf.readBlockPos())
|
||||
|
||||
fun encode(buf: FriendlyByteBuf) {
|
||||
buf.writeBlockPos(pos)
|
||||
}
|
||||
|
||||
fun apply(context: Supplier<PacketContext>) {
|
||||
val ctx = context.get()
|
||||
if (!ctx.player.level().isClientSide) {
|
||||
ctx.queue {
|
||||
val player = ctx.player as ServerPlayer
|
||||
val result = ProjectionShellMutex.tryLock(ctx.player.level() as ServerLevel, pos, player)
|
||||
ProjectionShell.channel.sendToPlayer(player, ClientboundPSHLockResultPacket(pos, result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package quaedam.shell.network
|
||||
|
||||
import dev.architectury.networking.NetworkManager.PacketContext
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import quaedam.shell.ProjectionShell
|
||||
import quaedam.shell.ProjectionShellMutex
|
||||
import java.util.function.Supplier
|
||||
|
||||
data class ServerboundPSHLockReleasePacket(val pos: BlockPos) {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
ProjectionShell.channel.register(
|
||||
ServerboundPSHLockReleasePacket::class.java,
|
||||
ServerboundPSHLockReleasePacket::encode,
|
||||
::ServerboundPSHLockReleasePacket,
|
||||
ServerboundPSHLockReleasePacket::apply
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(buf: FriendlyByteBuf) : this(buf.readBlockPos())
|
||||
|
||||
fun encode(buf: FriendlyByteBuf) {
|
||||
buf.writeBlockPos(pos)
|
||||
}
|
||||
|
||||
fun apply(context: Supplier<PacketContext>) {
|
||||
val ctx = context.get()
|
||||
if (!ctx.player.level().isClientSide) {
|
||||
ctx.queue {
|
||||
val player = ctx.player as ServerPlayer
|
||||
ProjectionShellMutex.release(ctx.player.level() as ServerLevel, pos, player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -5,5 +5,11 @@
|
||||
"block.quaedam.swarm_projection": "Swarm Projection",
|
||||
"block.quaedam.sound_projection": "Sound Projection",
|
||||
"block.quaedam.noise_projection": "Noise Projection",
|
||||
"entity.quaedam.projected_person": "Virtual Person"
|
||||
"entity.quaedam.projected_person": "Virtual Person",
|
||||
"item.quaedam.projection_shell": "Projection Shell",
|
||||
"quaedam.screen.projection_shell": "Projection Shell",
|
||||
"quaedam.screen.projection_shell.lock_revoked": "Timeout! Connection Lost",
|
||||
"quaedam.screen.projection_shell.lock_failed": "Permission denied!",
|
||||
"quaedam.screen.projection_shell.save": "Save",
|
||||
"quaedam.shell.skylight.factor": "Factor"
|
||||
}
|
@ -5,5 +5,9 @@
|
||||
"block.quaedam.swarm_projection": "人群投影",
|
||||
"block.quaedam.sound_projection": "声音投影",
|
||||
"block.quaedam.noise_projection": "噪音投影",
|
||||
"entity.quaedam.projected_person": "虚拟个体"
|
||||
"entity.quaedam.projected_person": "虚拟个体",
|
||||
"item.quaedam.projection_shell": "投影操作面板",
|
||||
"quaedam.screen.projection_shell": "投影操作",
|
||||
"quaedam.screen.projection_shell.lock_revoked": "超时!连接丢失",
|
||||
"quaedam.screen.projection_shell.lock_failed": "正被使用"
|
||||
}
|
||||
|
@ -8,7 +8,8 @@
|
||||
],
|
||||
"mixins": [
|
||||
"MixinBedBlock",
|
||||
"MixinBuiltInRegistries"
|
||||
"MixinBuiltInRegistries",
|
||||
"MixinMinecraftServer"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
Loading…
Reference in New Issue
Block a user