(1.21.8) migrate to moj mapping
This commit is contained in:
72 files changed
+862
-977
No files matched your search
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id("io.freefair.lombok") version "8.6"
|
id("io.freefair.lombok") version "9.5.0"
|
||||||
id("com.gradleup.shadow") version "9.3.1"
|
id("com.gradleup.shadow") version "9.3.1"
|
||||||
id 'fabric-loom' version '1.10.1'
|
id 'fabric-loom' version '1.17-SNAPSHOT'
|
||||||
}
|
}
|
||||||
|
|
||||||
version = project.mod_version
|
version = project.mod_version
|
||||||
@@ -23,7 +23,7 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
// To change the versions see the gradle.properties file1
|
// To change the versions see the gradle.properties file1
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
mappings loom.officialMojangMappings()
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
modImplementation 'me.lucko:fabric-permissions-api:0.3.1'
|
modImplementation 'me.lucko:fabric-permissions-api:0.3.1'
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||||
@@ -2,14 +2,14 @@ package io.ib67.sfcraft;
|
|||||||
|
|
||||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||||
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
|
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
public class SFRegistries {
|
public class SFRegistries {
|
||||||
public static final Registry<Item> ITEMS = FabricRegistryBuilder
|
public static final Registry<Item> ITEMS = FabricRegistryBuilder
|
||||||
.<Item>createSimple(RegistryKey.ofRegistry(Identifier.of(SFCraft.MOD_ID, "item")))
|
.<Item>createSimple(ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "item")))
|
||||||
.attribute(RegistryAttribute.MODDED)
|
.attribute(RegistryAttribute.MODDED)
|
||||||
.buildAndRegister();
|
.buildAndRegister();
|
||||||
}
|
}
|
||||||
@@ -3,16 +3,15 @@ package io.ib67.sfcraft.callback;
|
|||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
import net.fabricmc.fabric.api.event.Event;
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
import net.fabricmc.fabric.api.event.EventFactory;
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.network.Connection;
|
||||||
import net.minecraft.network.ClientConnection;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.protocol.status.ServerStatus;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.ServerMetadata;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Unit;
|
import net.minecraft.util.Unit;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static io.ib67.sfcraft.callback.Utility.*;
|
import static io.ib67.sfcraft.callback.Utility.*;
|
||||||
@@ -39,35 +38,35 @@ public interface SFCallbacks {
|
|||||||
l -> (p, s) -> forEach(l, i -> i.onAFKStatus(p, s)));
|
l -> (p, s) -> forEach(l, i -> i.onAFKStatus(p, s)));
|
||||||
|
|
||||||
interface PlayerAFKCallback {
|
interface PlayerAFKCallback {
|
||||||
void onAFKStatus(ServerPlayerEntity player, boolean inAFK);
|
void onAFKStatus(ServerPlayer player, boolean inAFK);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerFlyingCallback {
|
interface PlayerFlyingCallback {
|
||||||
void onFlyingTick(PlayerEntity player, long flyingTick, boolean flying);
|
void onFlyingTick(Player player, long flyingTick, boolean flying);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerSneakingCallback {
|
interface PlayerSneakingCallback {
|
||||||
void onSneaking(PlayerEntity player, boolean sneak);
|
void onSneaking(Player player, boolean sneak);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerIdlingCallback {
|
interface PlayerIdlingCallback {
|
||||||
void onSwitchIdle(ServerPlayerEntity player, boolean afk);
|
void onSwitchIdle(ServerPlayer player, boolean afk);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ServerMotdCallback {
|
interface ServerMotdCallback {
|
||||||
ServerMetadata onMotd(MinecraftServer server, ClientConnection connection);
|
ServerStatus onMotd(MinecraftServer server, Connection connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerDeathCallback {
|
interface PlayerDeathCallback {
|
||||||
void onPlayerDeath(PlayerEntity player, DamageSource damageSource);
|
void onPlayerDeath(Player player, DamageSource damageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerPreLoginCallback {
|
interface PlayerPreLoginCallback {
|
||||||
void onPlayerPreLogin(String currentPlayer, ClientConnection connection, Consumer<Text> disconnect, boolean offline);
|
void onPlayerPreLogin(String currentPlayer, Connection connection, Consumer<Component> disconnect, boolean offline);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlayerSleepCallback {
|
interface PlayerSleepCallback {
|
||||||
|
|
||||||
Either<PlayerEntity.SleepFailureReason, Unit> onPlayerSleep(PlayerEntity player, BlockPos pos);
|
Either<Player.BedSleepingProblem, Unit> onPlayerSleep(Player player, BlockPos pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
package io.ib67.sfcraft.entity;
|
package io.ib67.sfcraft.entity;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.entity.passive.AllayEntity;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.world.entity.EntityType;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.entity.animal.allay.Allay;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class SFGuiderEntity extends AllayEntity {
|
public class SFGuiderEntity extends Allay {
|
||||||
public SFGuiderEntity(EntityType<SFGuiderEntity> entityEntityType, World world) {
|
public SFGuiderEntity(EntityType<SFGuiderEntity> entityEntityType, Level world) {
|
||||||
super(entityEntityType, world);
|
super(entityEntityType, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Text getName() {
|
public Component getName() {
|
||||||
return Text.of("guider");
|
return Component.nullToEmpty("guider");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
var nearbyPlayer = PlayerLookup.around((ServerWorld) getWorld(), getPos(), 20D);
|
var nearbyPlayer = PlayerLookup.around((ServerLevel) level(), position(), 20D);
|
||||||
for (ServerPlayerEntity serverPlayerEntity : nearbyPlayer) {
|
for (ServerPlayer serverPlayerEntity : nearbyPlayer) {
|
||||||
this.navigation.startMovingTo(serverPlayerEntity, 2f);
|
this.navigation.moveTo(serverPlayerEntity, 2f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,18 @@ package io.ib67.sfcraft.init;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PreInitHandler {
|
public class PreInitHandler {
|
||||||
private final AtomicBoolean initialized;
|
private final AtomicBoolean initialized;
|
||||||
|
|
||||||
void defend(ServerPlayNetworkHandler handler, PacketSender sender, MinecraftServer server) {
|
void defend(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server) {
|
||||||
if (!initialized.get()) {
|
if (!initialized.get()) {
|
||||||
handler.disconnect(Text.of("Server is initializing, please wait."));
|
handler.disconnect(Component.nullToEmpty("Server is initializing, please wait."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,6 @@ import io.ib67.sfcraft.SFCraft;
|
|||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import io.ib67.sfcraft.module.RoomModule;
|
import io.ib67.sfcraft.module.RoomModule;
|
||||||
import io.ib67.sfcraft.registry.RoomRegistry;
|
import io.ib67.sfcraft.registry.RoomRegistry;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.world.TeleportTarget;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
@@ -16,31 +13,34 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.portal.TeleportTransition;
|
||||||
|
|
||||||
@Mixin(Entity.class)
|
@Mixin(Entity.class)
|
||||||
public abstract class EntityMixin {
|
public abstract class EntityMixin {
|
||||||
@Inject(method = "setSneaking", at = @At("HEAD"))
|
@Inject(method = "setShiftKeyDown", at = @At("HEAD"))
|
||||||
public void onSneaking(boolean sneaking, CallbackInfo ci) {
|
public void onSneaking(boolean sneaking, CallbackInfo ci) {
|
||||||
if ($this() instanceof PlayerEntity pe) {
|
if ($this() instanceof Player pe) {
|
||||||
SFCallbacks.PLAYER_SNEAKING.invoker().onSneaking(pe, sneaking);
|
SFCallbacks.PLAYER_SNEAKING.invoker().onSneaking(pe, sneaking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public abstract UUID getUuid();
|
public abstract UUID getUUID();
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "teleportTo", cancellable = true)
|
@Inject(at = @At("HEAD"), method = "teleport", cancellable = true)
|
||||||
private void sf$redirectTeleport(TeleportTarget teleportTarget, CallbackInfoReturnable<Entity> cir) {
|
private void sf$redirectTeleport(TeleportTransition teleportTarget, CallbackInfoReturnable<Entity> cir) {
|
||||||
if (RoomModule.isVirtual(this.getUuid())) {
|
if (RoomModule.isVirtual(this.getUUID())) {
|
||||||
cir.setReturnValue((Entity) (Object) this);
|
cir.setReturnValue((Entity) (Object) this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "canUsePortals", cancellable = true)
|
@Inject(at = @At("HEAD"), method = "canUsePortal", cancellable = true)
|
||||||
private void sf$disablePortal(boolean allowVehicles, CallbackInfoReturnable<Boolean> cir) {
|
private void sf$disablePortal(boolean allowVehicles, CallbackInfoReturnable<Boolean> cir) {
|
||||||
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
||||||
var $this = (Entity) (Object) this;
|
var $this = (Entity) (Object) this;
|
||||||
if (registry.isRoomWorld($this.getWorld().getRegistryKey())) {
|
if (registry.isRoomWorld($this.level().dimension())) {
|
||||||
cir.setReturnValue(false);
|
cir.setReturnValue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package io.ib67.sfcraft.mixin.common;
|
package io.ib67.sfcraft.mixin.common;
|
||||||
|
|
||||||
import net.minecraft.entity.mob.MobEntity;
|
import net.minecraft.world.entity.Mob;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
@Mixin(MobEntity.class)
|
@Mixin(Mob.class)
|
||||||
public abstract class MobEntityMixin {
|
public abstract class MobEntityMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
public boolean cannotDespawn() {
|
public boolean requiresCustomPersistence() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,19 +2,19 @@ package io.ib67.sfcraft.mixin.common;
|
|||||||
|
|
||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import io.ib67.sfcraft.mixin.common.bridge.EntityBridge;
|
import io.ib67.sfcraft.mixin.common.bridge.EntityBridge;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(PlayerEntity.class)
|
@Mixin(Player.class)
|
||||||
public abstract class PlayerEntityMixin {
|
public abstract class PlayerEntityMixin {
|
||||||
@Unique
|
@Unique
|
||||||
private long flyTime;
|
private long flyTime;
|
||||||
|
|
||||||
@Inject(method = "tickMovement", at = @At("TAIL"))
|
@Inject(method = "aiStep", at = @At("TAIL"))
|
||||||
public void tickMovement(CallbackInfo ci) {
|
public void tickMovement(CallbackInfo ci) {
|
||||||
var eb = ((EntityBridge) $this());
|
var eb = ((EntityBridge) $this());
|
||||||
if (eb.sfcraft$getFlag(EntityBridge.sfcraft$getFlyingFlagIndex())) {
|
if (eb.sfcraft$getFlag(EntityBridge.sfcraft$getFlyingFlagIndex())) {
|
||||||
@@ -28,8 +28,8 @@ public abstract class PlayerEntityMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
public PlayerEntity $this() {
|
public Player $this() {
|
||||||
return (PlayerEntity) (Object) this;
|
return (Player) (Object) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.bridge;
|
package io.ib67.sfcraft.mixin.common.bridge;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
@Mixin(Entity.class)
|
@Mixin(Entity.class)
|
||||||
public interface EntityBridge {
|
public interface EntityBridge {
|
||||||
@Accessor("GLIDING_FLAG_INDEX")
|
@Accessor("FLAG_FALL_FLYING")
|
||||||
static int sfcraft$getFlyingFlagIndex() {
|
static int sfcraft$getFlyingFlagIndex() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Invoker("getFlag")
|
@Invoker("getSharedFlag")
|
||||||
boolean sfcraft$getFlag(int index);
|
boolean sfcraft$getFlag(int index);
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.bridge;
|
package io.ib67.sfcraft.mixin.common.bridge;
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.registry.entry.RegistryEntry;
|
import net.minecraft.world.item.Item;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
@Mixin(Item.class)
|
@Mixin(Item.class)
|
||||||
public interface ItemBridge {
|
public interface ItemBridge {
|
||||||
@Accessor
|
@Accessor
|
||||||
void setRegistryEntry(RegistryEntry.Reference<Item> value);
|
void setBuiltInRegistryHolder(Holder.Reference<Item> value);
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.bridge;
|
package io.ib67.sfcraft.mixin.common.bridge;
|
||||||
|
|
||||||
import net.minecraft.server.world.ChunkLevelManager;
|
import net.minecraft.server.level.DistanceManager;
|
||||||
import net.minecraft.server.world.ServerChunkManager;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
@Mixin(ServerChunkManager.class)
|
@Mixin(ServerChunkCache.class)
|
||||||
public interface ServerChunkManagerBridge {
|
public interface ServerChunkManagerBridge {
|
||||||
@Accessor("levelManager")
|
@Accessor("distanceManager")
|
||||||
ChunkLevelManager getLevelManager();
|
DistanceManager getLevelManager();
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.bridge;
|
package io.ib67.sfcraft.mixin.common.bridge;
|
||||||
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
@Mixin(ServerPlayerEntity.class)
|
@Mixin(ServerPlayer.class)
|
||||||
public interface ServerPlayerBridge {
|
public interface ServerPlayerBridge {
|
||||||
@Accessor
|
@Accessor
|
||||||
void setLastActionTime(long time);
|
void setLastActionTime(long time);
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.bridge;
|
package io.ib67.sfcraft.mixin.common.bridge;
|
||||||
|
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.world.SleepManager;
|
import net.minecraft.server.players.SleepStatus;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
@Mixin(ServerWorld.class)
|
@Mixin(ServerLevel.class)
|
||||||
public interface ServerWorldBridge {
|
public interface ServerWorldBridge {
|
||||||
@Accessor
|
@Accessor
|
||||||
SleepManager getSleepManager();
|
SleepStatus getDEEPSLATE_BRICKS();
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.fixes;
|
package io.ib67.sfcraft.mixin.common.fixes;
|
||||||
|
|
||||||
import io.ib67.sfcraft.mixin.common.MobEntityMixin;
|
import io.ib67.sfcraft.mixin.common.MobEntityMixin;
|
||||||
import net.minecraft.entity.mob.EndermanEntity;
|
import net.minecraft.world.entity.monster.EnderMan;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
@Mixin(EndermanEntity.class)
|
@Mixin(EnderMan.class)
|
||||||
public abstract class EndermanEntityMixin extends MobEntityMixin {
|
public abstract class EndermanEntityMixin extends MobEntityMixin {
|
||||||
@Inject(at = @At("HEAD"), method = "cannotDespawn", cancellable = true)
|
@Inject(at = @At("HEAD"), method = "requiresCustomPersistence", cancellable = true)
|
||||||
private void sf$cannotDespawn(CallbackInfoReturnable<Boolean> cir) {
|
private void sf$cannotDespawn(CallbackInfoReturnable<Boolean> cir) {
|
||||||
cir.setReturnValue(super.cannotDespawn());
|
cir.setReturnValue(super.requiresCustomPersistence());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.fixes;
|
package io.ib67.sfcraft.mixin.common.fixes;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.entity.passive.BeeEntity;
|
import net.minecraft.world.entity.animal.Bee;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -10,9 +10,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
|
|
||||||
@Mixin(LivingEntity.class)
|
@Mixin(LivingEntity.class)
|
||||||
public abstract class LivingEntityMixin {
|
public abstract class LivingEntityMixin {
|
||||||
@Inject(method = "tickCramming", at=@At("HEAD"), cancellable = true)
|
@Inject(method = "pushEntities", at=@At("HEAD"), cancellable = true)
|
||||||
private void sf$disableBeeCramming(CallbackInfo ci) {
|
private void sf$disableBeeCramming(CallbackInfo ci) {
|
||||||
if($this() instanceof BeeEntity) {
|
if($this() instanceof Bee) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
package io.ib67.sfcraft.mixin.common.fixes;
|
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.LazyEntityReference;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.entity.projectile.ProjectileEntity;
|
|
||||||
import net.minecraft.server.world.ServerWorld;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Mixin(ProjectileEntity.class)
|
|
||||||
public class ProjectileEntityMixin {
|
|
||||||
@Shadow
|
|
||||||
@Nullable
|
|
||||||
protected LazyEntityReference<Entity> owner;
|
|
||||||
|
|
||||||
@Unique
|
|
||||||
private boolean isPlayer;
|
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "setOwner(Lnet/minecraft/entity/Entity;)V")
|
|
||||||
private void setOwner(@Nullable Entity owner, CallbackInfo ci) {
|
|
||||||
isPlayer = owner instanceof PlayerEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(at=@At("HEAD"), method = "setOwner(Lnet/minecraft/entity/LazyEntityReference;)V")
|
|
||||||
private void setOwner(@Nullable LazyEntityReference<Entity> owner, CallbackInfo ci) {
|
|
||||||
isPlayer = LazyEntityReference.resolve(owner, $().getWorld(), Entity.class) instanceof PlayerEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @reason Implement the logic correctly.
|
|
||||||
* @author icybear
|
|
||||||
*/
|
|
||||||
@Overwrite
|
|
||||||
public @Nullable Entity getOwner() {
|
|
||||||
if (this.owner != null) {
|
|
||||||
var ownerUuid = this.owner.getUuid();
|
|
||||||
var server = $().getWorld().getServer();
|
|
||||||
if (server == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (isPlayer) {
|
|
||||||
return server.getPlayerManager().getPlayer(ownerUuid);
|
|
||||||
} else {
|
|
||||||
return LazyEntityReference.resolve(this.owner, $().getWorld(), Entity.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unique
|
|
||||||
private ProjectileEntity $() {
|
|
||||||
return (ProjectileEntity) (Object) this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
package io.ib67.sfcraft.mixin.server;
|
package io.ib67.sfcraft.mixin.server;
|
||||||
|
|
||||||
import io.ib67.sfcraft.mixin.common.bridge.ServerWorldBridge;
|
import io.ib67.sfcraft.mixin.common.bridge.ServerWorldBridge;
|
||||||
import net.minecraft.block.AbstractFurnaceBlock;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.block.BlockWithEntity;
|
import net.minecraft.world.level.GameRules;
|
||||||
import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.AbstractFurnaceBlock;
|
||||||
import net.minecraft.block.entity.BlockEntityTicker;
|
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||||
import net.minecraft.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||||
import net.minecraft.world.GameRules;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
import org.spongepowered.asm.mixin.Overwrite;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
|
||||||
@Mixin(AbstractFurnaceBlock.class)
|
@Mixin(AbstractFurnaceBlock.class)
|
||||||
public abstract class AbstractFurnaceBlockMixin extends BlockWithEntity {
|
public abstract class AbstractFurnaceBlockMixin extends BaseEntityBlock {
|
||||||
protected AbstractFurnaceBlockMixin(Settings settings) {
|
protected AbstractFurnaceBlockMixin(Properties settings) {
|
||||||
super(settings);
|
super(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,20 +29,20 @@ public abstract class AbstractFurnaceBlockMixin extends BlockWithEntity {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public static <T extends BlockEntity> BlockEntityTicker<T> validateTicker(
|
public static <T extends BlockEntity> BlockEntityTicker<T> createFurnaceTicker(
|
||||||
World world, BlockEntityType<T> givenType, BlockEntityType<? extends AbstractFurnaceBlockEntity> expectedType
|
Level world, BlockEntityType<T> givenType, BlockEntityType<? extends AbstractFurnaceBlockEntity> expectedType
|
||||||
) {
|
) {
|
||||||
return world instanceof ServerWorld sw ? BlockWithEntity.validateTicker(givenType, expectedType, AbstractFurnaceBlockMixin::tickMultiple) : null;
|
return world instanceof ServerLevel sw ? BaseEntityBlock.createTickerHelper(givenType, expectedType, AbstractFurnaceBlockMixin::tickMultiple) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private static <E extends AbstractFurnaceBlockEntity> void tickMultiple(World _world, BlockPos pos, BlockState state, E blockEntity) {
|
private static <E extends AbstractFurnaceBlockEntity> void tickMultiple(Level _world, BlockPos pos, BlockState state, E blockEntity) {
|
||||||
var world = (ServerWorld) _world;
|
var world = (ServerLevel) _world;
|
||||||
AbstractFurnaceBlockEntity.tick(world, pos, state, blockEntity);
|
AbstractFurnaceBlockEntity.serverTick(world, pos, state, blockEntity);
|
||||||
int i = world.getGameRules().getInt(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
|
int i = world.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||||
if (((ServerWorldBridge) world).getSleepManager().canSkipNight(i)) {
|
if (((ServerWorldBridge) world).getDEEPSLATE_BRICKS().areEnoughSleeping(i)) {
|
||||||
AbstractFurnaceBlockEntity.tick(world, pos, state, blockEntity); //todo: config support?
|
AbstractFurnaceBlockEntity.serverTick(world, pos, state, blockEntity); //todo: config support?
|
||||||
AbstractFurnaceBlockEntity.tick(world, pos, state, blockEntity);
|
AbstractFurnaceBlockEntity.serverTick(world, pos, state, blockEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,6 @@ package io.ib67.sfcraft.mixin.server;
|
|||||||
|
|
||||||
import io.ib67.sfcraft.util.Helper;
|
import io.ib67.sfcraft.util.Helper;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import net.minecraft.network.QueryableServer;
|
|
||||||
import net.minecraft.network.handler.LegacyQueryHandler;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -14,6 +12,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import net.minecraft.server.ServerInfo;
|
||||||
|
import net.minecraft.server.network.LegacyQueryHandler;
|
||||||
|
|
||||||
@Mixin(LegacyQueryHandler.class)
|
@Mixin(LegacyQueryHandler.class)
|
||||||
public class LegacyQueryHandlerMixin {
|
public class LegacyQueryHandlerMixin {
|
||||||
@@ -25,17 +25,17 @@ public class LegacyQueryHandlerMixin {
|
|||||||
address = ctx.channel().remoteAddress();
|
address = ctx.channel().remoteAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "channelRead", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/handler/LegacyQueryHandler;getResponse(Lnet/minecraft/network/QueryableServer;)Ljava/lang/String;"))
|
@Redirect(method = "channelRead", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/LegacyQueryHandler;createVersion1Response(Lnet/minecraft/server/ServerInfo;)Ljava/lang/String;"))
|
||||||
private String getResponse(QueryableServer server) {
|
private String getResponse(ServerInfo server) {
|
||||||
var version = server.getVersion();
|
var version = server.getServerVersion();
|
||||||
return String.format(
|
return String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"§1\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d",
|
"§1\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d",
|
||||||
127,
|
127,
|
||||||
version,
|
version,
|
||||||
server.getServerMotd(),
|
server.getMotd(),
|
||||||
server.getCurrentPlayerCount(),
|
server.getPlayerCount(),
|
||||||
server.getMaxPlayerCount()
|
server.getMaxPlayers()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||||||
@Mixin(MinecraftServer.class)
|
@Mixin(MinecraftServer.class)
|
||||||
public abstract class MinecraftServerMixin {
|
public abstract class MinecraftServerMixin {
|
||||||
|
|
||||||
@ModifyConstant(method = "tickWorlds", constant = @Constant(intValue = 20))
|
@ModifyConstant(method = "tickChildren", constant = @Constant(intValue = 20))
|
||||||
private int speedUpAtNight(int constant) {
|
private int speedUpAtNight(int constant) {
|
||||||
if (MixinHelper.spedUp) {
|
if (MixinHelper.spedUp) {
|
||||||
return 2;
|
return 2;
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package io.ib67.sfcraft.mixin.server;
|
|||||||
|
|
||||||
import io.ib67.sfcraft.SFCraft;
|
import io.ib67.sfcraft.SFCraft;
|
||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import net.minecraft.network.ClientConnection;
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.protocol.status.ServerStatus;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.ServerMetadata;
|
import net.minecraft.server.network.ServerHandshakePacketListenerImpl;
|
||||||
import net.minecraft.server.network.ServerHandshakeNetworkHandler;
|
|
||||||
import org.spongepowered.asm.mixin.Debug;
|
import org.spongepowered.asm.mixin.Debug;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -13,17 +13,17 @@ import org.spongepowered.asm.mixin.Shadow;
|
|||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
@Mixin(ServerHandshakeNetworkHandler.class)
|
@Mixin(ServerHandshakePacketListenerImpl.class)
|
||||||
public abstract class ServerHandshakeNetworkHandlerMixin {
|
public abstract class ServerHandshakeNetworkHandlerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private ClientConnection connection;
|
private Connection connection;
|
||||||
|
|
||||||
@Redirect(method = "onHandshake", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getServerMetadata()Lnet/minecraft/server/ServerMetadata;"))
|
@Redirect(method = "handleIntention", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getStatus()Lnet/minecraft/network/protocol/status/ServerStatus;"))
|
||||||
public ServerMetadata getMetadata(MinecraftServer instance) {
|
public ServerStatus getMetadata(MinecraftServer instance) {
|
||||||
var result = SFCallbacks.MOTD.invoker().onMotd(instance,connection);
|
var result = SFCallbacks.MOTD.invoker().onMotd(instance,connection);
|
||||||
if(result == null) {
|
if(result == null) {
|
||||||
return instance.getServerMetadata();
|
return instance.getStatus();
|
||||||
}else{
|
}else{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,12 @@ package io.ib67.sfcraft.mixin.server;
|
|||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import io.netty.channel.local.LocalChannel;
|
import io.netty.channel.local.LocalChannel;
|
||||||
import io.netty.channel.local.LocalServerChannel;
|
import io.netty.channel.local.LocalServerChannel;
|
||||||
import net.minecraft.network.ClientConnection;
|
import net.minecraft.core.UUIDUtil;
|
||||||
import net.minecraft.network.packet.c2s.login.LoginHelloC2SPacket;
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.protocol.login.ServerboundHelloPacket;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerLoginNetworkHandler;
|
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.ActionResult;
|
|
||||||
import net.minecraft.util.Uuids;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -21,10 +20,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
@Mixin(ServerLoginNetworkHandler.class)
|
@Mixin(ServerLoginPacketListenerImpl.class)
|
||||||
public abstract class ServerLoginNetworkHandlerMixin {
|
public abstract class ServerLoginNetworkHandlerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
public abstract void disconnect(Text reason);
|
public abstract void disconnect(Component reason);
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
@@ -32,23 +31,23 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
|||||||
@Unique
|
@Unique
|
||||||
private String currentPlayer;
|
private String currentPlayer;
|
||||||
|
|
||||||
@Inject(method = "onHello", at = @At("HEAD"))
|
@Inject(method = "handleHello", at = @At("HEAD"))
|
||||||
public void onHello(LoginHelloC2SPacket packet, CallbackInfo ci) {
|
public void onHello(ServerboundHelloPacket packet, CallbackInfo ci) {
|
||||||
currentPlayer = packet.name();
|
currentPlayer = packet.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "onHello", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;isLocal()Z"))
|
@Redirect(method = "handleHello", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;isMemoryConnection()Z"))
|
||||||
public boolean isLocal(ClientConnection connection) {
|
public boolean isLocal(Connection connection) {
|
||||||
if (!(connection.getAddress() instanceof InetSocketAddress)) {
|
if (!(connection.getRemoteAddress() instanceof InetSocketAddress)) {
|
||||||
return connection.isLocal(); // 碰上真 isLocal 了
|
return connection.isMemoryConnection(); // 碰上真 isLocal 了
|
||||||
}
|
}
|
||||||
var offlineProfile = Uuids.getOfflinePlayerProfile(currentPlayer);
|
var offlineProfile = UUIDUtil.createOfflineProfile(currentPlayer);
|
||||||
boolean _r;
|
boolean _r;
|
||||||
if (server.getUserCache() != null) {
|
if (server.getProfileCache() != null) {
|
||||||
_r = server.getUserCache().getByUuid(offlineProfile.getId()).isPresent();
|
_r = server.getProfileCache().get(offlineProfile.getId()).isPresent();
|
||||||
}else{
|
}else{
|
||||||
var wl = server.getPlayerManager().getWhitelist();
|
var wl = server.getPlayerList().getWhiteList();
|
||||||
_r = wl.isAllowed(offlineProfile);
|
_r = wl.isWhiteListed(offlineProfile);
|
||||||
}
|
}
|
||||||
SFCallbacks.PRE_LOGIN.invoker().onPlayerPreLogin(currentPlayer, connection, this::disconnect, _r);
|
SFCallbacks.PRE_LOGIN.invoker().onPlayerPreLogin(currentPlayer, connection, this::disconnect, _r);
|
||||||
return _r;
|
return _r;
|
||||||
|
|||||||
@@ -4,39 +4,39 @@ import io.ib67.sfcraft.SFCraft;
|
|||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import io.ib67.sfcraft.mixin.common.bridge.ServerPlayerBridge;
|
import io.ib67.sfcraft.mixin.common.bridge.ServerPlayerBridge;
|
||||||
import io.ib67.sfcraft.registry.chat.SimpleMessageDecorator;
|
import io.ib67.sfcraft.registry.chat.SimpleMessageDecorator;
|
||||||
import net.minecraft.network.DisconnectionInfo;
|
import net.minecraft.network.DisconnectionDetails;
|
||||||
import net.minecraft.network.message.MessageDecorator;
|
import net.minecraft.network.chat.ChatDecorator;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.*;
|
import org.spongepowered.asm.mixin.injection.*;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(ServerPlayNetworkHandler.class)
|
@Mixin(ServerGamePacketListenerImpl.class)
|
||||||
public abstract class ServerPlayNetworkHandlerMixin {
|
public abstract class ServerPlayNetworkHandlerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
public ServerPlayerEntity player;
|
public ServerPlayer player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author icybear
|
* @author icybear
|
||||||
* @reason small method, overwrite to reduce overhead
|
* @reason small method, overwrite to reduce overhead
|
||||||
*/
|
*/
|
||||||
@Redirect(method = "method_44900", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getMessageDecorator()Lnet/minecraft/network/message/MessageDecorator;"))
|
@Redirect(method = "method_44900", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getChatDecorator()Lnet/minecraft/network/chat/ChatDecorator;"))
|
||||||
public MessageDecorator getMessageDecorator(MinecraftServer instance) {
|
public ChatDecorator getMessageDecorator(MinecraftServer instance) {
|
||||||
return SFCraft.getInjector().getInstance(SimpleMessageDecorator.class);
|
return SFCraft.getInjector().getInstance(SimpleMessageDecorator.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayNetworkHandler;disconnect(Lnet/minecraft/text/Text;)V", ordinal = 2))
|
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;disconnect(Lnet/minecraft/network/chat/Component;)V", ordinal = 2))
|
||||||
public void onPlayerIdling(ServerPlayNetworkHandler instance, Text text) {
|
public void onPlayerIdling(ServerGamePacketListenerImpl instance, Component text) {
|
||||||
((ServerPlayerBridge) instance.player).setLastActionTime(Long.MAX_VALUE);
|
((ServerPlayerBridge) instance.player).setLastActionTime(Long.MAX_VALUE);
|
||||||
SFCallbacks.PLAYER_IDLE.invoker().onSwitchIdle(instance.player, true);
|
SFCallbacks.PLAYER_IDLE.invoker().onSwitchIdle(instance.player, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "onDisconnected", at = @At("HEAD"))
|
@Inject(method = "onDisconnect", at = @At("HEAD"))
|
||||||
public void onDisconnected(DisconnectionInfo instance, CallbackInfo ci) {
|
public void onDisconnected(DisconnectionDetails instance, CallbackInfo ci) {
|
||||||
player.updateLastActionTime();
|
player.resetLastActionTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,11 +2,11 @@ package io.ib67.sfcraft.mixin.server;
|
|||||||
|
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.util.Unit;
|
import net.minecraft.util.Unit;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -14,28 +14,28 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
@Mixin(ServerPlayerEntity.class)
|
@Mixin(ServerPlayer.class)
|
||||||
public class ServerPlayerEntityMixin {
|
public class ServerPlayerEntityMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
private long lastActionTime;
|
private long lastActionTime;
|
||||||
|
|
||||||
@Inject(method = "onDeath", at = @At("TAIL"))
|
@Inject(method = "die", at = @At("TAIL"))
|
||||||
public void onDeath(DamageSource damageSource, CallbackInfo ci) {
|
public void onDeath(DamageSource damageSource, CallbackInfo ci) {
|
||||||
SFCallbacks.PLAYER_DEATH.invoker().onPlayerDeath((ServerPlayerEntity) (Object) this, damageSource);
|
SFCallbacks.PLAYER_DEATH.invoker().onPlayerDeath((ServerPlayer) (Object) this, damageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "trySleep", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "startSleepInBed", at = @At("HEAD"), cancellable = true)
|
||||||
public void onSleep(BlockPos pos, CallbackInfoReturnable<Either<PlayerEntity.SleepFailureReason, Unit>> cir) {
|
public void onSleep(BlockPos pos, CallbackInfoReturnable<Either<Player.BedSleepingProblem, Unit>> cir) {
|
||||||
var result = SFCallbacks.PLAYER_SLEEP.invoker().onPlayerSleep((ServerPlayerEntity) (Object) this, pos);
|
var result = SFCallbacks.PLAYER_SLEEP.invoker().onPlayerSleep((ServerPlayer) (Object) this, pos);
|
||||||
if (result.left().isPresent()) {
|
if (result.left().isPresent()) {
|
||||||
cir.setReturnValue(result);
|
cir.setReturnValue(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "updateLastActionTime", at = @At("HEAD"))
|
@Inject(method = "resetLastActionTime", at = @At("HEAD"))
|
||||||
public void leaveAFK(CallbackInfo ci) {
|
public void leaveAFK(CallbackInfo ci) {
|
||||||
if (lastActionTime == Long.MAX_VALUE) {
|
if (lastActionTime == Long.MAX_VALUE) {
|
||||||
SFCallbacks.PLAYER_IDLE.invoker().onSwitchIdle((ServerPlayerEntity) (Object) this, false);
|
SFCallbacks.PLAYER_IDLE.invoker().onSwitchIdle((ServerPlayer) (Object) this, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,8 @@ import io.ib67.sfcraft.SFCraft;
|
|||||||
import io.ib67.sfcraft.mixin.common.bridge.ServerWorldBridge;
|
import io.ib67.sfcraft.mixin.common.bridge.ServerWorldBridge;
|
||||||
import io.ib67.sfcraft.module.RoomModule;
|
import io.ib67.sfcraft.module.RoomModule;
|
||||||
import io.ib67.sfcraft.util.MixinHelper;
|
import io.ib67.sfcraft.util.MixinHelper;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.world.level.GameRules;
|
||||||
import net.minecraft.world.GameRules;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -15,12 +13,12 @@ import org.spongepowered.asm.mixin.Unique;
|
|||||||
import org.spongepowered.asm.mixin.injection.*;
|
import org.spongepowered.asm.mixin.injection.*;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
@Mixin(ServerWorld.class)
|
@Mixin(ServerLevel.class)
|
||||||
public abstract class ServerWorldMixin {
|
public abstract class ServerWorldMixin {
|
||||||
@ModifyArg(method = "tickTime", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;setTimeOfDay(J)V"))
|
@ModifyArg(method = "tickTime", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setDayTime(J)V"))
|
||||||
public long setTimeOfDay(long timeOfDay) {
|
public long setTimeOfDay(long timeOfDay) {
|
||||||
int i = ((ServerWorld) (Object) this).getGameRules().getInt(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
|
int i = ((ServerLevel) (Object) this).getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||||
if (((ServerWorldBridge) this).getSleepManager().canSkipNight(i)) {
|
if (((ServerWorldBridge) this).getDEEPSLATE_BRICKS().areEnoughSleeping(i)) {
|
||||||
MixinHelper.spedUp = true;
|
MixinHelper.spedUp = true;
|
||||||
return timeOfDay + 10;
|
return timeOfDay + 10;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
package io.ib67.sfcraft.mixin.server;
|
package io.ib67.sfcraft.mixin.server;
|
||||||
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.server.world.SleepManager;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.server.players.SleepStatus;
|
||||||
|
|
||||||
@Mixin(SleepManager.class)
|
@Mixin(SleepStatus.class)
|
||||||
public abstract class SleepManagerMixin {
|
public abstract class SleepManagerMixin {
|
||||||
@Inject(method = "canResetTime", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "areEnoughDeepSleeping", at = @At("HEAD"), cancellable = true)
|
||||||
public void canResetTime(int percentage, List<ServerPlayerEntity> players, CallbackInfoReturnable<Boolean> cir) {
|
public void canResetTime(int percentage, List<ServerPlayer> players, CallbackInfoReturnable<Boolean> cir) {
|
||||||
if (players.isEmpty()) {
|
if (players.isEmpty()) {
|
||||||
cir.setReturnValue(false);
|
cir.setReturnValue(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var world = players.getFirst().getWorld();
|
var world = players.getFirst().level();
|
||||||
if (world.getTimeOfDay() % 24000 >= 12544) {
|
if (world.getDayTime() % 24000 >= 12544) {
|
||||||
if(!world.isRaining()){
|
if(!world.isRaining()){
|
||||||
cir.setReturnValue(false);
|
cir.setReturnValue(false);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -3,16 +3,16 @@ package io.ib67.sfcraft.mixin.server.subserver;
|
|||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import io.ib67.sfcraft.SFCraft;
|
import io.ib67.sfcraft.SFCraft;
|
||||||
import io.ib67.sfcraft.module.RoomModule;
|
import io.ib67.sfcraft.module.RoomModule;
|
||||||
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
@Mixin(PlayerListS2CPacket.Entry.class)
|
@Mixin(ClientboundPlayerInfoUpdatePacket.Entry.class)
|
||||||
public class PlayerListS2CPacket$EntryMixin {
|
public class PlayerListS2CPacket$EntryMixin {
|
||||||
@Unique
|
@Unique
|
||||||
private static final byte[] lock = new byte[0];
|
private static final byte[] lock = new byte[0];
|
||||||
@@ -31,11 +31,11 @@ public class PlayerListS2CPacket$EntryMixin {
|
|||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "<init>(Lnet/minecraft/server/network/ServerPlayerEntity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;getGameProfile()Lcom/mojang/authlib/GameProfile;"))
|
@Redirect(method = "<init>(Lnet/minecraft/server/level/ServerPlayer;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getGameProfile()Lcom/mojang/authlib/GameProfile;"))
|
||||||
private static GameProfile sf$redirectGameProfileForRoom(ServerPlayerEntity instance) {
|
private static GameProfile sf$redirectGameProfileForRoom(ServerPlayer instance) {
|
||||||
if (!RoomModule.isVirtual(instance.getUuid())) {
|
if (!RoomModule.isVirtual(instance.getUUID())) {
|
||||||
return instance.getGameProfile();
|
return instance.getGameProfile();
|
||||||
}
|
}
|
||||||
return getModule().devirtualize(instance.getUuid());
|
return getModule().devirtualize(instance.getUUID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,13 +5,6 @@ import io.ib67.sfcraft.SFCraft;
|
|||||||
import io.ib67.sfcraft.mixin.common.bridge.ServerChunkManagerBridge;
|
import io.ib67.sfcraft.mixin.common.bridge.ServerChunkManagerBridge;
|
||||||
import io.ib67.sfcraft.module.RoomModule;
|
import io.ib67.sfcraft.module.RoomModule;
|
||||||
import io.ib67.sfcraft.registry.RoomRegistry;
|
import io.ib67.sfcraft.registry.RoomRegistry;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.network.ClientConnection;
|
|
||||||
import net.minecraft.server.PlayerManager;
|
|
||||||
import net.minecraft.server.network.ConnectedClientData;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.math.GlobalPos;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -24,56 +17,63 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import net.minecraft.core.GlobalPos;
|
||||||
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.server.network.CommonListenerCookie;
|
||||||
|
import net.minecraft.server.players.PlayerList;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
|
||||||
@Mixin(PlayerManager.class)
|
@Mixin(PlayerList.class)
|
||||||
|
|
||||||
public abstract class PlayerManagerMixin {
|
public abstract class PlayerManagerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private static Logger LOGGER;
|
private static Logger LOGGER;
|
||||||
|
|
||||||
@Inject(method = "onPlayerConnect", at = @At("TAIL"))
|
@Inject(method = "placeNewPlayer", at = @At("TAIL"))
|
||||||
public void sf$updateSession(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) {
|
public void sf$updateSession(Connection connection, ServerPlayer player, CommonListenerCookie clientData, CallbackInfo ci) {
|
||||||
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
||||||
var room = registry.getRoomBy(player.getUuid());
|
var room = registry.getRoomBy(player.getUUID());
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
var spawn = room.getSpawnPosition();
|
var spawn = room.getSpawnPosition();
|
||||||
if(player.getWorld().getRegistryKey() != spawn.dimension()){
|
if(player.level().dimension() != spawn.dimension()){
|
||||||
teleportToRoom(player, spawn);
|
teleportToRoom(player, spawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.info("Room player joined as " + player.getName().getLiteralString() + "/" + player.getUuid());
|
LOGGER.info("Room player joined as " + player.getName().tryCollapseToString() + "/" + player.getUUID());
|
||||||
room.onPlayerJoin(player);
|
room.onPlayerJoin(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "respawnPlayer", at = @At("TAIL"))
|
@Inject(method = "respawn", at = @At("TAIL"))
|
||||||
public void sf$updateSession(ServerPlayerEntity player, boolean alive, Entity.RemovalReason removalReason, CallbackInfoReturnable<ServerPlayerEntity> cir) {
|
public void sf$updateSession(ServerPlayer player, boolean alive, Entity.RemovalReason removalReason, CallbackInfoReturnable<ServerPlayer> cir) {
|
||||||
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
||||||
var room = registry.getRoomBy(player.getUuid());
|
var room = registry.getRoomBy(player.getUUID());
|
||||||
if (!alive && room != null) {
|
if (!alive && room != null) {
|
||||||
var spawn = room.getSpawnPosition();
|
var spawn = room.getSpawnPosition();
|
||||||
teleportToRoom(cir.getReturnValue(), spawn);
|
teleportToRoom(cir.getReturnValue(), spawn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "checkCanJoin", cancellable = true, at = @At("HEAD"))
|
@Inject(method = "canPlayerLogin", cancellable = true, at = @At("HEAD"))
|
||||||
private void sf$bypassJoinLimit(SocketAddress address, GameProfile profile, CallbackInfoReturnable<Text> cir) {
|
private void sf$bypassJoinLimit(SocketAddress address, GameProfile profile, CallbackInfoReturnable<Component> cir) {
|
||||||
if (RoomModule.isVirtual(profile.getId())) cir.setReturnValue(null);
|
if (RoomModule.isVirtual(profile.getId())) cir.setReturnValue(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private void teleportToRoom(ServerPlayerEntity player, GlobalPos spawn) {
|
private void teleportToRoom(ServerPlayer player, GlobalPos spawn) {
|
||||||
var world = player.getServer().getWorld(spawn.dimension());
|
var world = player.getServer().getLevel(spawn.dimension());
|
||||||
var pos = spawn.pos();
|
var pos = spawn.pos();
|
||||||
((ServerChunkManagerBridge)world.getChunkManager()).getLevelManager().handleChunkEnter(player.getWatchedSection(), player);
|
((ServerChunkManagerBridge)world.getChunkSource()).getLevelManager().addPlayer(player.getLastSectionPos(), player);
|
||||||
player.teleport(world, pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0, true);
|
player.teleportTo(world, pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "remove", at = @At("HEAD"))
|
@Inject(method = "remove", at = @At("HEAD"))
|
||||||
public void sf$removePlayers(ServerPlayerEntity instance, CallbackInfo ci) {
|
public void sf$removePlayers(ServerPlayer instance, CallbackInfo ci) {
|
||||||
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
var registry = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
||||||
var room = registry.getRoomBy(instance.getUuid());
|
var room = registry.getRoomBy(instance.getUUID());
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
room.onPlayerQuit(instance);
|
room.onPlayerQuit(instance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ package io.ib67.sfcraft.mixin.server.subserver;
|
|||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
import io.ib67.sfcraft.module.RoomModule;
|
import io.ib67.sfcraft.module.RoomModule;
|
||||||
import io.ib67.sfcraft.util.Helper;
|
import io.ib67.sfcraft.util.Helper;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.util.WorldSavePath;
|
|
||||||
import net.minecraft.world.PlayerSaveHandler;
|
|
||||||
import net.minecraft.world.level.storage.LevelStorage;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -17,36 +13,40 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.storage.LevelResource;
|
||||||
|
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||||
|
import net.minecraft.world.level.storage.PlayerDataStorage;
|
||||||
|
|
||||||
@Mixin(PlayerSaveHandler.class)
|
@Mixin(PlayerDataStorage.class)
|
||||||
public class PlayerSaveHandlerMixin {
|
public class PlayerSaveHandlerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private File playerDataDir;
|
private File playerDir;
|
||||||
@Unique
|
@Unique
|
||||||
private File virtualPlayerFolder;
|
private File virtualPlayerFolder;
|
||||||
|
|
||||||
@Inject(at = @At("TAIL"), method = "<init>")
|
@Inject(at = @At("TAIL"), method = "<init>")
|
||||||
private void sf$createVirtualPlayerDataFolder(LevelStorage.Session session, DataFixer dataFixer, CallbackInfo ci) {
|
private void sf$createVirtualPlayerDataFolder(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, CallbackInfo ci) {
|
||||||
this.virtualPlayerFolder = session.getDirectory(WorldSavePath.PLAYERDATA).resolve("in_rooms").toFile();
|
this.virtualPlayerFolder = session.getLevelPath(LevelResource.PLAYER_DATA_DIR).resolve("in_rooms").toFile();
|
||||||
this.virtualPlayerFolder.mkdirs();
|
this.virtualPlayerFolder.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/world/PlayerSaveHandler;playerDataDir:Ljava/io/File;"), method = "savePlayerData")
|
@Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;playerDir:Ljava/io/File;"), method = "save")
|
||||||
private File sf$getPlayerDataFolder(PlayerSaveHandler instance, PlayerEntity entity) {
|
private File sf$getPlayerDataFolder(PlayerDataStorage instance, Player entity) {
|
||||||
if (RoomModule.isVirtual(entity.getUuid())) {
|
if (RoomModule.isVirtual(entity.getUUID())) {
|
||||||
return virtualPlayerFolder;
|
return virtualPlayerFolder;
|
||||||
} else {
|
} else {
|
||||||
return this.playerDataDir;
|
return this.playerDir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/world/PlayerSaveHandler;playerDataDir:Ljava/io/File;"), method = "loadPlayerData(Lnet/minecraft/entity/player/PlayerEntity;Ljava/lang/String;)Ljava/util/Optional;")
|
@Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;playerDir:Ljava/io/File;"), method = "load(Lnet/minecraft/world/entity/player/Player;Ljava/lang/String;)Ljava/util/Optional;")
|
||||||
private File sf$saveGetPlayerFolder(PlayerSaveHandler instance, PlayerEntity player) {
|
private File sf$saveGetPlayerFolder(PlayerDataStorage instance, Player player) {
|
||||||
if (RoomModule.isVirtual(player.getUuid())) {
|
if (RoomModule.isVirtual(player.getUUID())) {
|
||||||
return virtualPlayerFolder;
|
return virtualPlayerFolder;
|
||||||
} else {
|
} else {
|
||||||
return this.playerDataDir;
|
return this.playerDir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+25
-25
@@ -8,12 +8,6 @@ import io.ib67.sfcraft.registry.RoomRegistry;
|
|||||||
import io.ib67.sfcraft.room.CookieState;
|
import io.ib67.sfcraft.room.CookieState;
|
||||||
import io.ib67.sfcraft.room.RequestedRoom;
|
import io.ib67.sfcraft.room.RequestedRoom;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import net.minecraft.network.ClientConnection;
|
|
||||||
import net.minecraft.network.packet.c2s.common.CookieResponseC2SPacket;
|
|
||||||
import net.minecraft.network.packet.s2c.common.CookieRequestS2CPacket;
|
|
||||||
import net.minecraft.server.PlayerManager;
|
|
||||||
import net.minecraft.server.network.ServerLoginNetworkHandler;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
@@ -26,26 +20,32 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.protocol.cookie.ClientboundCookieRequestPacket;
|
||||||
|
import net.minecraft.network.protocol.cookie.ServerboundCookieResponsePacket;
|
||||||
|
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||||
|
import net.minecraft.server.players.PlayerList;
|
||||||
|
|
||||||
import static io.ib67.sfcraft.room.CookieState.*;
|
import static io.ib67.sfcraft.room.CookieState.*;
|
||||||
import static io.ib67.sfcraft.room.RoomTeleporter.ROOM_COOKIE;
|
import static io.ib67.sfcraft.room.RoomTeleporter.ROOM_COOKIE;
|
||||||
|
|
||||||
@Mixin(ServerLoginNetworkHandler.class)
|
@Mixin(ServerLoginPacketListenerImpl.class)
|
||||||
public abstract class ServerLoginNetworkHandlerMixin {
|
public abstract class ServerLoginNetworkHandlerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
abstract void startVerify(GameProfile profile);
|
abstract void startClientVerification(GameProfile profile);
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
private @Nullable GameProfile profile;
|
private @Nullable GameProfile authenticatedProfile;
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private boolean transferred;
|
private boolean transferred;
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private ClientConnection connection;
|
private Connection connection;
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public abstract void disconnect(Text reason);
|
public abstract void disconnect(Component reason);
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
@@ -61,12 +61,12 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
|||||||
void restoreVerify(CallbackInfo ci) {
|
void restoreVerify(CallbackInfo ci) {
|
||||||
if ((sf$cookieState == SENT && sf$room != null) || (clean && sf$cookieState != DONE)) {
|
if ((sf$cookieState == SENT && sf$room != null) || (clean && sf$cookieState != DONE)) {
|
||||||
sf$cookieState = CookieState.RECV;
|
sf$cookieState = CookieState.RECV;
|
||||||
startVerify(this.profile);
|
startClientVerification(this.authenticatedProfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "onCookieResponse", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "handleCookieResponse", at = @At("HEAD"), cancellable = true)
|
||||||
private void sf$onRoomId(CookieResponseC2SPacket packet, CallbackInfo ci) {
|
private void sf$onRoomId(ServerboundCookieResponsePacket packet, CallbackInfo ci) {
|
||||||
if (packet.key().equals(ROOM_COOKIE)) {
|
if (packet.key().equals(ROOM_COOKIE)) {
|
||||||
if (sf$cookieState != SENT) throw new IllegalStateException("Protocol error");
|
if (sf$cookieState != SENT) throw new IllegalStateException("Protocol error");
|
||||||
var roomSvc = SFCraft.getInjector().getInstance(RoomModule.class);
|
var roomSvc = SFCraft.getInjector().getInstance(RoomModule.class);
|
||||||
@@ -74,7 +74,7 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
|||||||
try {
|
try {
|
||||||
if (packet.payload().length == 0) {
|
if (packet.payload().length == 0) {
|
||||||
// clean reconnect.
|
// clean reconnect.
|
||||||
LOGGER.info("Player " + profile.getName() + " requested a clean reconnection");
|
LOGGER.info("Player " + authenticatedProfile.getName() + " requested a clean reconnection");
|
||||||
clean = true;
|
clean = true;
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
return;
|
return;
|
||||||
@@ -83,7 +83,7 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
|||||||
this.sf$room = RequestedRoom.PACKET_CODEC.decode(Unpooled.wrappedBuffer(sign.data()));
|
this.sf$room = RequestedRoom.PACKET_CODEC.decode(Unpooled.wrappedBuffer(sign.data()));
|
||||||
} catch (Exception t) {
|
} catch (Exception t) {
|
||||||
LOGGER.error("Failed to read cookie: {0}", t);
|
LOGGER.error("Failed to read cookie: {0}", t);
|
||||||
this.disconnect(Text.of("Protocol error."));
|
this.disconnect(Component.nullToEmpty("Protocol error."));
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -91,29 +91,29 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
|||||||
ci.cancel();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "startVerify", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "startClientVerification", at = @At("HEAD"), cancellable = true)
|
||||||
void sf$makeTransferPlayerProfile(GameProfile profile, CallbackInfo ci) {
|
void sf$makeTransferPlayerProfile(GameProfile profile, CallbackInfo ci) {
|
||||||
if (transferred && !clean) {
|
if (transferred && !clean) {
|
||||||
switch (this.sf$cookieState) {
|
switch (this.sf$cookieState) {
|
||||||
case NOT_SENT -> {
|
case NOT_SENT -> {
|
||||||
this.profile = profile;
|
this.authenticatedProfile = profile;
|
||||||
this.connection.send(new CookieRequestS2CPacket(ROOM_COOKIE));
|
this.connection.send(new ClientboundCookieRequestPacket(ROOM_COOKIE));
|
||||||
this.sf$cookieState = SENT;
|
this.sf$cookieState = SENT;
|
||||||
}
|
}
|
||||||
case RECV -> {
|
case RECV -> {
|
||||||
var ssr = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
var ssr = SFCraft.getInjector().getInstance(RoomRegistry.class);
|
||||||
var room = ssr.getRoomBy(sf$room.identifier());
|
var room = ssr.getRoomBy(sf$room.identifier());
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
this.profile = new GameProfile(sf$room.profileUuid(), sf$room.profileName());
|
this.authenticatedProfile = new GameProfile(sf$room.profileUuid(), sf$room.profileName());
|
||||||
var session = room.getPlayerManager().getSessionBy(sf$room.profileUuid());
|
var session = room.getPlayerManager().getSessionBy(sf$room.profileUuid());
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
disconnect(Text.of("Session isn't exists."));
|
disconnect(Component.nullToEmpty("Session isn't exists."));
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
session.onPlayerLogin(sf$room.profileUuid());
|
session.onPlayerLogin(sf$room.profileUuid());
|
||||||
this.sf$cookieState = DONE;
|
this.sf$cookieState = DONE;
|
||||||
this.startVerify(this.profile);
|
this.startClientVerification(this.authenticatedProfile);
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -128,9 +128,9 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "tickVerify", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;checkCanJoin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/text/Text;"))
|
@Redirect(method = "verifyLoginAndFinishConnectionSetup", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/network/chat/Component;"))
|
||||||
private Text sf$bypassRoomPlayer(PlayerManager instance, SocketAddress address, GameProfile profile) {
|
private Component sf$bypassRoomPlayer(PlayerList instance, SocketAddress address, GameProfile profile) {
|
||||||
if (sf$cookieState == DONE) return null;
|
if (sf$cookieState == DONE) return null;
|
||||||
return instance.checkCanJoin(address, profile);
|
return instance.canPlayerLogin(address, profile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,6 @@ package io.ib67.sfcraft.mixin.server.subserver;
|
|||||||
|
|
||||||
import io.ib67.sfcraft.SFCraft;
|
import io.ib67.sfcraft.SFCraft;
|
||||||
import io.ib67.sfcraft.registry.RoomRegistry;
|
import io.ib67.sfcraft.registry.RoomRegistry;
|
||||||
import net.minecraft.network.packet.s2c.play.PositionFlag;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.server.world.ServerWorld;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
@@ -12,16 +9,19 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.entity.Relative;
|
||||||
|
|
||||||
@Mixin(ServerPlayerEntity.class)
|
@Mixin(ServerPlayer.class)
|
||||||
public abstract class ServerPlayerEntityMixin {
|
public abstract class ServerPlayerEntityMixin {
|
||||||
//todo test this
|
//todo test this
|
||||||
//todo fix playground operate players in main world
|
//todo fix playground operate players in main world
|
||||||
@Inject(at=@At("HEAD"), method = "teleport(Lnet/minecraft/server/world/ServerWorld;DDDLjava/util/Set;FFZ)Z")
|
@Inject(at=@At("HEAD"), method = "teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")
|
||||||
public void sf$interceptTeleport(ServerWorld world, double destX, double destY, double destZ, Set<PositionFlag> flags, float yaw, float pitch, boolean resetCamera, CallbackInfoReturnable<Boolean> cir) {
|
public void sf$interceptTeleport(ServerLevel world, double destX, double destY, double destZ, Set<Relative> flags, float yaw, float pitch, boolean resetCamera, CallbackInfoReturnable<Boolean> cir) {
|
||||||
var room = roomRegistry().getRoomBy($this().getUuid());
|
var room = roomRegistry().getRoomBy($this().getUUID());
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
if (world.getRegistryKey() != room.getSpawnPosition().dimension()) {
|
if (world.dimension() != room.getSpawnPosition().dimension()) {
|
||||||
cir.setReturnValue(false);
|
cir.setReturnValue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ public abstract class ServerPlayerEntityMixin {
|
|||||||
return SFCraft.getInjector().getInstance(RoomRegistry.class);
|
return SFCraft.getInjector().getInstance(RoomRegistry.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerPlayerEntity $this() {
|
private ServerPlayer $this() {
|
||||||
return (ServerPlayerEntity) (Object) this;
|
return (ServerPlayer) (Object) this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,9 @@ import io.ib67.sfcraft.callback.SFCallbacks;
|
|||||||
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
||||||
import io.ib67.sfcraft.module.chat.ChatPrefix;
|
import io.ib67.sfcraft.module.chat.ChatPrefix;
|
||||||
import io.ib67.sfcraft.module.chat.ChatPrefixModule;
|
import io.ib67.sfcraft.module.chat.ChatPrefixModule;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.util.CommonColors;
|
||||||
|
|
||||||
public class AFKModule extends ServerModule {
|
public class AFKModule extends ServerModule {
|
||||||
@Inject
|
@Inject
|
||||||
@@ -21,7 +21,7 @@ public class AFKModule extends ServerModule {
|
|||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
SFCallbacks.PLAYER_IDLE.register(this::onAFK);
|
SFCallbacks.PLAYER_IDLE.register(this::onAFK);
|
||||||
prefix = new ChatPrefix(
|
prefix = new ChatPrefix(
|
||||||
Text.literal("[挂机] ").withColor(Colors.LIGHT_GRAY),
|
Component.literal("[挂机] ").withColor(CommonColors.LIGHT_GRAY),
|
||||||
"afk",
|
"afk",
|
||||||
true,
|
true,
|
||||||
10
|
10
|
||||||
@@ -29,7 +29,7 @@ public class AFKModule extends ServerModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void onAFK(ServerPlayerEntity player, boolean afk) {
|
private void onAFK(ServerPlayer player, boolean afk) {
|
||||||
if (afk) {
|
if (afk) {
|
||||||
enAFK(player);
|
enAFK(player);
|
||||||
} else {
|
} else {
|
||||||
@@ -37,20 +37,20 @@ public class AFKModule extends ServerModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enAFK(ServerPlayerEntity player) {
|
private void enAFK(ServerPlayer player) {
|
||||||
chatPrefixModule.applyPrefix(player, prefix);
|
chatPrefixModule.applyPrefix(player, prefix);
|
||||||
player.getServer().getPlayerManager().broadcast(
|
player.getServer().getPlayerList().broadcastSystemMessage(
|
||||||
Text.literal(" * " + player.getName().getLiteralString() + " 正在挂机.").withColor(Colors.LIGHT_GRAY),
|
Component.literal(" * " + player.getName().tryCollapseToString() + " 正在挂机.").withColor(CommonColors.LIGHT_GRAY),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
SFCallbacks.PLAYER_AFK.invoker().onAFKStatus(player, true);
|
SFCallbacks.PLAYER_AFK.invoker().onAFKStatus(player, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deAFK(ServerPlayerEntity player) {
|
public void deAFK(ServerPlayer player) {
|
||||||
String playerName = player.getName().getLiteralString();
|
String playerName = player.getName().tryCollapseToString();
|
||||||
chatPrefixModule.removePrefix(player, prefix);
|
chatPrefixModule.removePrefix(player, prefix);
|
||||||
player.getServer().getPlayerManager().broadcast(
|
player.getServer().getPlayerList().broadcastSystemMessage(
|
||||||
Text.literal(" * " + playerName + " 回来了.").withColor(Colors.LIGHT_GRAY),
|
Component.literal(" * " + playerName + " 回来了.").withColor(CommonColors.LIGHT_GRAY),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
SFCallbacks.PLAYER_AFK.invoker().onAFKStatus(player, false);
|
SFCallbacks.PLAYER_AFK.invoker().onAFKStatus(player, false);
|
||||||
|
|||||||
@@ -4,27 +4,27 @@ import io.ib67.sfcraft.ServerModule;
|
|||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import it.unimi.dsi.fastutil.objects.*;
|
import it.unimi.dsi.fastutil.objects.*;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.text.MutableText;
|
import net.minecraft.util.CommonColors;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.entity.EquipmentSlot;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
|
|
||||||
public class ElytraSpeedMeterModule extends ServerModule {
|
public class ElytraSpeedMeterModule extends ServerModule {
|
||||||
private static final int BAR_LEN = 20;
|
private static final int BAR_LEN = 20;
|
||||||
private static final int MAX_NORMAL_SPEED = 6;
|
private static final int MAX_NORMAL_SPEED = 6;
|
||||||
private static final int THRESHLD_OF_ELYTRA_FLY = 8;
|
private static final int THRESHLD_OF_ELYTRA_FLY = 8;
|
||||||
private static final Text[] ELYTRA_DURABILITY = new Text[100];
|
private static final Component[] ELYTRA_DURABILITY = new Component[100];
|
||||||
private final Object2ObjectMap<PlayerEntity, BlockPos> playerFlyMap = new Object2ObjectOpenHashMap<>();
|
private final Object2ObjectMap<Player, BlockPos> playerFlyMap = new Object2ObjectOpenHashMap<>();
|
||||||
private final Object2FloatMap<PlayerEntity> lastMeasuredSpeed = new Object2FloatOpenHashMap<>();
|
private final Object2FloatMap<Player> lastMeasuredSpeed = new Object2FloatOpenHashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (int i = 1; i <= 100; i++) {
|
for (int i = 1; i <= 100; i++) {
|
||||||
ELYTRA_DURABILITY[i - 1] = Text.literal("ELYTRA: " + i + "%").withColor(getDamageColor(i));
|
ELYTRA_DURABILITY[i - 1] = Component.literal("ELYTRA: " + i + "%").withColor(getDamageColor(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,68 +34,68 @@ public class ElytraSpeedMeterModule extends ServerModule {
|
|||||||
ServerPlayConnectionEvents.DISCONNECT.register(this::onDisconnect);
|
ServerPlayConnectionEvents.DISCONNECT.register(this::onDisconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDisconnect(ServerPlayNetworkHandler serverPlayNetworkHandler, MinecraftServer minecraftServer) {
|
private void onDisconnect(ServerGamePacketListenerImpl serverPlayNetworkHandler, MinecraftServer minecraftServer) {
|
||||||
clean(serverPlayNetworkHandler.getPlayer());
|
clean(serverPlayNetworkHandler.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clean(ServerPlayerEntity player) {
|
private void clean(ServerPlayer player) {
|
||||||
playerFlyMap.remove(player);
|
playerFlyMap.remove(player);
|
||||||
lastMeasuredSpeed.removeFloat(player);
|
lastMeasuredSpeed.removeFloat(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFlying(PlayerEntity player, long f, boolean b) {
|
private void onFlying(Player player, long f, boolean b) {
|
||||||
if (f < THRESHLD_OF_ELYTRA_FLY * 20) {
|
if (f < THRESHLD_OF_ELYTRA_FLY * 20) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (b) {
|
if (b) {
|
||||||
var text = Text.literal("");
|
var text = Component.literal("");
|
||||||
text.append(genPitchMeter(player.getPitch()));
|
text.append(genPitchMeter(player.getXRot()));
|
||||||
text.append(" ");
|
text.append(" ");
|
||||||
text.append(generateDurabilityMeter(f, player));
|
text.append(generateDurabilityMeter(f, player));
|
||||||
player.sendMessage(text, true);
|
player.displayClientMessage(text, true);
|
||||||
} else {
|
} else {
|
||||||
clean((ServerPlayerEntity) player);
|
clean((ServerPlayer) player);
|
||||||
if (f > THRESHLD_OF_ELYTRA_FLY * 20) {
|
if (f > THRESHLD_OF_ELYTRA_FLY * 20) {
|
||||||
player.sendMessage(Text.literal("!! LANDED !!").withColor(Colors.GREEN), true);
|
player.displayClientMessage(Component.literal("!! LANDED !!").withColor(CommonColors.GREEN), true);
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(Text.empty(), true);
|
player.displayClientMessage(Component.empty(), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Text genPitchMeter(float pitch) {
|
private Component genPitchMeter(float pitch) {
|
||||||
MutableText text;
|
MutableComponent text;
|
||||||
var display = (Math.ceil(Math.abs(pitch) * 100) / 100);
|
var display = (Math.ceil(Math.abs(pitch) * 100) / 100);
|
||||||
if (pitch < 0) { // 朝上
|
if (pitch < 0) { // 朝上
|
||||||
text = Text.literal(" 🡹 " + display + "°");
|
text = Component.literal(" 🡹 " + display + "°");
|
||||||
} else {
|
} else {
|
||||||
text = Text.literal(" 🡻 " + display + "°");
|
text = Component.literal(" 🡻 " + display + "°");
|
||||||
}
|
}
|
||||||
if (pitch > 75) {
|
if (pitch > 75) {
|
||||||
text.withColor(Colors.LIGHT_RED);
|
text.withColor(CommonColors.SOFT_RED);
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Text generateDurabilityMeter(long f, PlayerEntity player) {
|
private Component generateDurabilityMeter(long f, Player player) {
|
||||||
var stack = player.getEquippedStack(EquipmentSlot.CHEST);
|
var stack = player.getItemBySlot(EquipmentSlot.CHEST);
|
||||||
if (stack.isDamageable() && stack.isDamaged()) {
|
if (stack.isDamageableItem() && stack.isDamaged()) {
|
||||||
var remaining = stack.getMaxDamage() - stack.getDamage();
|
var remaining = stack.getMaxDamage() - stack.getDamageValue();
|
||||||
var percent = (int) Math.ceil(((double) remaining / stack.getMaxDamage()) * 100);
|
var percent = (int) Math.ceil(((double) remaining / stack.getMaxDamage()) * 100);
|
||||||
return ELYTRA_DURABILITY[Math.max(percent - 1, 0)];
|
return ELYTRA_DURABILITY[Math.max(percent - 1, 0)];
|
||||||
}
|
}
|
||||||
return Text.literal("ELYTRA: INFINITY").withColor(Colors.BLUE);
|
return Component.literal("ELYTRA: INFINITY").withColor(CommonColors.BLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getDamageColor(int percent) {
|
private static int getDamageColor(int percent) {
|
||||||
if (percent > 70) {
|
if (percent > 70) {
|
||||||
return Colors.GREEN;
|
return CommonColors.GREEN;
|
||||||
} else if (percent > 50) {
|
} else if (percent > 50) {
|
||||||
return Colors.LIGHT_YELLOW;
|
return CommonColors.SOFT_YELLOW;
|
||||||
} else if (percent > 30) {
|
} else if (percent > 30) {
|
||||||
return Colors.LIGHT_RED;
|
return CommonColors.SOFT_RED;
|
||||||
}
|
}
|
||||||
return Colors.RED;
|
return CommonColors.RED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,54 +6,54 @@ import io.ib67.sfcraft.util.Helper;
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
|
||||||
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
||||||
import net.minecraft.block.Fertilizable;
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.sound.SoundEvents;
|
import net.minecraft.world.level.block.BonemealableBlock;
|
||||||
|
|
||||||
public class FartFertilizerModule extends ServerModule {
|
public class FartFertilizerModule extends ServerModule {
|
||||||
private final Object2LongMap<PlayerEntity> lastSneaked = new Object2LongOpenHashMap<>();
|
private final Object2LongMap<Player> lastSneaked = new Object2LongOpenHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
SFCallbacks.PLAYER_SNEAKING.register(this::onSneaking);
|
SFCallbacks.PLAYER_SNEAKING.register(this::onSneaking);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSneaking(PlayerEntity player, boolean sneak) {
|
private void onSneaking(Player player, boolean sneak) {
|
||||||
if (sneak) {
|
if (sneak) {
|
||||||
var lastSneak = lastSneaked.getOrDefault(player, 0);
|
var lastSneak = lastSneaked.getOrDefault(player, 0);
|
||||||
var dlta = Math.min(System.currentTimeMillis() - lastSneak, 100);
|
var dlta = Math.min(System.currentTimeMillis() - lastSneak, 100);
|
||||||
if (player.getRandom().nextBetween(50, 150) > dlta) {
|
if (player.getRandom().nextIntBetweenInclusive(50, 150) > dlta) {
|
||||||
var playerPos = player.getBlockPos();
|
var playerPos = player.blockPosition();
|
||||||
var start = playerPos.add(-2, 0, -2);
|
var start = playerPos.offset(-2, 0, -2);
|
||||||
var end = playerPos.add(2, 1, 2);
|
var end = playerPos.offset(2, 1, 2);
|
||||||
for (int dX = 0; dX < end.getX() - start.getX(); dX++) {
|
for (int dX = 0; dX < end.getX() - start.getX(); dX++) {
|
||||||
for (int dZ = 0; dZ < end.getZ() - start.getZ(); dZ++) {
|
for (int dZ = 0; dZ < end.getZ() - start.getZ(); dZ++) {
|
||||||
for (int dY = 0; dY < end.getY() - start.getY(); dY++) {
|
for (int dY = 0; dY < end.getY() - start.getY(); dY++) {
|
||||||
var blockPos = start.add(dX, dY, dZ);
|
var blockPos = start.offset(dX, dY, dZ);
|
||||||
var state = player.getWorld().getBlockState(blockPos);
|
var state = player.level().getBlockState(blockPos);
|
||||||
var block = state.getBlock();
|
var block = state.getBlock();
|
||||||
if (Helper.canFertilize(block)) {
|
if (Helper.canFertilize(block)) {
|
||||||
var wld = (ServerWorld) player.getWorld();
|
var wld = (ServerLevel) player.level();
|
||||||
wld.spawnParticles(
|
wld.sendParticles(
|
||||||
ParticleTypes.COMPOSTER,
|
ParticleTypes.COMPOSTER,
|
||||||
blockPos.getX(), blockPos.getY(), blockPos.getZ(), 5,
|
blockPos.getX(), blockPos.getY(), blockPos.getZ(), 5,
|
||||||
Math.max(0.5, Math.random()), Math.max(0.5, Math.random()), Math.max(0.5, Math.random()),
|
Math.max(0.5, Math.random()), Math.max(0.5, Math.random()), Math.max(0.5, Math.random()),
|
||||||
0.4
|
0.4
|
||||||
);
|
);
|
||||||
for (ServerPlayerEntity serverPlayerEntity : PlayerLookup.around(wld, blockPos, 6f)) {
|
for (ServerPlayer serverPlayerEntity : PlayerLookup.around(wld, blockPos, 6f)) {
|
||||||
serverPlayerEntity.playSoundToPlayer(
|
serverPlayerEntity.playNotifySound(
|
||||||
SoundEvents.BLOCK_COMPOSTER_FILL,
|
SoundEvents.COMPOSTER_FILL,
|
||||||
SoundCategory.BLOCKS,
|
SoundSource.BLOCKS,
|
||||||
((6 - serverPlayerEntity.distanceTo(player) + 1) / 6) * 50,
|
((6 - serverPlayerEntity.distanceTo(player) + 1) / 6) * 50,
|
||||||
3f
|
3f
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (player.getRandom().nextInt(10) < 3) {
|
if (player.getRandom().nextInt(10) < 3) {
|
||||||
((Fertilizable) block).grow(wld,
|
((BonemealableBlock) block).performBonemeal(wld,
|
||||||
wld.getRandom(), blockPos, state);
|
wld.getRandom(), blockPos, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class MotdModule extends ServerModule {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
originalMotd = minecraftServer.get().getServerMotd();
|
originalMotd = minecraftServer.get().getMotd();
|
||||||
minecraftServer.get().setMotd(motd);
|
minecraftServer.get().setMotd(motd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,15 +12,14 @@ import io.ib67.sfcraft.callback.SFCallbacks;
|
|||||||
import io.ib67.sfcraft.config.SFConfig;
|
import io.ib67.sfcraft.config.SFConfig;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.network.ClientConnection;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.server.WhitelistEntry;
|
import net.minecraft.commands.Commands;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.core.UUIDUtil;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.network.Connection;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.server.players.UserWhiteListEntry;
|
||||||
import net.minecraft.util.Uuids;
|
import net.minecraft.util.CommonColors;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -40,46 +39,46 @@ public class OfflineExemptModule extends ServerModule {
|
|||||||
CommandRegistrationCallback.EVENT.register(this::registerCommand);
|
CommandRegistrationCallback.EVENT.register(this::registerCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment registrationEnvironment) {
|
private void registerCommand(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext registryAccess, Commands.CommandSelection registrationEnvironment) {
|
||||||
dispatcher.register(
|
dispatcher.register(
|
||||||
LiteralArgumentBuilder.<ServerCommandSource>literal("addwl")
|
LiteralArgumentBuilder.<CommandSourceStack>literal("addwl")
|
||||||
.requires(i -> isEnabled())
|
.requires(i -> isEnabled())
|
||||||
.requires(it -> it.hasPermissionLevel(2) || SFConsts.COMMAND_ADDWL.hasPermission(it.getPlayer()))
|
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_ADDWL.hasPermission(it.getPlayer()))
|
||||||
.then(RequiredArgumentBuilder.<ServerCommandSource, String>argument("player", StringArgumentType.string())
|
.then(RequiredArgumentBuilder.<CommandSourceStack, String>argument("player", StringArgumentType.string())
|
||||||
.executes(it -> this.addPlayerOffline(it.getSource(), it.getArgument("player", String.class))))
|
.executes(it -> this.addPlayerOffline(it.getSource(), it.getArgument("player", String.class))))
|
||||||
|
|
||||||
);
|
);
|
||||||
dispatcher.register(LiteralArgumentBuilder.<ServerCommandSource>literal("listoffline")
|
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("listoffline")
|
||||||
.requires(i -> isEnabled())
|
.requires(i -> isEnabled())
|
||||||
.requires(it -> it.hasPermissionLevel(2) || SFConsts.COMMAND_LISTOFFLINE.hasPermission(it.getPlayer()))
|
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_LISTOFFLINE.hasPermission(it.getPlayer()))
|
||||||
.executes(this::listOffline)
|
.executes(this::listOffline)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addPlayerOffline(ServerCommandSource source, String player) {
|
public int addPlayerOffline(CommandSourceStack source, String player) {
|
||||||
player = player.trim();
|
player = player.trim();
|
||||||
var pm = source.getServer().getPlayerManager();
|
var pm = source.getServer().getPlayerList();
|
||||||
var wl = pm.getWhitelist();
|
var wl = pm.getWhiteList();
|
||||||
if (List.of(wl.getNames()).contains(player)) {
|
if (List.of(wl.getUserList()).contains(player)) {
|
||||||
source.sendError(Text.of(player + " is already whitelisted or this id is conflict with a online user."));
|
source.sendFailure(Component.nullToEmpty(player + " is already whitelisted or this id is conflict with a online user."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var profile = Uuids.getOfflinePlayerProfile(player);
|
var profile = UUIDUtil.createOfflineProfile(player);
|
||||||
wl.add(new WhitelistEntry(profile));
|
wl.add(new UserWhiteListEntry(profile));
|
||||||
var uc = source.getServer().getUserCache();
|
var uc = source.getServer().getProfileCache();
|
||||||
if (uc != null) uc.add(profile);
|
if (uc != null) uc.add(profile);
|
||||||
source.sendMessage(Text.of("[" + profile.getName() + "/" + profile.getId() + "]" + " is added!"));
|
source.sendSystemMessage(Component.nullToEmpty("[" + profile.getName() + "/" + profile.getId() + "]" + " is added!"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int listOffline(CommandContext<ServerCommandSource> ctx) {
|
public int listOffline(CommandContext<CommandSourceStack> ctx) {
|
||||||
var source = ctx.getSource();
|
var source = ctx.getSource();
|
||||||
var server = source.getServer();
|
var server = source.getServer();
|
||||||
var wl = server.getPlayerManager().getWhitelist();
|
var wl = server.getPlayerList().getWhiteList();
|
||||||
var names = wl.getNames();
|
var names = wl.getUserList();
|
||||||
source.sendMessage(Text.of("Offline Users:").copy().withColor(Colors.GREEN));
|
source.sendSystemMessage(Component.nullToEmpty("Offline Users:").copy().withColor(CommonColors.GREEN));
|
||||||
var r = Stream.of(names).filter(name -> wl.isAllowed(Uuids.getOfflinePlayerProfile(name))).collect(Collectors.joining(", "));
|
var r = Stream.of(names).filter(name -> wl.isWhiteListed(UUIDUtil.createOfflineProfile(name))).collect(Collectors.joining(", "));
|
||||||
source.sendMessage(Text.of(r.isEmpty() ? "No offline users found in whitelist." : r));
|
source.sendSystemMessage(Component.nullToEmpty(r.isEmpty() ? "No offline users found in whitelist." : r));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,9 +92,9 @@ public class OfflineExemptModule extends ServerModule {
|
|||||||
state = temporallyState || config.enableOfflineExempt;
|
state = temporallyState || config.enableOfflineExempt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPreLogin(String s, ClientConnection connection, Consumer<Text> textConsumer, boolean offline) {
|
private void onPreLogin(String s, Connection connection, Consumer<Component> textConsumer, boolean offline) {
|
||||||
if (!state && offline) {
|
if (!state && offline) {
|
||||||
textConsumer.accept(Text.of("§c盗版赦免现已关闭"));
|
textConsumer.accept(Component.nullToEmpty("§c盗版赦免现已关闭"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,21 +12,20 @@ import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
|||||||
import io.ib67.sfcraft.registry.RoomRegistry;
|
import io.ib67.sfcraft.registry.RoomRegistry;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.network.PacketCallbacks;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.network.packet.s2c.common.ServerTransferS2CPacket;
|
import net.minecraft.commands.Commands;
|
||||||
import net.minecraft.network.packet.s2c.common.StoreCookieS2CPacket;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.network.PacketSendListener;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.network.protocol.common.ClientboundStoreCookiePacket;
|
||||||
import net.minecraft.server.world.ChunkTicketType;
|
import net.minecraft.network.protocol.common.ClientboundTransferPacket;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.Pair;
|
import net.minecraft.server.level.TicketType;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.Tuple;
|
||||||
import net.minecraft.util.math.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -44,7 +43,7 @@ public class RoomModule extends ServerModule {
|
|||||||
private MinecraftServerSupplier serverSupplier;
|
private MinecraftServerSupplier serverSupplier;
|
||||||
@Inject
|
@Inject
|
||||||
private SFConfig config;
|
private SFConfig config;
|
||||||
private final List<Pair<RegistryKey<World>, BlockPos>> pregenQueue = new ArrayList<>();
|
private final List<Tuple<ResourceKey<Level>, BlockPos>> pregenQueue = new ArrayList<>();
|
||||||
private final Map<UUID, GameProfile> uuidMapper = new ConcurrentHashMap<>();
|
private final Map<UUID, GameProfile> uuidMapper = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -54,45 +53,45 @@ public class RoomModule extends ServerModule {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
for (Pair<RegistryKey<World>, BlockPos> registryKeyBlockPosPair : pregenQueue) {
|
for (Tuple<ResourceKey<Level>, BlockPos> registryKeyBlockPosPair : pregenQueue) {
|
||||||
var world = serverSupplier.get().getWorld(registryKeyBlockPosPair.getLeft());
|
var world = serverSupplier.get().getLevel(registryKeyBlockPosPair.getA());
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
log.warn("Cannot find world {}", registryKeyBlockPosPair.getLeft());
|
log.warn("Cannot find world {}", registryKeyBlockPosPair.getA());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
world.getChunkManager().addTicket(ChunkTicketType.START, new ChunkPos(registryKeyBlockPosPair.getRight()), 64);
|
world.getChunkSource().addTicketWithRadius(TicketType.START, new ChunkPos(registryKeyBlockPosPair.getB()), 64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommand(CommandDispatcher<ServerCommandSource> serverCommandSourceCommandDispatcher, CommandRegistryAccess commandRegistryAccess, CommandManager.RegistrationEnvironment registrationEnvironment) {
|
private void registerCommand(CommandDispatcher<CommandSourceStack> serverCommandSourceCommandDispatcher, CommandBuildContext commandRegistryAccess, Commands.CommandSelection registrationEnvironment) {
|
||||||
serverCommandSourceCommandDispatcher.register(
|
serverCommandSourceCommandDispatcher.register(
|
||||||
LiteralArgumentBuilder.<ServerCommandSource>literal("reco")
|
LiteralArgumentBuilder.<CommandSourceStack>literal("reco")
|
||||||
.requires(it -> it.isExecutedByPlayer() && COMMAND_RECO.hasPermission(it.getPlayer()))
|
.requires(it -> it.isPlayer() && COMMAND_RECO.hasPermission(it.getPlayer()))
|
||||||
.executes(this::onCleanReconnect)
|
.executes(this::onCleanReconnect)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int onCleanReconnect(CommandContext<ServerCommandSource> serverCommandSourceCommandContext) {
|
private int onCleanReconnect(CommandContext<CommandSourceStack> serverCommandSourceCommandContext) {
|
||||||
var player = serverCommandSourceCommandContext.getSource().getPlayer();
|
var player = serverCommandSourceCommandContext.getSource().getPlayer();
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!isVirtual(player.getUuid())) {
|
if (!isVirtual(player.getUUID())) {
|
||||||
player.sendMessage(Text.literal("你不在任何 \"房间\" 内。"));
|
player.sendSystemMessage(Component.literal("你不在任何 \"房间\" 内。"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var networkHandler = player.networkHandler;
|
var networkHandler = player.connection;
|
||||||
networkHandler.send(new StoreCookieS2CPacket(ROOM_COOKIE, EMPTY), PacketCallbacks.always(() -> {
|
networkHandler.send(new ClientboundStoreCookiePacket(ROOM_COOKIE, EMPTY), PacketSendListener.thenRun(() -> {
|
||||||
networkHandler.sendPacket(new ServerTransferS2CPacket(config.domain, serverSupplier.get().getServerPort()));
|
networkHandler.send(new ClientboundTransferPacket(config.domain, serverSupplier.get().getPort()));
|
||||||
}));
|
}));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enqueuePregen(RegistryKey<World> world, BlockPos spawnPos) {
|
public void enqueuePregen(ResourceKey<Level> world, BlockPos spawnPos) {
|
||||||
pregenQueue.add(new Pair<>(world, spawnPos));
|
pregenQueue.add(new Tuple<>(world, spawnPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID generateIdForRoom(GameProfile issuer, String name, Identifier room) {
|
public UUID generateIdForRoom(GameProfile issuer, String name, ResourceLocation room) {
|
||||||
var uuid = UUID.nameUUIDFromBytes((name + "@" + room.toString()).getBytes(StandardCharsets.UTF_8));
|
var uuid = UUID.nameUUIDFromBytes((name + "@" + room.toString()).getBytes(StandardCharsets.UTF_8));
|
||||||
var result = new UUID(uuid.getMostSignificantBits(), 0);
|
var result = new UUID(uuid.getMostSignificantBits(), 0);
|
||||||
if (issuer != null) uuidMapper.put(result, issuer);
|
if (issuer != null) uuidMapper.put(result, issuer);
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import io.ib67.sfcraft.config.SFConfig;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.minecraft.network.codec.PacketCodec;
|
import net.minecraft.network.codec.ByteBufCodecs;
|
||||||
import net.minecraft.network.codec.PacketCodecs;
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
|
||||||
import javax.crypto.SecretKeyFactory;
|
import javax.crypto.SecretKeyFactory;
|
||||||
@@ -63,12 +63,12 @@ public class SignatureService {
|
|||||||
long validUntil,
|
long validUntil,
|
||||||
byte[] data
|
byte[] data
|
||||||
) {
|
) {
|
||||||
public static final PacketCodec<ByteBuf, Signature> PACKET_CODEC = PacketCodec.tuple(
|
public static final StreamCodec<ByteBuf, Signature> PACKET_CODEC = StreamCodec.composite(
|
||||||
PacketCodecs.STRING, Signature::topic,
|
ByteBufCodecs.STRING_UTF8, Signature::topic,
|
||||||
PacketCodecs.STRING, Signature::issuer,
|
ByteBufCodecs.STRING_UTF8, Signature::issuer,
|
||||||
PacketCodecs.VAR_INT, Signature::permission,
|
ByteBufCodecs.VAR_INT, Signature::permission,
|
||||||
PacketCodecs.VAR_LONG, Signature::validUntil,
|
ByteBufCodecs.VAR_LONG, Signature::validUntil,
|
||||||
PacketCodecs.BYTE_ARRAY, Signature::data,
|
ByteBufCodecs.BYTE_ARRAY, Signature::data,
|
||||||
Signature::new
|
Signature::new
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -12,17 +12,10 @@ import io.ib67.sfcraft.inject.ConfigRoot;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.minecraft.component.DataComponentTypes;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.component.type.WrittenBookContentComponent;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.item.Items;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.text.ClickEvent;
|
|
||||||
import net.minecraft.text.RawFilteredPair;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -63,25 +56,25 @@ public class WelcomeModule extends ServerModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPlayerJoin(ServerPlayNetworkHandler serverPlayNetworkHandler, PacketSender
|
public void onPlayerJoin(ServerGamePacketListenerImpl serverPlayNetworkHandler, PacketSender
|
||||||
packetSender, MinecraftServer minecraftServer) {
|
packetSender, MinecraftServer minecraftServer) {
|
||||||
if (!isEnabled()) return;
|
if (!isEnabled()) return;
|
||||||
var player = serverPlayNetworkHandler.getPlayer();
|
var player = serverPlayNetworkHandler.getPlayer();
|
||||||
if (!player.getCommandTags().contains("sf_unlock_recipe")) {
|
if (!player.getTags().contains("sf_unlock_recipe")) {
|
||||||
player.addCommandTag("sf_unlock_recipe");
|
player.addTag("sf_unlock_recipe");
|
||||||
unlockRecipe(player);
|
unlockRecipe(player);
|
||||||
}
|
}
|
||||||
for (String s : announcements.keySet()) {
|
for (String s : announcements.keySet()) {
|
||||||
if (!player.getCommandTags().contains(s)) {
|
if (!player.getTags().contains(s)) {
|
||||||
player.addCommandTag(s);
|
player.addTag(s);
|
||||||
announcements.get(s).lines().map(Text::of).forEach(player::sendMessage);
|
announcements.get(s).lines().map(Component::nullToEmpty).forEach(player::sendSystemMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void unlockRecipe(ServerPlayerEntity player) {
|
private void unlockRecipe(ServerPlayer player) {
|
||||||
var recipe = player.getRecipeBook();
|
var recipe = player.getRecipeBook();
|
||||||
recipe.unlockRecipes(player.getServer().getRecipeManager().values(), player);
|
recipe.addRecipes(player.getServer().getRecipeManager().getRecipes(), player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
package io.ib67.sfcraft.module.chat;
|
package io.ib67.sfcraft.module.chat;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
public record ChatPrefix(
|
public record ChatPrefix(
|
||||||
Text prefix,
|
Component prefix,
|
||||||
String id,
|
String id,
|
||||||
boolean temporary,
|
boolean temporary,
|
||||||
int priority
|
int priority
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import io.ib67.sfcraft.ServerModule;
|
|||||||
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
||||||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.packet.Packet;
|
import net.minecraft.network.protocol.Packet;
|
||||||
import net.minecraft.network.packet.s2c.play.TeamS2CPacket;
|
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
|
||||||
import net.minecraft.scoreboard.Team;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.scores.PlayerTeam;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
//todo rework
|
//todo rework
|
||||||
@@ -21,8 +20,8 @@ public class ChatPrefixModule extends ServerModule {
|
|||||||
private MinecraftServerSupplier serverSupplier;
|
private MinecraftServerSupplier serverSupplier;
|
||||||
private volatile ChatPrefix empty;
|
private volatile ChatPrefix empty;
|
||||||
private final Map<UUID, SortedSet<ChatPrefix>> playerPrefixes = new HashMap<>();
|
private final Map<UUID, SortedSet<ChatPrefix>> playerPrefixes = new HashMap<>();
|
||||||
private final Map<String, Team> virtualTeams = new HashMap<>();
|
private final Map<String, PlayerTeam> virtualTeams = new HashMap<>();
|
||||||
private final Map<UUID, Team> players = new HashMap<>();
|
private final Map<UUID, PlayerTeam> players = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
@@ -33,7 +32,7 @@ public class ChatPrefixModule extends ServerModule {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
empty = new ChatPrefix(
|
empty = new ChatPrefix(
|
||||||
Text.empty(),
|
Component.empty(),
|
||||||
"EMPTY",
|
"EMPTY",
|
||||||
true,
|
true,
|
||||||
1000
|
1000
|
||||||
@@ -41,25 +40,25 @@ public class ChatPrefixModule extends ServerModule {
|
|||||||
virtualTeams.put(empty.id(), createTeamFrom(empty));
|
virtualTeams.put(empty.id(), createTeamFrom(empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDisconnect(ServerPlayNetworkHandler serverPlayNetworkHandler, MinecraftServer minecraftServer) {
|
private void onDisconnect(ServerGamePacketListenerImpl serverPlayNetworkHandler, MinecraftServer minecraftServer) {
|
||||||
var player = serverPlayNetworkHandler.getPlayer();
|
var player = serverPlayNetworkHandler.getPlayer();
|
||||||
var current = getCurrentPrefix(player);
|
var current = getCurrentPrefix(player);
|
||||||
if (current != null && current.temporary()) {
|
if (current != null && current.temporary()) {
|
||||||
removeFromTeam(player, players.get(player.getUuid()));
|
removeFromTeam(player, players.get(player.getUUID()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onJoin(ServerPlayNetworkHandler networkHandler, PacketSender sender, MinecraftServer minecraftServer) {
|
private void onJoin(ServerGamePacketListenerImpl networkHandler, PacketSender sender, MinecraftServer minecraftServer) {
|
||||||
applyPrefix(networkHandler.getPlayer(), empty);
|
applyPrefix(networkHandler.getPlayer(), empty);
|
||||||
for (Map.Entry<UUID, Team> uuidTeamEntry : players.entrySet()) {
|
for (Map.Entry<UUID, PlayerTeam> uuidTeamEntry : players.entrySet()) {
|
||||||
var team = uuidTeamEntry.getValue();
|
var team = uuidTeamEntry.getValue();
|
||||||
sender.sendPacket(TeamS2CPacket.updateTeam(team, true));
|
sender.sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPrefixUpdate(PlayerEntity player) {
|
private void onPrefixUpdate(Player player) {
|
||||||
var lastTeam = players.get(player.getUuid());
|
var lastTeam = players.get(player.getUUID());
|
||||||
var current = virtualTeams.get(playerPrefixes.get(player.getUuid()).getFirst().id());
|
var current = virtualTeams.get(playerPrefixes.get(player.getUUID()).getFirst().id());
|
||||||
if (lastTeam == current) return;
|
if (lastTeam == current) return;
|
||||||
if (lastTeam != null) removeFromTeam(player, lastTeam);
|
if (lastTeam != null) removeFromTeam(player, lastTeam);
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
@@ -68,49 +67,49 @@ public class ChatPrefixModule extends ServerModule {
|
|||||||
addToTeam(player, current);
|
addToTeam(player, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToTeam(PlayerEntity player, Team team) {
|
private void addToTeam(Player player, PlayerTeam team) {
|
||||||
var playerName = player.getName().getLiteralString();
|
var playerName = player.getName().tryCollapseToString();
|
||||||
if(team == null) return;
|
if(team == null) return;
|
||||||
team.getPlayerList().add(playerName);
|
team.getPlayers().add(playerName);
|
||||||
players.put(player.getUuid(), team);
|
players.put(player.getUUID(), team);
|
||||||
sendToAll(TeamS2CPacket.updateTeam(team, true));
|
sendToAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeFromTeam(PlayerEntity player, Team team) {
|
private void removeFromTeam(Player player, PlayerTeam team) {
|
||||||
var playerName = player.getName().getLiteralString();
|
var playerName = player.getName().tryCollapseToString();
|
||||||
if(team == null) return;
|
if(team == null) return;
|
||||||
team.getPlayerList().remove(playerName);
|
team.getPlayers().remove(playerName);
|
||||||
sendToAll(TeamS2CPacket.updateTeam(team, true));
|
sendToAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true));
|
||||||
var current = getCurrentPrefix(player);
|
var current = getCurrentPrefix(player);
|
||||||
var newTeam = virtualTeams.get(current.id());
|
var newTeam = virtualTeams.get(current.id());
|
||||||
addToTeam(player, newTeam);
|
addToTeam(player, newTeam);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendToAll(Packet<?> packet) {
|
private void sendToAll(Packet<?> packet) {
|
||||||
serverSupplier.get().getPlayerManager().sendToAll(packet);
|
serverSupplier.get().getPlayerList().broadcastAll(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyPrefix(PlayerEntity player, ChatPrefix prefix) {
|
public void applyPrefix(Player player, ChatPrefix prefix) {
|
||||||
if (hasPrefix(player.getUuid(), prefix)) {
|
if (hasPrefix(player.getUUID(), prefix)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
playerPrefixes.get(player.getUuid()).add(prefix);
|
playerPrefixes.get(player.getUUID()).add(prefix);
|
||||||
onPrefixUpdate(player);
|
onPrefixUpdate(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePrefix(PlayerEntity player, ChatPrefix prefix) {
|
public void removePrefix(Player player, ChatPrefix prefix) {
|
||||||
if (!hasPrefix(player.getUuid(), prefix)) {
|
if (!hasPrefix(player.getUUID(), prefix)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
playerPrefixes.get(player.getUuid()).remove(prefix);
|
playerPrefixes.get(player.getUUID()).remove(prefix);
|
||||||
onPrefixUpdate(player);
|
onPrefixUpdate(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatPrefix getCurrentPrefix(PlayerEntity player) {
|
public ChatPrefix getCurrentPrefix(Player player) {
|
||||||
if (!playerPrefixes.containsKey(player.getUuid())) {
|
if (!playerPrefixes.containsKey(player.getUUID())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return playerPrefixes.get(player.getUuid()).first();
|
return playerPrefixes.get(player.getUUID()).first();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,12 +120,12 @@ public class ChatPrefixModule extends ServerModule {
|
|||||||
return playerPrefixes.computeIfAbsent(player, ignored -> new TreeSet<>(List.of(empty))).contains(prefix);
|
return playerPrefixes.computeIfAbsent(player, ignored -> new TreeSet<>(List.of(empty))).contains(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Team createTeamFrom(ChatPrefix prefix) {
|
private PlayerTeam createTeamFrom(ChatPrefix prefix) {
|
||||||
var t = new Team(
|
var t = new PlayerTeam(
|
||||||
serverSupplier.get().getScoreboard(),
|
serverSupplier.get().getScoreboard(),
|
||||||
prefix.id()
|
prefix.id()
|
||||||
);
|
);
|
||||||
t.setPrefix(prefix.prefix());
|
t.setPlayerPrefix(prefix.prefix());
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,13 +5,6 @@ import io.ib67.sfcraft.ServerModule;
|
|||||||
import io.ib67.sfcraft.registry.chat.SimpleMessageDecorator;
|
import io.ib67.sfcraft.registry.chat.SimpleMessageDecorator;
|
||||||
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
||||||
import io.ib67.sfcraft.util.SFConsts;
|
import io.ib67.sfcraft.util.SFConsts;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.network.message.MessageDecorator;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.sound.SoundCategory;
|
|
||||||
import net.minecraft.sound.SoundEvents;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Colors;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -19,8 +12,15 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.MatchResult;
|
import java.util.regex.MatchResult;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import net.minecraft.network.chat.ChatDecorator;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.util.CommonColors;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
public class ChatPingModule extends ServerModule implements MessageDecorator {
|
public class ChatPingModule extends ServerModule implements ChatDecorator {
|
||||||
private static final Pattern PING = Pattern.compile("(@[\\w]+)?"); //todo remove the need of prefix
|
private static final Pattern PING = Pattern.compile("(@[\\w]+)?"); //todo remove the need of prefix
|
||||||
@Inject
|
@Inject
|
||||||
MinecraftServerSupplier serverSupplier;
|
MinecraftServerSupplier serverSupplier;
|
||||||
@@ -33,7 +33,7 @@ public class ChatPingModule extends ServerModule implements MessageDecorator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Text decorate(@Nullable ServerPlayerEntity sender, Text message) {
|
public Component decorate(@Nullable ServerPlayer sender, Component message) {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
@@ -42,20 +42,20 @@ public class ChatPingModule extends ServerModule implements MessageDecorator {
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var text = message.getLiteralString();
|
var text = message.tryCollapseToString();
|
||||||
if (text == null) return message;
|
if (text == null) return message;
|
||||||
var match = PING.matcher(text);
|
var match = PING.matcher(text);
|
||||||
if (!match.find()) return message;
|
if (!match.find()) return message;
|
||||||
var foundPlayers = new HashSet<PlayerEntity>();
|
var foundPlayers = new HashSet<Player>();
|
||||||
var names = List.of(serverSupplier.get().getPlayerNames());
|
var names = List.of(serverSupplier.get().getPlayerNames());
|
||||||
var r = Text.literal(match.replaceAll(it -> this.matchPlayer(it, names, foundPlayers)));
|
var r = Component.literal(match.replaceAll(it -> this.matchPlayer(it, names, foundPlayers)));
|
||||||
for (PlayerEntity foundPlayer : foundPlayers) {
|
for (Player foundPlayer : foundPlayers) {
|
||||||
if (sender != null) {
|
if (sender != null) {
|
||||||
foundPlayer.sendMessage(Text.literal(sender.getName().getLiteralString() + " 正在叫你。").withColor(Colors.LIGHT_GRAY), true);
|
foundPlayer.displayClientMessage(Component.literal(sender.getName().tryCollapseToString() + " 正在叫你。").withColor(CommonColors.LIGHT_GRAY), true);
|
||||||
}
|
}
|
||||||
foundPlayer.playSoundToPlayer(
|
foundPlayer.playNotifySound(
|
||||||
SoundEvents.ENTITY_ITEM_PICKUP,
|
SoundEvents.ITEM_PICKUP,
|
||||||
SoundCategory.PLAYERS,
|
SoundSource.PLAYERS,
|
||||||
0.8f,
|
0.8f,
|
||||||
0.5f
|
0.5f
|
||||||
);
|
);
|
||||||
@@ -63,14 +63,14 @@ public class ChatPingModule extends ServerModule implements MessageDecorator {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String matchPlayer(MatchResult match, List<String> playerNames, Set<PlayerEntity> foundPlayers) {
|
private String matchPlayer(MatchResult match, List<String> playerNames, Set<Player> foundPlayers) {
|
||||||
for (int i = 0; i < match.groupCount(); i++) {
|
for (int i = 0; i < match.groupCount(); i++) {
|
||||||
var r = match.group();
|
var r = match.group();
|
||||||
if (r.isEmpty()) continue;
|
if (r.isEmpty()) continue;
|
||||||
final var d = r.substring(1);
|
final var d = r.substring(1);
|
||||||
return playerNames.stream()
|
return playerNames.stream()
|
||||||
.filter(it -> it.toLowerCase().startsWith(d))
|
.filter(it -> it.toLowerCase().startsWith(d))
|
||||||
.peek(it -> foundPlayers.add(serverSupplier.get().getPlayerManager().getPlayer(it)))
|
.peek(it -> foundPlayers.add(serverSupplier.get().getPlayerList().getPlayerByName(it)))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(r);
|
.orElse(r);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ import io.ib67.sfcraft.ServerModule;
|
|||||||
import io.ib67.sfcraft.registry.chat.SimpleMessageDecorator;
|
import io.ib67.sfcraft.registry.chat.SimpleMessageDecorator;
|
||||||
import io.ib67.sfcraft.util.Helper;
|
import io.ib67.sfcraft.util.Helper;
|
||||||
import io.ib67.sfcraft.util.SFConsts;
|
import io.ib67.sfcraft.util.SFConsts;
|
||||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
import net.minecraft.network.chat.ChatDecorator;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
import net.minecraft.network.chat.ClickEvent;
|
||||||
import net.minecraft.network.message.MessageDecorator;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.text.ClickEvent;
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.effect.MobEffects;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.level.Level;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class ChatSendLocModule extends ServerModule implements MessageDecorator {
|
public class ChatSendLocModule extends ServerModule implements ChatDecorator {
|
||||||
@Inject
|
@Inject
|
||||||
SimpleMessageDecorator messageDecorator;
|
SimpleMessageDecorator messageDecorator;
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ public class ChatSendLocModule extends ServerModule implements MessageDecorator
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Text decorate(@Nullable ServerPlayerEntity sender, Text message) {
|
public Component decorate(@Nullable ServerPlayer sender, Component message) {
|
||||||
if (!isEnabled()) return message;
|
if (!isEnabled()) return message;
|
||||||
if (sender != null) {
|
if (sender != null) {
|
||||||
if (!SFConsts.USE_BROADCAST_LOCATION.hasPermission(sender)) {
|
if (!SFConsts.USE_BROADCAST_LOCATION.hasPermission(sender)) {
|
||||||
@@ -35,26 +35,26 @@ public class ChatSendLocModule extends ServerModule implements MessageDecorator
|
|||||||
return ReplaceHelper.replace(sender, message, ".xyz", ChatSendLocModule::generateLocText);
|
return ReplaceHelper.replace(sender, message, ".xyz", ChatSendLocModule::generateLocText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Text generateLocText(ServerPlayerEntity sender) {
|
private static Component generateLocText(ServerPlayer sender) {
|
||||||
if (sender == null) return Text.of(" (invalid position) ");
|
if (sender == null) return Component.nullToEmpty(" (invalid position) ");
|
||||||
sender.addStatusEffect(new StatusEffectInstance(StatusEffects.GLOWING, 15 * 20));
|
sender.addEffect(new MobEffectInstance(MobEffects.GLOWING, 15 * 20));
|
||||||
var x = sender.getBlockPos().getX();
|
var x = sender.blockPosition().getX();
|
||||||
var y = sender.getBlockPos().getY();
|
var y = sender.blockPosition().getY();
|
||||||
var z = sender.getBlockPos().getZ();
|
var z = sender.blockPosition().getZ();
|
||||||
var key = sender.getWorld().getRegistryKey();
|
var key = sender.level().dimension();
|
||||||
var world = translate(key);
|
var world = translate(key);
|
||||||
return Text
|
return Component
|
||||||
.literal(" " + x + ", " + y + ", " + z + world + " ")
|
.literal(" " + x + ", " + y + ", " + z + world + " ")
|
||||||
.withColor(Helper.fromRgb(63, 254, 254))
|
.withColor(Helper.fromRgb(63, 254, 254))
|
||||||
.styled(style -> style.withClickEvent(new ClickEvent.RunCommand("/gps " + key + " " + x + " " + y + " " + z)));
|
.withStyle(style -> style.withClickEvent(new ClickEvent.RunCommand("/gps " + key + " " + x + " " + y + " " + z)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String translate(RegistryKey<World> registryKey) {
|
private static String translate(ResourceKey<Level> registryKey) {
|
||||||
if (registryKey == World.END) {
|
if (registryKey == Level.END) {
|
||||||
return " (末地)";
|
return " (末地)";
|
||||||
} else if (registryKey == World.NETHER) {
|
} else if (registryKey == Level.NETHER) {
|
||||||
return " (地狱)";
|
return " (地狱)";
|
||||||
} else if (registryKey == World.OVERWORLD) {
|
} else if (registryKey == Level.OVERWORLD) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
return " (未知)";
|
return " (未知)";
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
package io.ib67.sfcraft.module.chat.decorator;
|
package io.ib67.sfcraft.module.chat.decorator;
|
||||||
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
class ReplaceHelper {
|
class ReplaceHelper {
|
||||||
|
|
||||||
public static Text replace(ServerPlayerEntity sender, Text message, String s, Function<ServerPlayerEntity, Text> generator) {
|
public static Component replace(ServerPlayer sender, Component message, String s, Function<ServerPlayer, Component> generator) {
|
||||||
var text = message.getLiteralString();
|
var text = message.tryCollapseToString();
|
||||||
if (text == null || text.isEmpty()) return message;
|
if (text == null || text.isEmpty()) return message;
|
||||||
text = text.trim();
|
text = text.trim();
|
||||||
var result = Text.literal("");
|
var result = Component.literal("");
|
||||||
var head = 0;
|
var head = 0;
|
||||||
var lowercase = text.toLowerCase(Locale.ROOT);
|
var lowercase = text.toLowerCase(Locale.ROOT);
|
||||||
var i = lowercase.indexOf(s);
|
var i = lowercase.indexOf(s);
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import io.ib67.sfcraft.util.SFConsts;
|
|||||||
import io.ib67.sfcraft.ServerModule;
|
import io.ib67.sfcraft.ServerModule;
|
||||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.commands.Commands;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.util.CommonColors;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
public class BackModule extends ServerModule {
|
public class BackModule extends ServerModule {
|
||||||
@Override
|
@Override
|
||||||
@@ -24,38 +24,38 @@ public class BackModule extends ServerModule {
|
|||||||
CommandRegistrationCallback.EVENT.register(this::registerCommands);
|
CommandRegistrationCallback.EVENT.register(this::registerCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment registrationEnvironment) {
|
private void registerCommands(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext registryAccess, Commands.CommandSelection registrationEnvironment) {
|
||||||
dispatcher.register(LiteralArgumentBuilder.<ServerCommandSource>literal("back")
|
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("back")
|
||||||
.requires(it -> this.isEnabled())
|
.requires(it -> this.isEnabled())
|
||||||
.requires(it -> it.getPlayer() != null)
|
.requires(it -> it.getPlayer() != null)
|
||||||
.requires(it -> it.getPlayer().getLastDeathPos().isPresent())
|
.requires(it -> it.getPlayer().getLastDeathLocation().isPresent())
|
||||||
.requires(it -> SFConsts.COMMAND_BACK.hasPermission(it.getPlayer()))
|
.requires(it -> SFConsts.COMMAND_BACK.hasPermission(it.getPlayer()))
|
||||||
.executes(this::onBack));
|
.executes(this::onBack));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int onBack(CommandContext<ServerCommandSource> it) {
|
public int onBack(CommandContext<CommandSourceStack> it) {
|
||||||
var player = it.getSource().getPlayer();
|
var player = it.getSource().getPlayer();
|
||||||
var pos = player.getLastDeathPos().get();
|
var pos = player.getLastDeathLocation().get();
|
||||||
var wld = player.getServer().getWorld(pos.dimension());
|
var wld = player.getServer().getLevel(pos.dimension());
|
||||||
var _pos = pos.pos();
|
var _pos = pos.pos();
|
||||||
if (wld == null) return 0;
|
if (wld == null) return 0;
|
||||||
var nearby = wld.getClosestPlayer(_pos.getX(), _pos.getY(), _pos.getZ(), 100, true);
|
var nearby = wld.getNearestPlayer(_pos.getX(), _pos.getY(), _pos.getZ(), 100, true);
|
||||||
if (nearby != null) {
|
if (nearby != null) {
|
||||||
_pos = nearby.getBlockPos();
|
_pos = nearby.blockPosition();
|
||||||
Helper.teleportSafely(player, wld, _pos.getX(), _pos.getY(), _pos.getZ(),0,0);
|
Helper.teleportSafely(player, wld, _pos.getX(), _pos.getY(), _pos.getZ(),0,0);
|
||||||
} else {
|
} else {
|
||||||
if (SFConsts.UNLIMITED_COMMAND_BACK.hasPermission(player)) {
|
if (SFConsts.UNLIMITED_COMMAND_BACK.hasPermission(player)) {
|
||||||
Helper.teleportSafely(player, wld, _pos.getX(), _pos.getY(), _pos.getZ(),0,0);
|
Helper.teleportSafely(player, wld, _pos.getX(), _pos.getY(), _pos.getZ(),0,0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
player.sendMessage(Text.of("周围没有玩家。").copy().withColor(Colors.RED));
|
player.sendSystemMessage(Component.nullToEmpty("周围没有玩家。").copy().withColor(CommonColors.RED));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPlayerDeath(PlayerEntity player, DamageSource damageSource) {
|
public void onPlayerDeath(Player player, DamageSource damageSource) {
|
||||||
if (this.isEnabled() && Helper.canBack((ServerPlayerEntity) player)) {
|
if (this.isEnabled() && Helper.canBack((ServerPlayer) player)) {
|
||||||
player.sendMessage(Text.of("Tip: 死亡地点附近有玩家,可以使用 /back 传送到他们那里。(即使在对方也死亡的状态下)"), false);
|
player.displayClientMessage(Component.nullToEmpty("Tip: 死亡地点附近有玩家,可以使用 /back 传送到他们那里。(即使在对方也死亡的状态下)"), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,15 +13,14 @@ import io.ib67.sfcraft.ServerModule;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.Commands;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.util.CommonColors;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Colors;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@@ -38,72 +37,72 @@ public class ManagementModule extends ServerModule {
|
|||||||
ServerPlayConnectionEvents.DISCONNECT.register(this::onDisconnect);
|
ServerPlayConnectionEvents.DISCONNECT.register(this::onDisconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDisconnect(ServerPlayNetworkHandler serverPlayNetworkHandler, MinecraftServer minecraftServer) {
|
private void onDisconnect(ServerGamePacketListenerImpl serverPlayNetworkHandler, MinecraftServer minecraftServer) {
|
||||||
serverPlayNetworkHandler.getPlayer().removeCommandTag(SFConsts.SPECIAL_SUDO);
|
serverPlayNetworkHandler.getPlayer().removeTag(SFConsts.SPECIAL_SUDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands(
|
private void registerCommands(
|
||||||
CommandDispatcher<ServerCommandSource> dispatcher,
|
CommandDispatcher<CommandSourceStack> dispatcher,
|
||||||
CommandRegistryAccess registryAccess,
|
CommandBuildContext registryAccess,
|
||||||
CommandManager.RegistrationEnvironment env) {
|
Commands.CommandSelection env) {
|
||||||
dispatcher.register(LiteralArgumentBuilder.<ServerCommandSource>literal("sudo")
|
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("sudo")
|
||||||
.requires(it -> this.isEnabled())
|
.requires(it -> this.isEnabled())
|
||||||
.requires(it -> it.hasPermissionLevel(2) && it.getPlayer() != null)
|
.requires(it -> it.hasPermission(2) && it.getPlayer() != null)
|
||||||
.executes(this::enterSudoMode)
|
.executes(this::enterSudoMode)
|
||||||
);
|
);
|
||||||
dispatcher.register(LiteralArgumentBuilder.<ServerCommandSource>literal("listperm")
|
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("listperm")
|
||||||
.requires(it -> this.isEnabled())
|
.requires(it -> this.isEnabled())
|
||||||
.requires(it -> it.hasPermissionLevel(2) || SFConsts.COMMAND_LISTPERM.hasPermission(it.getPlayer()))
|
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_LISTPERM.hasPermission(it.getPlayer()))
|
||||||
.executes(this::listPerms)
|
.executes(this::listPerms)
|
||||||
);
|
);
|
||||||
dispatcher.register(LiteralArgumentBuilder.<ServerCommandSource>literal("listgeo")
|
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("listgeo")
|
||||||
.requires(it -> this.isEnabled())
|
.requires(it -> this.isEnabled())
|
||||||
.requires(it -> it.hasPermissionLevel(2) || SFConsts.COMMAND_LISTGEO.hasPermission(it.getPlayer()))
|
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_LISTGEO.hasPermission(it.getPlayer()))
|
||||||
.executes(this::listGeo)
|
.executes(this::listGeo)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int listGeo(CommandContext<ServerCommandSource> ctx) {
|
private int listGeo(CommandContext<CommandSourceStack> ctx) {
|
||||||
var src = ctx.getSource();
|
var src = ctx.getSource();
|
||||||
var server = src.getServer();
|
var server = src.getServer();
|
||||||
src.sendMessage(Text.of("List of player with cities:"));
|
src.sendSystemMessage(Component.nullToEmpty("List of player with cities:"));
|
||||||
for (ServerPlayerEntity serverPlayerEntity : server.getPlayerManager().getPlayerList()) {
|
for (ServerPlayer serverPlayerEntity : server.getPlayerList().getPlayers()) {
|
||||||
try {
|
try {
|
||||||
var addr = InetAddress.getByName(serverPlayerEntity.getIp());
|
var addr = InetAddress.getByName(serverPlayerEntity.getIpAddress());
|
||||||
var city = geoIPService.cityOf(addr);
|
var city = geoIPService.cityOf(addr);
|
||||||
src.sendMessage(
|
src.sendSystemMessage(
|
||||||
Text.literal(" - ")
|
Component.literal(" - ")
|
||||||
.append(Text.literal("[" + city.getName() + "] ").withColor(Colors.BLUE))
|
.append(Component.literal("[" + city.getName() + "] ").withColor(CommonColors.BLUE))
|
||||||
.append(Text.literal(serverPlayerEntity.getName().getLiteralString()))
|
.append(Component.literal(serverPlayerEntity.getName().tryCollapseToString()))
|
||||||
.append(Text.literal(" (" + Helper.hideIp(addr) + ")").withColor(Colors.LIGHT_GRAY))
|
.append(Component.literal(" (" + Helper.hideIp(addr) + ")").withColor(CommonColors.LIGHT_GRAY))
|
||||||
);
|
);
|
||||||
} catch (GeoIp2Exception | UnknownHostException e) {
|
} catch (GeoIp2Exception | UnknownHostException e) {
|
||||||
src.sendMessage(Text.literal(" - [FAILED TO FETCH] " + serverPlayerEntity.getName().getLiteralString()).withColor(Colors.LIGHT_RED));
|
src.sendSystemMessage(Component.literal(" - [FAILED TO FETCH] " + serverPlayerEntity.getName().tryCollapseToString()).withColor(CommonColors.SOFT_RED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int enterSudoMode(CommandContext<ServerCommandSource> ctx) {
|
public int enterSudoMode(CommandContext<CommandSourceStack> ctx) {
|
||||||
var player = ctx.getSource().getPlayer();
|
var player = ctx.getSource().getPlayer();
|
||||||
if (player.getCommandTags().contains(SFConsts.SPECIAL_SUDO)) {
|
if (player.getTags().contains(SFConsts.SPECIAL_SUDO)) {
|
||||||
player.removeCommandTag(SFConsts.SPECIAL_SUDO);
|
player.removeTag(SFConsts.SPECIAL_SUDO);
|
||||||
player.sendMessage(Text.of("Sudo is off.").copy().withColor(Colors.GREEN));
|
player.sendSystemMessage(Component.nullToEmpty("Sudo is off.").copy().withColor(CommonColors.GREEN));
|
||||||
} else {
|
} else {
|
||||||
player.addCommandTag(SFConsts.SPECIAL_SUDO);
|
player.addTag(SFConsts.SPECIAL_SUDO);
|
||||||
player.sendMessage(Text.of("Sudo is on.").copy().withColor(Colors.GREEN));
|
player.sendSystemMessage(Component.nullToEmpty("Sudo is on.").copy().withColor(CommonColors.GREEN));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public int listPerms(CommandContext<ServerCommandSource> ctx) {
|
public int listPerms(CommandContext<CommandSourceStack> ctx) {
|
||||||
var src = ctx.getSource();
|
var src = ctx.getSource();
|
||||||
src.sendMessage(Text.of("Permissions: ").copy().withColor(Colors.GREEN));
|
src.sendSystemMessage(Component.nullToEmpty("Permissions: ").copy().withColor(CommonColors.GREEN));
|
||||||
for (Field declaredField : SFConsts.class.getDeclaredFields()) {
|
for (Field declaredField : SFConsts.class.getDeclaredFields()) {
|
||||||
if (Permission.class.isAssignableFrom(declaredField.getType())) {
|
if (Permission.class.isAssignableFrom(declaredField.getType())) {
|
||||||
var permission = (Permission<?>) declaredField.get(null);
|
var permission = (Permission<?>) declaredField.get(null);
|
||||||
src.sendMessage(Text.of(" - " + permission.key() + " " + (permission.byDefault() ? "(default)" : "")));
|
src.sendSystemMessage(Component.nullToEmpty(" - " + permission.key() + " " + (permission.byDefault() ? "(default)" : "")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+7
-8
@@ -2,24 +2,23 @@ package io.ib67.sfcraft.module.randomevt.longnight;
|
|||||||
|
|
||||||
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.util.CommonColors;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DawnAfterLongNightEvent extends RandomEvent {
|
public class DawnAfterLongNightEvent extends RandomEvent {
|
||||||
private final World world;
|
private final Level world;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int start() {
|
public int start() {
|
||||||
if (LongNightEvent.justExpirencedLongNight) {
|
if (LongNightEvent.justExpirencedLongNight) {
|
||||||
LongNightEvent.justExpirencedLongNight = false;
|
LongNightEvent.justExpirencedLongNight = false;
|
||||||
world.getServer().getPlayerManager().broadcast(
|
world.getServer().getPlayerList().broadcastSystemMessage(
|
||||||
Text.literal("\"月亮\"离开了。")
|
Component.literal("\"月亮\"离开了。")
|
||||||
.withColor(new Color(235, 91, 0).getRGB())
|
.withColor(new Color(235, 91, 0).getRGB())
|
||||||
.append(Text.literal("(永夜事件结束)").withColor(Colors.LIGHT_GRAY))
|
.append(Component.literal("(永夜事件结束)").withColor(CommonColors.LIGHT_GRAY))
|
||||||
, false);
|
, false);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ package io.ib67.sfcraft.module.randomevt.longnight;
|
|||||||
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.util.CommonColors;
|
||||||
import net.minecraft.world.GameRules;
|
import net.minecraft.world.level.GameRules;
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class LongNightEvent extends RandomEvent {
|
public class LongNightEvent extends RandomEvent {
|
||||||
@@ -15,20 +14,20 @@ public class LongNightEvent extends RandomEvent {
|
|||||||
static boolean isAtLongNight;
|
static boolean isAtLongNight;
|
||||||
@Getter
|
@Getter
|
||||||
private static int remainingTicks;
|
private static int remainingTicks;
|
||||||
private final ServerWorld world;
|
private final ServerLevel world;
|
||||||
private boolean doDaylightCycle;
|
private boolean doDaylightCycle;
|
||||||
private boolean doTraderSpawning;
|
private boolean doTraderSpawning;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int start() {
|
public int start() {
|
||||||
var pm = world.getServer().getPlayerManager();
|
var pm = world.getServer().getPlayerList();
|
||||||
isAtLongNight = true;
|
isAtLongNight = true;
|
||||||
pm.broadcast(Text.literal("月亮停滞在空中...").withColor(Colors.BLUE), false);
|
pm.broadcastSystemMessage(Component.literal("月亮停滞在空中...").withColor(CommonColors.BLUE), false);
|
||||||
this.doDaylightCycle = world.getGameRules().getBoolean(GameRules.DO_DAYLIGHT_CYCLE);
|
this.doDaylightCycle = world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT);
|
||||||
this.doTraderSpawning = world.getGameRules().getBoolean(GameRules.DO_TRADER_SPAWNING);
|
this.doTraderSpawning = world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING);
|
||||||
world.getGameRules().get(GameRules.DO_DAYLIGHT_CYCLE).set(false, world.getServer());
|
world.getGameRules().getRule(GameRules.RULE_DAYLIGHT).set(false, world.getServer());
|
||||||
world.getGameRules().get(GameRules.DO_TRADER_SPAWNING).set(false, world.getServer());
|
world.getGameRules().getRule(GameRules.RULE_DO_TRADER_SPAWNING).set(false, world.getServer());
|
||||||
remainingTicks = world.random.nextBetween(8400, 2 * 8400);
|
remainingTicks = world.random.nextIntBetweenInclusive(8400, 2 * 8400);
|
||||||
return remainingTicks;
|
return remainingTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,8 +41,8 @@ public class LongNightEvent extends RandomEvent {
|
|||||||
isAtLongNight = false;
|
isAtLongNight = false;
|
||||||
justExpirencedLongNight = true;
|
justExpirencedLongNight = true;
|
||||||
remainingTicks = 0;
|
remainingTicks = 0;
|
||||||
world.getGameRules().get(GameRules.DO_DAYLIGHT_CYCLE).set(doDaylightCycle, world.getServer());
|
world.getGameRules().getRule(GameRules.RULE_DAYLIGHT).set(doDaylightCycle, world.getServer());
|
||||||
world.getGameRules().get(GameRules.DO_TRADER_SPAWNING).set(doTraderSpawning, world.getServer());
|
world.getGameRules().getRule(GameRules.RULE_DO_TRADER_SPAWNING).set(doTraderSpawning, world.getServer());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isRunning() {
|
public static boolean isRunning() {
|
||||||
|
|||||||
@@ -23,21 +23,17 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
|||||||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.fabricmc.fabric.api.util.TriState;
|
import net.fabricmc.fabric.api.util.TriState;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.command.EntitySelector;
|
import net.minecraft.commands.Commands;
|
||||||
import net.minecraft.command.argument.EntityArgumentType;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.command.argument.GameModeArgumentType;
|
import net.minecraft.commands.arguments.EntityArgument;
|
||||||
import net.minecraft.network.packet.s2c.play.TeamS2CPacket;
|
import net.minecraft.commands.arguments.GameModeArgument;
|
||||||
import net.minecraft.scoreboard.Team;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.util.CommonColors;
|
||||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
import net.minecraft.world.level.GameType;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Colors;
|
|
||||||
import net.minecraft.world.GameMode;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -66,7 +62,7 @@ public class CreativeRoomModule extends ServerModule {
|
|||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
prefix = new ChatPrefix(
|
prefix = new ChatPrefix(
|
||||||
Text.literal("[PLAYGRD] ").withColor(Colors.LIGHT_YELLOW),
|
Component.literal("[PLAYGRD] ").withColor(CommonColors.SOFT_YELLOW),
|
||||||
"playgrd",
|
"playgrd",
|
||||||
true,
|
true,
|
||||||
20
|
20
|
||||||
@@ -81,10 +77,10 @@ public class CreativeRoomModule extends ServerModule {
|
|||||||
roomModule.enqueuePregen(CreativeSpaceRoom.WORLD, CreativeSpaceRoom.SPAWN_POS);
|
roomModule.enqueuePregen(CreativeSpaceRoom.WORLD, CreativeSpaceRoom.SPAWN_POS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull TriState onOtherCommands(@NotNull CommandSource commandSource, @NotNull String s) {
|
private @NotNull TriState onOtherCommands(@NotNull SharedSuggestionProvider commandSource, @NotNull String s) {
|
||||||
if (commandSource instanceof ServerCommandSource source && source.getPlayer() != null) {
|
if (commandSource instanceof CommandSourceStack source && source.getPlayer() != null) {
|
||||||
var p = source.getPlayer();
|
var p = source.getPlayer();
|
||||||
if (p.getWorld().getRegistryKey().equals(CreativeSpaceRoom.WORLD)) {
|
if (p.level().dimension().equals(CreativeSpaceRoom.WORLD)) {
|
||||||
if (BYPASS_PERMISSIONS.contains(s)) {
|
if (BYPASS_PERMISSIONS.contains(s)) {
|
||||||
return TriState.TRUE;
|
return TriState.TRUE;
|
||||||
}
|
}
|
||||||
@@ -93,10 +89,10 @@ public class CreativeRoomModule extends ServerModule {
|
|||||||
return TriState.DEFAULT;
|
return TriState.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull TriState onWorldEdit(@NotNull CommandSource commandSource, @NotNull String s) {
|
private @NotNull TriState onWorldEdit(@NotNull SharedSuggestionProvider commandSource, @NotNull String s) {
|
||||||
if (commandSource instanceof ServerCommandSource source && source.getPlayer() != null) {
|
if (commandSource instanceof CommandSourceStack source && source.getPlayer() != null) {
|
||||||
var p = source.getPlayer();
|
var p = source.getPlayer();
|
||||||
if (p.getWorld().getRegistryKey().equals(CreativeSpaceRoom.WORLD)) {
|
if (p.level().dimension().equals(CreativeSpaceRoom.WORLD)) {
|
||||||
if (s.startsWith("worldedit") && SFConsts.WORLDEDIT_AT_PLAYGROUND.hasPermission(p)) {
|
if (s.startsWith("worldedit") && SFConsts.WORLDEDIT_AT_PLAYGROUND.hasPermission(p)) {
|
||||||
return TriState.TRUE;
|
return TriState.TRUE;
|
||||||
}
|
}
|
||||||
@@ -105,89 +101,89 @@ public class CreativeRoomModule extends ServerModule {
|
|||||||
return TriState.DEFAULT;
|
return TriState.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher,
|
private void registerCommand(CommandDispatcher<CommandSourceStack> dispatcher,
|
||||||
CommandRegistryAccess registry, CommandManager.RegistrationEnvironment env) {
|
CommandBuildContext registry, Commands.CommandSelection env) {
|
||||||
dispatcher.register(
|
dispatcher.register(
|
||||||
LiteralArgumentBuilder.<ServerCommandSource>literal("playgrd")
|
LiteralArgumentBuilder.<CommandSourceStack>literal("playgrd")
|
||||||
.requires(it -> it.isExecutedByPlayer() && SFConsts.COMMAND_PLAYGROUND.hasPermission(it.getPlayer()))
|
.requires(it -> it.isPlayer() && SFConsts.COMMAND_PLAYGROUND.hasPermission(it.getPlayer()))
|
||||||
.executes(this::gotoPlayground)
|
.executes(this::gotoPlayground)
|
||||||
);
|
);
|
||||||
dispatcher.register(
|
dispatcher.register(
|
||||||
CommandManager.literal("gm")
|
Commands.literal("gm")
|
||||||
.then(CommandManager.argument("mode", GameModeArgumentType.gameMode())
|
.then(Commands.argument("mode", GameModeArgument.gameMode())
|
||||||
.requires(it -> it.isExecutedByPlayer() && SFConsts.COMMAND_PLAYGROUND_GAMEMODE.hasPermission(it.getPlayer()))
|
.requires(it -> it.isPlayer() && SFConsts.COMMAND_PLAYGROUND_GAMEMODE.hasPermission(it.getPlayer()))
|
||||||
.executes(this::onGameMode)
|
.executes(this::onGameMode)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
dispatcher.register(
|
dispatcher.register(
|
||||||
CommandManager.literal("pt")
|
Commands.literal("pt")
|
||||||
.then(CommandManager.argument("dest", EntityArgumentType.entity())
|
.then(Commands.argument("dest", EntityArgument.entity())
|
||||||
.requires(it -> it.isExecutedByPlayer() && SFConsts.COMMAND_PLAYGROUND_TELEPORT.hasPermission(it.getPlayer()))
|
.requires(it -> it.isPlayer() && SFConsts.COMMAND_PLAYGROUND_TELEPORT.hasPermission(it.getPlayer()))
|
||||||
.executes(this::onTeleport))
|
.executes(this::onTeleport))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int onTeleport(CommandContext<ServerCommandSource> ctx) throws CommandSyntaxException {
|
private int onTeleport(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
|
||||||
var src = ctx.getSource();
|
var src = ctx.getSource();
|
||||||
if (src instanceof ServerCommandSource source && source.getPlayer() != null) {
|
if (src instanceof CommandSourceStack source && source.getPlayer() != null) {
|
||||||
var p = source.getPlayer();
|
var p = source.getPlayer();
|
||||||
var dest = EntityArgumentType.getEntity(ctx, "dest");
|
var dest = EntityArgument.getEntity(ctx, "dest");
|
||||||
if (p.getWorld().getRegistryKey().equals(CreativeSpaceRoom.WORLD)) {
|
if (p.level().dimension().equals(CreativeSpaceRoom.WORLD)) {
|
||||||
if (dest.getWorld() == p.getWorld()) {
|
if (dest.level() == p.level()) {
|
||||||
Helper.teleportSafely(
|
Helper.teleportSafely(
|
||||||
p, p.getWorld(),
|
p, p.level(),
|
||||||
dest.getBlockX(), dest.getBlockY(), dest.getBlockZ(),
|
dest.getBlockX(), dest.getBlockY(), dest.getBlockZ(),
|
||||||
dest.getYaw(), dest.getPitch()
|
dest.getYRot(), dest.getXRot()
|
||||||
);
|
);
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.sendMessage(Text.of("You and target must be in playground!"));
|
p.sendSystemMessage(Component.nullToEmpty("You and target must be in playground!"));
|
||||||
}
|
}
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int onGameMode(CommandContext<ServerCommandSource> ctx) {
|
private int onGameMode(CommandContext<CommandSourceStack> ctx) {
|
||||||
var src = ctx.getSource();
|
var src = ctx.getSource();
|
||||||
if (src instanceof ServerCommandSource source && source.getPlayer() != null) {
|
if (src instanceof CommandSourceStack source && source.getPlayer() != null) {
|
||||||
var p = source.getPlayer();
|
var p = source.getPlayer();
|
||||||
var mode = ctx.getArgument("mode", GameMode.class);
|
var mode = ctx.getArgument("mode", GameType.class);
|
||||||
if (p.getWorld().getRegistryKey().equals(CreativeSpaceRoom.WORLD)) {
|
if (p.level().dimension().equals(CreativeSpaceRoom.WORLD)) {
|
||||||
p.changeGameMode(mode);
|
p.setGameMode(mode);
|
||||||
p.sendMessage(Text.of("Your gamemode has been changed to " + mode.asString()));
|
p.sendSystemMessage(Component.nullToEmpty("Your gamemode has been changed to " + mode.getSerializedName()));
|
||||||
} else {
|
} else {
|
||||||
p.sendMessage(Text.of("You can only use this in playground!"));
|
p.sendSystemMessage(Component.nullToEmpty("You can only use this in playground!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int gotoPlayground(CommandContext<ServerCommandSource> serverCommandSourceCommandContext) {
|
private int gotoPlayground(CommandContext<CommandSourceStack> serverCommandSourceCommandContext) {
|
||||||
var player = serverCommandSourceCommandContext.getSource().getPlayer();
|
var player = serverCommandSourceCommandContext.getSource().getPlayer();
|
||||||
try {
|
try {
|
||||||
teleporter.teleportTo(room, player);
|
teleporter.teleportTo(room, player);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
player.networkHandler.disconnect(Text.of(e.getMessage()));
|
player.connection.disconnect(Component.nullToEmpty(e.getMessage()));
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPlayerJoin(ServerPlayerEntity player) {
|
public void onPlayerJoin(ServerPlayer player) {
|
||||||
player.sendMessage(Text.of("你现在正在创造游乐园中,使用 //schem list 查看可用投影。"));
|
player.sendSystemMessage(Component.nullToEmpty("你现在正在创造游乐园中,使用 //schem list 查看可用投影。"));
|
||||||
player.sendMessage(Text.literal("以下功能现在可用:").withColor(Colors.WHITE)
|
player.sendSystemMessage(Component.literal("以下功能现在可用:").withColor(CommonColors.WHITE)
|
||||||
.append(Text.literal("/player /track /summon /setblock /gamerule 及 WorldEdit 的所有命令").withColor(Color.MAGENTA.getRGB()).append("。")));
|
.append(Component.literal("/player /track /summon /setblock /gamerule 及 WorldEdit 的所有命令").withColor(Color.MAGENTA.getRGB()).append("。")));
|
||||||
player.sendMessage(Text.of(" "));
|
player.sendSystemMessage(Component.nullToEmpty(" "));
|
||||||
player.sendMessage(Text.literal("如何上传投影到游乐场: ").withColor(Colors.GRAY)
|
player.sendSystemMessage(Component.literal("如何上传投影到游乐场: ").withColor(CommonColors.GRAY)
|
||||||
.append(Text.literal("https://github.com/saltedfishclub/sfcraft-schematics").withColor(Colors.GRAY).styled(it -> it.withUnderline(true))));
|
.append(Component.literal("https://github.com/saltedfishclub/sfcraft-schematics").withColor(CommonColors.GRAY).withStyle(it -> it.withUnderlined(true))));
|
||||||
player.sendMessage(Text.literal("游乐园中的生物不能逃逸到其他维度。").withColor(Colors.GRAY));
|
player.sendSystemMessage(Component.literal("游乐园中的生物不能逃逸到其他维度。").withColor(CommonColors.GRAY));
|
||||||
player.sendMessage(Text.literal("使用 /reco 或重新加入游戏即可离开。").withColor(Colors.GRAY));
|
player.sendSystemMessage(Component.literal("使用 /reco 或重新加入游戏即可离开。").withColor(CommonColors.GRAY));
|
||||||
player.changeGameMode(GameMode.CREATIVE);
|
player.setGameMode(GameType.CREATIVE);
|
||||||
|
|
||||||
chatPrefixModule.applyPrefix(player, prefix);
|
chatPrefixModule.applyPrefix(player, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPlayerQuit(ServerPlayerEntity player) {
|
public void onPlayerQuit(ServerPlayer player) {
|
||||||
chatPrefixModule.removePrefix(player, prefix);
|
chatPrefixModule.removePrefix(player, prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,14 +19,14 @@ import io.netty.buffer.Unpooled;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.Commands;
|
||||||
|
import net.minecraft.nbt.NbtAccounter;
|
||||||
import net.minecraft.nbt.NbtIo;
|
import net.minecraft.nbt.NbtIo;
|
||||||
import net.minecraft.nbt.NbtSizeTracker;
|
import net.minecraft.network.chat.ClickEvent;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.ClickEvent;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -55,22 +55,22 @@ public class SchematicUploader extends WebHandler {
|
|||||||
CommandRegistrationCallback.EVENT.register(this::registerCommand);
|
CommandRegistrationCallback.EVENT.register(this::registerCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registry, CommandManager.RegistrationEnvironment env) {
|
private void registerCommand(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext registry, Commands.CommandSelection env) {
|
||||||
dispatcher.register(CommandManager.literal("upload").then(
|
dispatcher.register(Commands.literal("upload").then(
|
||||||
CommandManager.literal("schematic")
|
Commands.literal("schematic")
|
||||||
.executes(this::onRequestSchematic)
|
.executes(this::onRequestSchematic)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int onRequestSchematic(CommandContext<ServerCommandSource> context) {
|
private int onRequestSchematic(CommandContext<CommandSourceStack> context) {
|
||||||
var source = context.getSource();
|
var source = context.getSource();
|
||||||
if (source.isExecutedByPlayer() && !SFConsts.COMMAND_UPLOAD_SCHEMATIC.hasPermission(source.getPlayer())) {
|
if (source.isPlayer() && !SFConsts.COMMAND_UPLOAD_SCHEMATIC.hasPermission(source.getPlayer())) {
|
||||||
source.sendMessage(Text.literal("你没有使用上传功能的权限!请联系管理员申请"));
|
source.sendSystemMessage(Component.literal("你没有使用上传功能的权限!请联系管理员申请"));
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
var url = generateSchematicUrl(source.isExecutedByPlayer() ? source.getPlayer().getName().getLiteralString() : "CONSOLE");
|
var url = generateSchematicUrl(source.isPlayer() ? source.getPlayer().getName().tryCollapseToString() : "CONSOLE");
|
||||||
source.sendMessage(Text.literal("Click this URL to upload schematic files.").withColor(Color.GREEN.getRGB()));
|
source.sendSystemMessage(Component.literal("Click this URL to upload schematic files.").withColor(Color.GREEN.getRGB()));
|
||||||
source.sendMessage(Text.literal(url).styled(it -> it.withClickEvent(new ClickEvent.OpenUrl(URI.create(url)))));
|
source.sendSystemMessage(Component.literal(url).withStyle(it -> it.withClickEvent(new ClickEvent.OpenUrl(URI.create(url)))));
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,14 +139,14 @@ public class SchematicUploader extends WebHandler {
|
|||||||
if (fileName.length() <= 10) return;
|
if (fileName.length() <= 10) return;
|
||||||
var baseFileName = Helper.cleanFileName(fileName.substring(0, fileName.length() - 10));
|
var baseFileName = Helper.cleanFileName(fileName.substring(0, fileName.length() - 10));
|
||||||
var sign = context.<SignatureService.Signature>attribute("sign");
|
var sign = context.<SignatureService.Signature>attribute("sign");
|
||||||
var player = serverSupplier.get().getPlayerManager().getPlayer(sign.issuer());
|
var player = serverSupplier.get().getPlayerList().getPlayerByName(sign.issuer());
|
||||||
log.info("Handling file {} from player {}", fileName, sign.issuer());
|
log.info("Handling file {} from player {}", fileName, sign.issuer());
|
||||||
if (fileName.endsWith(".schematic") || fileName.endsWith(".schem")) {
|
if (fileName.endsWith(".schematic") || fileName.endsWith(".schem")) {
|
||||||
Files.write(SCHEMATIC_DIR.resolve(baseFileName + ".schematic"), file.content().readAllBytes());
|
Files.write(SCHEMATIC_DIR.resolve(baseFileName + ".schematic"), file.content().readAllBytes());
|
||||||
log.info("Saved " + fileName + " as a schematic.");
|
log.info("Saved " + fileName + " as a schematic.");
|
||||||
sendSuccess(player, baseFileName);
|
sendSuccess(player, baseFileName);
|
||||||
} else if (fileName.endsWith(".litematic")) {
|
} else if (fileName.endsWith(".litematic")) {
|
||||||
try (var converter = new LitematicConverterV3(file.content(), new NbtSizeTracker(config.maxSchematicSize, 64))) {
|
try (var converter = new LitematicConverterV3(file.content(), new NbtAccounter(config.maxSchematicSize, 64))) {
|
||||||
converter.read((name, nbt) -> {
|
converter.read((name, nbt) -> {
|
||||||
name = baseFileName + "-" + Helper.cleanFileName(name) + ".schematic";
|
name = baseFileName + "-" + Helper.cleanFileName(name) + ".schematic";
|
||||||
try {
|
try {
|
||||||
@@ -169,12 +169,12 @@ public class SchematicUploader extends WebHandler {
|
|||||||
context.result("Uploaded!");
|
context.result("Uploaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendSuccess(ServerPlayerEntity player, String fileName) {
|
private static void sendSuccess(ServerPlayer player, String fileName) {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.sendMessage(Text.literal("Schematic " + fileName + " has been saved! Use //schem list to find it").withColor(Color.GREEN.getRGB()));
|
player.sendSystemMessage(Component.literal("Schematic " + fileName + " has been saved! Use //schem list to find it").withColor(Color.GREEN.getRGB()));
|
||||||
player.sendMessage(Text.literal("Or you can click this").styled(it -> it.withUnderline(true).withClickEvent(
|
player.sendSystemMessage(Component.literal("Or you can click this").withStyle(it -> it.withUnderlined(true).withClickEvent(
|
||||||
new ClickEvent.SuggestCommand("//schem load " + fileName)
|
new ClickEvent.SuggestCommand("//schem load " + fileName)
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ package io.ib67.sfcraft.registry;
|
|||||||
|
|
||||||
import io.ib67.sfcraft.module.randomevt.ActiveEvent;
|
import io.ib67.sfcraft.module.randomevt.ActiveEvent;
|
||||||
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
||||||
import net.minecraft.registry.RegistryKey;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public interface RandomEventRegistry {
|
public interface RandomEventRegistry {
|
||||||
List<ActiveEvent> getActiveEvents();
|
List<ActiveEvent> getActiveEvents();
|
||||||
|
|
||||||
void registerEvent(Function<World, RandomEvent> event, RegistryKey<World> world, Predicate<World> worldTickPredicate);
|
void registerEvent(Function<Level, RandomEvent> event, ResourceKey<Level> world, Predicate<Level> worldTickPredicate);
|
||||||
}
|
}
|
||||||
@@ -3,24 +3,23 @@ package io.ib67.sfcraft.registry;
|
|||||||
import io.ib67.sfcraft.subserver.Room;
|
import io.ib67.sfcraft.subserver.Room;
|
||||||
import io.ib67.sfcraft.subserver.RoomFactory;
|
import io.ib67.sfcraft.subserver.RoomFactory;
|
||||||
import io.ib67.sfcraft.subserver.RoomSession;
|
import io.ib67.sfcraft.subserver.RoomSession;
|
||||||
import net.minecraft.registry.RegistryKey;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public interface RoomRegistry {
|
public interface RoomRegistry {
|
||||||
Collection<? extends Room> getRooms();
|
Collection<? extends Room> getRooms();
|
||||||
|
|
||||||
Room getRoomBy(Identifier identifier);
|
Room getRoomBy(ResourceLocation identifier);
|
||||||
|
|
||||||
RoomSession getRoomBy(UUID player);
|
RoomSession getRoomBy(UUID player);
|
||||||
|
|
||||||
<T extends Room> T createRoomOf(Class<T> type, Identifier roomId, ServerPlayerEntity issuer, String... arguments);
|
<T extends Room> T createRoomOf(Class<T> type, ResourceLocation roomId, ServerPlayer issuer, String... arguments);
|
||||||
|
|
||||||
boolean isRoomWorld(RegistryKey<World> world);
|
boolean isRoomWorld(ResourceKey<Level> world);
|
||||||
|
|
||||||
<T extends Room> void registerRoomType(Class<T> type, RegistryKey<World> worldKey, RoomFactory<T> factory);
|
<T extends Room> void registerRoomType(Class<T> type, ResourceKey<Level> worldKey, RoomFactory<T> factory);
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
package io.ib67.sfcraft.registry.chat;
|
package io.ib67.sfcraft.registry.chat;
|
||||||
|
|
||||||
import net.minecraft.network.message.MessageDecorator;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import net.minecraft.network.chat.ChatDecorator;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
public class SimpleMessageDecorator implements MessageDecorator {
|
public class SimpleMessageDecorator implements ChatDecorator {
|
||||||
protected final List<MessageDecorator> decorators = new ArrayList<>();
|
protected final List<ChatDecorator> decorators = new ArrayList<>();
|
||||||
|
|
||||||
protected SimpleMessageDecorator() {
|
protected SimpleMessageDecorator() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerDecorator(MessageDecorator decorator) {
|
public void registerDecorator(ChatDecorator decorator) {
|
||||||
decorators.add(decorator);
|
decorators.add(decorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Text decorate(@Nullable ServerPlayerEntity sender, Text message) {
|
public Component decorate(@Nullable ServerPlayer sender, Component message) {
|
||||||
var targets = new ArrayList<Text>();
|
var targets = new ArrayList<Component>();
|
||||||
targets.add(message);
|
targets.add(message);
|
||||||
for (MessageDecorator decorator : decorators) {
|
for (ChatDecorator decorator : decorators) {
|
||||||
var newRd = new ArrayList<Text>();
|
var newRd = new ArrayList<Component>();
|
||||||
for (Text target : targets) {
|
for (Component target : targets) {
|
||||||
var r = decorator.decorate(sender, target);
|
var r = decorator.decorate(sender, target);
|
||||||
var copy = r.copy();
|
var copy = r.copy();
|
||||||
copy.getSiblings().clear();
|
copy.getSiblings().clear();
|
||||||
@@ -34,7 +34,7 @@ public class SimpleMessageDecorator implements MessageDecorator {
|
|||||||
}
|
}
|
||||||
targets = newRd;
|
targets = newRd;
|
||||||
}
|
}
|
||||||
var result = Text.empty();
|
var result = Component.empty();
|
||||||
targets.forEach(result::append);
|
targets.forEach(result::append);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import lombok.Getter;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -35,15 +34,15 @@ public class SimpleRandomEventRegistry implements RandomEventRegistry {
|
|||||||
activeEvents.clear();
|
activeEvents.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void afterWorldTick(ServerWorld serverWorld) {
|
private void afterWorldTick(ServerLevel serverWorld) {
|
||||||
if (shutdown) return;
|
if (shutdown) return;
|
||||||
triggerEvents(serverWorld);
|
triggerEvents(serverWorld);
|
||||||
clearActiveEvents();
|
clearActiveEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void triggerEvents(ServerWorld serverWorld) {
|
private void triggerEvents(ServerLevel serverWorld) {
|
||||||
for (RegisteredEntry entry : entries) {
|
for (RegisteredEntry entry : entries) {
|
||||||
if (entry.world == serverWorld.getRegistryKey()
|
if (entry.world == serverWorld.dimension()
|
||||||
&& !entry.started && entry.worldTickPredicate.test(serverWorld)) {
|
&& !entry.started && entry.worldTickPredicate.test(serverWorld)) {
|
||||||
var event = entry.event.apply(serverWorld);
|
var event = entry.event.apply(serverWorld);
|
||||||
var ticks = event.start();
|
var ticks = event.start();
|
||||||
@@ -74,7 +73,7 @@ public class SimpleRandomEventRegistry implements RandomEventRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerEvent(Function<World, RandomEvent> event, RegistryKey<World> world, Predicate<World> worldTickPredicate) {
|
public void registerEvent(Function<Level, RandomEvent> event, ResourceKey<Level> world, Predicate<Level> worldTickPredicate) {
|
||||||
entries.add(new RegisteredEntry(world, event, worldTickPredicate));
|
entries.add(new RegisteredEntry(world, event, worldTickPredicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,9 +93,9 @@ public class SimpleRandomEventRegistry implements RandomEventRegistry {
|
|||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
private static final class RegisteredEntry {
|
private static final class RegisteredEntry {
|
||||||
private final RegistryKey<World> world;
|
private final ResourceKey<Level> world;
|
||||||
private final Function<World, RandomEvent> event;
|
private final Function<Level, RandomEvent> event;
|
||||||
private final Predicate<World> worldTickPredicate;
|
private final Predicate<Level> worldTickPredicate;
|
||||||
private boolean started;
|
private boolean started;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,21 +4,20 @@ import io.ib67.sfcraft.registry.RoomRegistry;
|
|||||||
import io.ib67.sfcraft.subserver.Room;
|
import io.ib67.sfcraft.subserver.Room;
|
||||||
import io.ib67.sfcraft.subserver.RoomFactory;
|
import io.ib67.sfcraft.subserver.RoomFactory;
|
||||||
import io.ib67.sfcraft.subserver.RoomSession;
|
import io.ib67.sfcraft.subserver.RoomSession;
|
||||||
import net.minecraft.registry.RegistryKey;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class SimpleRoomRegistry implements RoomRegistry {
|
public class SimpleRoomRegistry implements RoomRegistry {
|
||||||
private final ConcurrentMap<Identifier, Room> rooms = new ConcurrentHashMap<>();
|
private final ConcurrentMap<ResourceLocation, Room> rooms = new ConcurrentHashMap<>();
|
||||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
private final Map<Class<?>, RoomFactory<?>> factories = new HashMap<>();
|
private final Map<Class<?>, RoomFactory<?>> factories = new HashMap<>();
|
||||||
private final Set<RegistryKey<World>> roomWorlds = new HashSet<>();
|
private final Set<ResourceKey<Level>> roomWorlds = new HashSet<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends Room> getRooms() {
|
public Collection<? extends Room> getRooms() {
|
||||||
@@ -26,7 +25,7 @@ public class SimpleRoomRegistry implements RoomRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Room getRoomBy(Identifier identifier) {
|
public Room getRoomBy(ResourceLocation identifier) {
|
||||||
return rooms.get(identifier);
|
return rooms.get(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ public class SimpleRoomRegistry implements RoomRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Room> T createRoomOf(Class<T> type, Identifier roomId, ServerPlayerEntity issuer, String... arguments) {
|
public <T extends Room> T createRoomOf(Class<T> type, ResourceLocation roomId, ServerPlayer issuer, String... arguments) {
|
||||||
if (getRoomBy(roomId) != null) {
|
if (getRoomBy(roomId) != null) {
|
||||||
throw new IllegalArgumentException("duplicate room id: " + roomId);
|
throw new IllegalArgumentException("duplicate room id: " + roomId);
|
||||||
}
|
}
|
||||||
@@ -59,12 +58,12 @@ public class SimpleRoomRegistry implements RoomRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRoomWorld(RegistryKey<World> world) {
|
public boolean isRoomWorld(ResourceKey<Level> world) {
|
||||||
return roomWorlds.contains(world);
|
return roomWorlds.contains(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Room> void registerRoomType(Class<T> type, RegistryKey<World> worldKey, RoomFactory<T> factory) {
|
public <T extends Room> void registerRoomType(Class<T> type, ResourceKey<Level> worldKey, RoomFactory<T> factory) {
|
||||||
roomWorlds.add(worldKey);
|
roomWorlds.add(worldKey);
|
||||||
factories.put(type, factory);
|
factories.put(type, factory);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,23 +2,21 @@ package io.ib67.sfcraft.room;
|
|||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.network.codec.PacketCodec;
|
|
||||||
import net.minecraft.network.codec.PacketCodecs;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.Uuids;
|
|
||||||
import net.minecraft.util.dynamic.Codecs;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.minecraft.core.UUIDUtil;
|
||||||
|
import net.minecraft.network.codec.ByteBufCodecs;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public record RequestedRoom(
|
public record RequestedRoom(
|
||||||
Identifier identifier,
|
ResourceLocation identifier,
|
||||||
String profileName,
|
String profileName,
|
||||||
UUID profileUuid
|
UUID profileUuid
|
||||||
) {
|
) {
|
||||||
public static final PacketCodec<ByteBuf, RequestedRoom> PACKET_CODEC = PacketCodec.tuple(
|
public static final StreamCodec<ByteBuf, RequestedRoom> PACKET_CODEC = StreamCodec.composite(
|
||||||
Identifier.PACKET_CODEC, RequestedRoom::identifier,
|
ResourceLocation.STREAM_CODEC, RequestedRoom::identifier,
|
||||||
PacketCodecs.STRING, RequestedRoom::profileName,
|
ByteBufCodecs.STRING_UTF8, RequestedRoom::profileName,
|
||||||
Uuids.PACKET_CODEC, RequestedRoom::profileUuid,
|
UUIDUtil.STREAM_CODEC, RequestedRoom::profileUuid,
|
||||||
RequestedRoom::new
|
RequestedRoom::new
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -9,13 +9,13 @@ import io.ib67.sfcraft.module.SignatureService;
|
|||||||
import io.ib67.sfcraft.registry.RoomRegistry;
|
import io.ib67.sfcraft.registry.RoomRegistry;
|
||||||
import io.ib67.sfcraft.subserver.Room;
|
import io.ib67.sfcraft.subserver.Room;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import net.minecraft.network.PacketCallbacks;
|
import net.minecraft.network.PacketSendListener;
|
||||||
import net.minecraft.network.packet.s2c.common.ServerTransferS2CPacket;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.packet.s2c.common.StoreCookieS2CPacket;
|
import net.minecraft.network.protocol.common.ClientboundStoreCookiePacket;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.network.protocol.common.ClientboundTransferPacket;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.CommonColors;
|
||||||
|
|
||||||
public class RoomTeleporter {
|
public class RoomTeleporter {
|
||||||
@Inject
|
@Inject
|
||||||
@@ -29,21 +29,21 @@ public class RoomTeleporter {
|
|||||||
@Inject
|
@Inject
|
||||||
private SFConfig config;
|
private SFConfig config;
|
||||||
|
|
||||||
public static final Identifier ROOM_COOKIE = Identifier.of(SFCraft.MOD_ID, "room");
|
public static final ResourceLocation ROOM_COOKIE = ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "room");
|
||||||
|
|
||||||
public void teleportTo(Room room, ServerPlayerEntity player) {
|
public void teleportTo(Room room, ServerPlayer player) {
|
||||||
if (roomModule.isVirtual(player.getUuid())) {
|
if (roomModule.isVirtual(player.getUUID())) {
|
||||||
player.sendMessage(Text.literal("您已经在某个房间里了").withColor(Colors.LIGHT_RED));
|
player.sendSystemMessage(Component.literal("您已经在某个房间里了").withColor(CommonColors.SOFT_RED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var finalUuid = roomModule.generateIdForRoom(player.getGameProfile(), player.getName().getLiteralString(), room.getServerIdentifier());
|
var finalUuid = roomModule.generateIdForRoom(player.getGameProfile(), player.getName().tryCollapseToString(), room.getServerIdentifier());
|
||||||
var sess = room.getPlayerManager().createSessionFor(finalUuid);
|
var sess = room.getPlayerManager().createSessionFor(finalUuid);
|
||||||
var name = player.getName().getLiteralString();
|
var name = player.getName().tryCollapseToString();
|
||||||
if (player.getServer().getWorld(sess.getSpawnPosition().dimension()) == null) {
|
if (player.getServer().getLevel(sess.getSpawnPosition().dimension()) == null) {
|
||||||
throw new IllegalStateException("world isn't exist");
|
throw new IllegalStateException("world isn't exist");
|
||||||
}
|
}
|
||||||
var networkHandler = player.networkHandler;
|
var networkHandler = player.connection;
|
||||||
networkHandler.reconfigure();
|
networkHandler.switchToConfig();
|
||||||
var request = new RequestedRoom(room.getServerIdentifier(), name, finalUuid);
|
var request = new RequestedRoom(room.getServerIdentifier(), name, finalUuid);
|
||||||
var requestBuf = Unpooled.buffer();
|
var requestBuf = Unpooled.buffer();
|
||||||
RequestedRoom.PACKET_CODEC.encode(requestBuf, request);
|
RequestedRoom.PACKET_CODEC.encode(requestBuf, request);
|
||||||
@@ -56,8 +56,8 @@ public class RoomTeleporter {
|
|||||||
requestBuf.array()
|
requestBuf.array()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
networkHandler.send(new StoreCookieS2CPacket(ROOM_COOKIE, cookie), PacketCallbacks.always(() -> {
|
networkHandler.send(new ClientboundStoreCookiePacket(ROOM_COOKIE, cookie), PacketSendListener.thenRun(() -> {
|
||||||
networkHandler.sendPacket(new ServerTransferS2CPacket(config.domain, config.port));
|
networkHandler.send(new ClientboundTransferPacket(config.domain, config.port));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,8 @@ import io.ib67.sfcraft.subserver.RoomSession;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.core.GlobalPos;
|
||||||
import net.minecraft.util.math.GlobalPos;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public abstract class SimpleRoomPlayerManager implements RoomPlayerManager {
|
public abstract class SimpleRoomPlayerManager implements RoomPlayerManager {
|
||||||
@@ -20,7 +19,7 @@ public abstract class SimpleRoomPlayerManager implements RoomPlayerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ServerPlayerEntity> getJoinedPlayers() {
|
public List<ServerPlayer> getJoinedPlayers() {
|
||||||
return onlinePlayers.values().stream().map(it -> it.player).toList();
|
return onlinePlayers.values().stream().map(it -> it.player).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +48,7 @@ public abstract class SimpleRoomPlayerManager implements RoomPlayerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerPlayerEntity getPlayer(UUID uuid) {
|
public ServerPlayer getPlayer(UUID uuid) {
|
||||||
return onlinePlayers.get(uuid).getPlayer();
|
return onlinePlayers.get(uuid).getPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,14 +71,14 @@ public abstract class SimpleRoomPlayerManager implements RoomPlayerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerJoin(ServerPlayerEntity player) {
|
public void onPlayerJoin(ServerPlayer player) {
|
||||||
onlinePlayers.get(player.getUuid()).setPlayer(player);
|
onlinePlayers.get(player.getUUID()).setPlayer(player);
|
||||||
session.onPlayerJoin(player);
|
session.onPlayerJoin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerQuit(ServerPlayerEntity player) {
|
public void onPlayerQuit(ServerPlayer player) {
|
||||||
onlinePlayers.remove(player.getUuid());
|
onlinePlayers.remove(player.getUUID());
|
||||||
session.onPlayerQuit(player);
|
session.onPlayerQuit(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,7 +86,7 @@ public abstract class SimpleRoomPlayerManager implements RoomPlayerManager {
|
|||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
class PlayerEntry {
|
class PlayerEntry {
|
||||||
private ServerPlayerEntity player;
|
private ServerPlayer player;
|
||||||
private RoomSession session;
|
private RoomSession session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,14 +3,9 @@ package io.ib67.sfcraft.room.create;
|
|||||||
import io.ib67.sfcraft.module.room.CreativeRoomModule;
|
import io.ib67.sfcraft.module.room.CreativeRoomModule;
|
||||||
import io.ib67.sfcraft.subserver.Room;
|
import io.ib67.sfcraft.subserver.Room;
|
||||||
import io.ib67.sfcraft.subserver.RoomSession;
|
import io.ib67.sfcraft.subserver.RoomSession;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Colors;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.GlobalPos;
|
|
||||||
import net.minecraft.world.GameMode;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.minecraft.core.GlobalPos;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
public class CreativePlayerSession extends RoomSession {
|
public class CreativePlayerSession extends RoomSession {
|
||||||
private final GlobalPos spawn;
|
private final GlobalPos spawn;
|
||||||
@@ -26,7 +21,7 @@ public class CreativePlayerSession extends RoomSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerJoin(ServerPlayerEntity player) {
|
public void onPlayerJoin(ServerPlayer player) {
|
||||||
module.onPlayerJoin(player);
|
module.onPlayerJoin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +36,7 @@ public class CreativePlayerSession extends RoomSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerQuit(ServerPlayerEntity player) {
|
public void onPlayerQuit(ServerPlayer player) {
|
||||||
module.onPlayerQuit(player);
|
module.onPlayerQuit(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,14 @@ package io.ib67.sfcraft.room.create;
|
|||||||
|
|
||||||
import io.ib67.sfcraft.subserver.RoomFactory;
|
import io.ib67.sfcraft.subserver.RoomFactory;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CreativeSpaceFactory implements RoomFactory<CreativeSpaceRoom> {
|
public class CreativeSpaceFactory implements RoomFactory<CreativeSpaceRoom> {
|
||||||
private final CreativeSpaceRoom room;
|
private final CreativeSpaceRoom room;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreativeSpaceRoom create(ServerPlayerEntity issuer, String[] arguments) {
|
public CreativeSpaceRoom create(ServerPlayer issuer, String[] arguments) {
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,17 +5,17 @@ import io.ib67.sfcraft.module.room.CreativeRoomModule;
|
|||||||
import io.ib67.sfcraft.subserver.Room;
|
import io.ib67.sfcraft.subserver.Room;
|
||||||
import io.ib67.sfcraft.subserver.RoomPlayerManager;
|
import io.ib67.sfcraft.subserver.RoomPlayerManager;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.registry.RegistryKeys;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class CreativeSpaceRoom implements Room {
|
public class CreativeSpaceRoom implements Room {
|
||||||
public static final RegistryKey<World> WORLD = RegistryKey.of(RegistryKeys.WORLD, Identifier.of(SFCraft.MOD_ID, "playground"));
|
public static final ResourceKey<Level> WORLD = ResourceKey.create(Registries.DIMENSION, ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "playground"));
|
||||||
public static final Identifier IDENTIFIER = Identifier.of(SFCraft.MOD_ID, "creative_space");
|
public static final ResourceLocation IDENTIFIER = ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "creative_space");
|
||||||
public static final BlockPos SPAWN_POS = new BlockPos(0, 66, 0);
|
public static final BlockPos SPAWN_POS = new BlockPos(0, 66, 0);
|
||||||
@Getter
|
@Getter
|
||||||
private final RoomPlayerManager playerManager;
|
private final RoomPlayerManager playerManager;
|
||||||
@@ -26,13 +26,13 @@ public class CreativeSpaceRoom implements Room {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
for (ServerPlayerEntity joinedPlayer : playerManager.getJoinedPlayers()) {
|
for (ServerPlayer joinedPlayer : playerManager.getJoinedPlayers()) {
|
||||||
joinedPlayer.networkHandler.disconnect(Text.of("Room is shutting down"));
|
joinedPlayer.connection.disconnect(Component.nullToEmpty("Room is shutting down"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier getServerIdentifier() {
|
public ResourceLocation getServerIdentifier() {
|
||||||
return IDENTIFIER;
|
return IDENTIFIER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
package io.ib67.sfcraft.subserver;
|
package io.ib67.sfcraft.subserver;
|
||||||
|
|
||||||
import net.minecraft.network.packet.s2c.common.StoreCookieS2CPacket;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.math.GlobalPos;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public interface Room {
|
public interface Room {
|
||||||
Identifier getServerIdentifier();
|
ResourceLocation getServerIdentifier();
|
||||||
|
|
||||||
RoomPlayerManager getPlayerManager();
|
RoomPlayerManager getPlayerManager();
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package io.ib67.sfcraft.subserver;
|
package io.ib67.sfcraft.subserver;
|
||||||
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface RoomFactory<T extends Room> {
|
public interface RoomFactory<T extends Room> {
|
||||||
T create(ServerPlayerEntity issuer, String[] arguments);
|
T create(ServerPlayer issuer, String[] arguments);
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
package io.ib67.sfcraft.subserver;
|
package io.ib67.sfcraft.subserver;
|
||||||
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
public interface RoomPlayerManager {
|
public interface RoomPlayerManager {
|
||||||
List<ServerPlayerEntity> getJoinedPlayers();
|
List<ServerPlayer> getJoinedPlayers();
|
||||||
|
|
||||||
List<RoomSession> getSessions();
|
List<RoomSession> getSessions();
|
||||||
|
|
||||||
@@ -14,5 +13,5 @@ public interface RoomPlayerManager {
|
|||||||
|
|
||||||
RoomSession getSessionBy(UUID uuid);
|
RoomSession getSessionBy(UUID uuid);
|
||||||
|
|
||||||
ServerPlayerEntity getPlayer(UUID uuid);
|
ServerPlayer getPlayer(UUID uuid);
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package io.ib67.sfcraft.subserver;
|
package io.ib67.sfcraft.subserver;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.core.GlobalPos;
|
||||||
import net.minecraft.util.math.GlobalPos;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class RoomSession {
|
public abstract class RoomSession {
|
||||||
@@ -18,7 +17,7 @@ public abstract class RoomSession {
|
|||||||
|
|
||||||
public abstract void onPlayerLogin(UUID uuid);
|
public abstract void onPlayerLogin(UUID uuid);
|
||||||
|
|
||||||
public abstract void onPlayerJoin(ServerPlayerEntity player);
|
public abstract void onPlayerJoin(ServerPlayer player);
|
||||||
|
|
||||||
public abstract void onPlayerQuit(ServerPlayerEntity player);
|
public abstract void onPlayerQuit(ServerPlayer player);
|
||||||
}
|
}
|
||||||
@@ -8,24 +8,17 @@ import io.ib67.sfcraft.SFCraft;
|
|||||||
import io.ib67.sfcraft.config.SFConfig;
|
import io.ib67.sfcraft.config.SFConfig;
|
||||||
import io.ib67.sfcraft.geoip.GeoIPService;
|
import io.ib67.sfcraft.geoip.GeoIPService;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.block.CropBlock;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.block.Fertilizable;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.block.SaplingBlock;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.fluid.EmptyFluid;
|
import net.minecraft.world.level.GameType;
|
||||||
import net.minecraft.fluid.LavaFluid;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.fluid.WaterFluid;
|
import net.minecraft.world.level.block.CropBlock;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.world.level.block.SaplingBlock;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.world.level.material.EmptyFluid;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.level.material.WaterFluid;
|
||||||
import net.minecraft.util.Colors;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.world.GameMode;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -41,13 +34,13 @@ public class Helper {
|
|||||||
private static final Pattern NON_ASCII = Pattern.compile("[^a-zA-Z0-9_+()]");
|
private static final Pattern NON_ASCII = Pattern.compile("[^a-zA-Z0-9_+()]");
|
||||||
public static final char COLOR = '§';
|
public static final char COLOR = '§';
|
||||||
|
|
||||||
public static boolean canBack(ServerPlayerEntity player) {
|
public static boolean canBack(ServerPlayer player) {
|
||||||
if (!SFConsts.COMMAND_BACK.hasPermission(player)) return false;
|
if (!SFConsts.COMMAND_BACK.hasPermission(player)) return false;
|
||||||
var pos = player.getLastDeathPos().get();
|
var pos = player.getLastDeathLocation().get();
|
||||||
var wld = player.getServer().getWorld(pos.dimension());
|
var wld = player.getServer().getLevel(pos.dimension());
|
||||||
var _pos = pos.pos();
|
var _pos = pos.pos();
|
||||||
if (wld == null) return false;
|
if (wld == null) return false;
|
||||||
var nearby = wld.getClosestPlayer(_pos.getX(), _pos.getY(), _pos.getZ(), 100, true);
|
var nearby = wld.getNearestPlayer(_pos.getX(), _pos.getY(), _pos.getZ(), 100, true);
|
||||||
return nearby != null;
|
return nearby != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,37 +53,37 @@ public class Helper {
|
|||||||
return NON_ASCII.matcher(name).replaceAll("");
|
return NON_ASCII.matcher(name).replaceAll("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean teleportSafely(ServerPlayerEntity player, ServerWorld world, int x, int y, int z, float yaw, float pitch) {
|
public static boolean teleportSafely(ServerPlayer player, ServerLevel world, int x, int y, int z, float yaw, float pitch) {
|
||||||
if (player.getGameMode() == GameMode.CREATIVE) return true;
|
if (player.gameMode() == GameType.CREATIVE) return true;
|
||||||
var pos = new BlockPos(x, y, z);
|
var pos = new BlockPos(x, y, z);
|
||||||
var stand = world.getBlockState(pos);
|
var stand = world.getBlockState(pos);
|
||||||
if (!stand.isAir() && !stand.isSolidBlock(world, pos)) {
|
if (!stand.isAir() && !stand.isRedstoneConductor(world, pos)) {
|
||||||
// check block type
|
// check block type
|
||||||
var fluid = stand.getFluidState().getFluid();
|
var fluid = stand.getFluidState().getType();
|
||||||
if (!(fluid instanceof EmptyFluid) && !(fluid instanceof WaterFluid)) {
|
if (!(fluid instanceof EmptyFluid) && !(fluid instanceof WaterFluid)) {
|
||||||
player.sendMessage(Text.literal("§c传送目的地具有非水流体, 因此拒绝传送。"));
|
player.sendSystemMessage(Component.literal("§c传送目的地具有非水流体, 因此拒绝传送。"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var groundPos = new BlockPos(x, y - 1, z);
|
var groundPos = new BlockPos(x, y - 1, z);
|
||||||
var ground = world.getBlockState(groundPos);
|
var ground = world.getBlockState(groundPos);
|
||||||
if (!ground.hasSolidTopSurface(world, groundPos, player)
|
if (!ground.entityCanStandOn(world, groundPos, player)
|
||||||
&& !stand.isSolidSurface(world, pos, player, Direction.DOWN)) {
|
&& !stand.entityCanStandOnFace(world, pos, player, Direction.DOWN)) {
|
||||||
player.sendMessage(Text.literal("§c传送目的地没有可靠落地点,且为非空气方块, 因此拒绝传送。"));
|
player.sendSystemMessage(Component.literal("§c传送目的地没有可靠落地点,且为非空气方块, 因此拒绝传送。"));
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
var deltaY = 0.0;
|
var deltaY = 0.0;
|
||||||
var deltaX = 0.5;
|
var deltaX = 0.5;
|
||||||
var deltaZ = 0.5;
|
var deltaZ = 0.5;
|
||||||
if (!stand.isAir()) {
|
if (!stand.isAir()) {
|
||||||
deltaY = stand.getCollisionShape(world, pos).getMax(Direction.Axis.Y);
|
deltaY = stand.getCollisionShape(world, pos).max(Direction.Axis.Y);
|
||||||
deltaY = Double.isFinite(deltaY) ? deltaY + 0.1 : 0;
|
deltaY = Double.isFinite(deltaY) ? deltaY + 0.1 : 0;
|
||||||
deltaX = stand.getCollisionShape(world, pos).getMax(Direction.Axis.X);
|
deltaX = stand.getCollisionShape(world, pos).max(Direction.Axis.X);
|
||||||
deltaX = Double.isFinite(deltaX) ? deltaX / 2 : 0.5;
|
deltaX = Double.isFinite(deltaX) ? deltaX / 2 : 0.5;
|
||||||
deltaZ = stand.getCollisionShape(world, pos).getMax(Direction.Axis.X);
|
deltaZ = stand.getCollisionShape(world, pos).max(Direction.Axis.X);
|
||||||
deltaZ = Double.isFinite(deltaZ) ? deltaZ / 2 : 0.5;
|
deltaZ = Double.isFinite(deltaZ) ? deltaZ / 2 : 0.5;
|
||||||
}
|
}
|
||||||
player.teleport(world, x + deltaX, y + deltaY, z + deltaZ, Set.of(), yaw, pitch, true);
|
player.teleportTo(world, x + deltaX, y + deltaY, z + deltaZ, Set.of(), yaw, pitch, true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package io.ib67.sfcraft.util;
|
package io.ib67.sfcraft.util;
|
||||||
|
|
||||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public record Permission<T extends Entity>(String key, boolean byDefault) {
|
public record Permission<T extends Entity>(String key, boolean byDefault) {
|
||||||
@@ -24,8 +23,8 @@ public record Permission<T extends Entity>(String key, boolean byDefault) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean check(T t, String permission){
|
private boolean check(T t, String permission){
|
||||||
if(t instanceof PlayerEntity player) {
|
if(t instanceof Player player) {
|
||||||
if (player.getCommandTags().contains(permission)){
|
if (player.getTags().contains(permission)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,30 +4,29 @@ import io.ib67.sfcraft.SFCraft;
|
|||||||
import io.ib67.sfcraft.util.Permission;
|
import io.ib67.sfcraft.util.Permission;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class SFConsts {
|
public class SFConsts {
|
||||||
public static final String VERSION = FabricLoader.getInstance().getModContainer(SFCraft.MOD_ID).get().getMetadata().getVersion().getFriendlyString();
|
public static final String VERSION = FabricLoader.getInstance().getModContainer(SFCraft.MOD_ID).get().getMetadata().getVersion().getFriendlyString();
|
||||||
public static final String SPECIAL_SUDO = "sfcraft.special.state.sudo";
|
public static final String SPECIAL_SUDO = "sfcraft.special.state.sudo";
|
||||||
public static final Permission<PlayerEntity> USE_AT = ofSFCPermission("chat.at", true);
|
public static final Permission<Player> USE_AT = ofSFCPermission("chat.at", true);
|
||||||
public static final Permission<PlayerEntity> USE_BROADCAST_LOCATION = ofSFCPermission("chat.xyz", true);
|
public static final Permission<Player> USE_BROADCAST_LOCATION = ofSFCPermission("chat.xyz", true);
|
||||||
public static final Permission<PlayerEntity> COMMAND_BACK = ofSFCPermission("command.back", true);
|
public static final Permission<Player> COMMAND_BACK = ofSFCPermission("command.back", true);
|
||||||
public static final Permission<PlayerEntity> UNLIMITED_COMMAND_BACK = ofSFCPermission("command.back.unlimited", false);
|
public static final Permission<Player> UNLIMITED_COMMAND_BACK = ofSFCPermission("command.back.unlimited", false);
|
||||||
public static final Permission<PlayerEntity> WORLDEDIT_AT_PLAYGROUND = ofSFCPermission("worldedit", true);
|
public static final Permission<Player> WORLDEDIT_AT_PLAYGROUND = ofSFCPermission("worldedit", true);
|
||||||
|
|
||||||
public static final Permission<PlayerEntity> COMMAND_ADDWL = ofSFCPermission("command.addwl", false);
|
public static final Permission<Player> COMMAND_ADDWL = ofSFCPermission("command.addwl", false);
|
||||||
public static final Permission<PlayerEntity> COMMAND_UPLOAD_SCHEMATIC = ofSFCPermission("command.upload.schematic", false);
|
public static final Permission<Player> COMMAND_UPLOAD_SCHEMATIC = ofSFCPermission("command.upload.schematic", false);
|
||||||
public static final Permission<PlayerEntity> COMMAND_LISTOFFLINE = ofSFCPermission("command.listoffline", false);
|
public static final Permission<Player> COMMAND_LISTOFFLINE = ofSFCPermission("command.listoffline", false);
|
||||||
public static final Permission<PlayerEntity> COMMAND_LISTPERM = ofSFCPermission("command.listperm", false);
|
public static final Permission<Player> COMMAND_LISTPERM = ofSFCPermission("command.listperm", false);
|
||||||
public static final Permission<PlayerEntity> COMMAND_LISTGEO = ofSFCPermission("command.listgeo", false);
|
public static final Permission<Player> COMMAND_LISTGEO = ofSFCPermission("command.listgeo", false);
|
||||||
public static final Permission<PlayerEntity> COMMAND_PLAYGROUND = ofSFCPermission("command.playground", true);
|
public static final Permission<Player> COMMAND_PLAYGROUND = ofSFCPermission("command.playground", true);
|
||||||
public static final Permission<PlayerEntity> COMMAND_PLAYGROUND_GAMEMODE = ofSFCPermission("command.playground.gamemode", true);
|
public static final Permission<Player> COMMAND_PLAYGROUND_GAMEMODE = ofSFCPermission("command.playground.gamemode", true);
|
||||||
public static final Permission<PlayerEntity> COMMAND_PLAYGROUND_TELEPORT = ofSFCPermission("command.playground.teleport", true);
|
public static final Permission<Player> COMMAND_PLAYGROUND_TELEPORT = ofSFCPermission("command.playground.teleport", true);
|
||||||
public static final Permission<PlayerEntity> COMMAND_RECO = ofSFCPermission("command.reco", true);
|
public static final Permission<Player> COMMAND_RECO = ofSFCPermission("command.reco", true);
|
||||||
|
|
||||||
public static Permission<PlayerEntity> ofSFCPermission(String key, boolean byDefault) {
|
public static Permission<Player> ofSFCPermission(String key, boolean byDefault) {
|
||||||
return new Permission<>("sfcraft." + key, byDefault);
|
return new Permission<>("sfcraft." + key, byDefault);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
package io.ib67.sfcraft.util;
|
package io.ib67.sfcraft.util;
|
||||||
|
|
||||||
import net.minecraft.nbt.NbtElement;
|
|
||||||
import net.minecraft.nbt.NbtList;
|
|
||||||
|
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
public class TypedNbtList extends NbtList {
|
public class TypedNbtList extends ListTag {
|
||||||
private final byte heldType;
|
private final byte heldType;
|
||||||
public TypedNbtList(List<NbtElement> list, byte type) {
|
public TypedNbtList(List<Tag> list, byte type) {
|
||||||
super(list);
|
super(list);
|
||||||
this.heldType = type;
|
this.heldType = type;
|
||||||
}
|
}
|
||||||
@@ -19,7 +18,7 @@ public class TypedNbtList extends NbtList {
|
|||||||
output.writeByte(heldType);
|
output.writeByte(heldType);
|
||||||
output.writeInt(this.size());
|
output.writeInt(this.size());
|
||||||
|
|
||||||
for (NbtElement nbtElement : this) {
|
for (Tag nbtElement : this) {
|
||||||
nbtElement.write(output);
|
nbtElement.write(output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.minecraft.nbt.*;
|
import net.minecraft.nbt.*;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import org.apache.commons.compress.utils.Lists;
|
import org.apache.commons.compress.utils.Lists;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -16,20 +16,20 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A cleaned up version of https://github.com/GoldenDelicios/Lite2Edit
|
* A cleaned up version of https://github.com/GoldenDelicios/Lite2Edit
|
||||||
* Uses {@link NbtCompound} from Minecraft.
|
* Uses {@link CompoundTag} from Minecraft.
|
||||||
*/
|
*/
|
||||||
public class LitematicConverter implements AutoCloseable {
|
public class LitematicConverter implements AutoCloseable {
|
||||||
protected final InputStream input;
|
protected final InputStream input;
|
||||||
protected final NbtSizeTracker sizeTracker;
|
protected final NbtAccounter sizeTracker;
|
||||||
|
|
||||||
public LitematicConverter(InputStream input, NbtSizeTracker sizeTracker) {
|
public LitematicConverter(InputStream input, NbtAccounter sizeTracker) {
|
||||||
this.input = input;
|
this.input = input;
|
||||||
this.sizeTracker = sizeTracker;
|
this.sizeTracker = sizeTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void read(
|
public void read(
|
||||||
BiConsumer<String, NbtCompound> schematicOutput
|
BiConsumer<String, CompoundTag> schematicOutput
|
||||||
) {
|
) {
|
||||||
var root = NbtIo.readCompressed(input, sizeTracker);
|
var root = NbtIo.readCompressed(input, sizeTracker);
|
||||||
var dataVersion = root.getInt("MinecraftDataVersion")
|
var dataVersion = root.getInt("MinecraftDataVersion")
|
||||||
@@ -37,7 +37,7 @@ public class LitematicConverter implements AutoCloseable {
|
|||||||
var regionsNbt = root.getCompound("Regions")
|
var regionsNbt = root.getCompound("Regions")
|
||||||
.orElseThrow(() -> new IllegalStateException("Regions not found"));
|
.orElseThrow(() -> new IllegalStateException("Regions not found"));
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (String regionName : regionsNbt.getKeys()) {
|
for (String regionName : regionsNbt.keySet()) {
|
||||||
var compound = regionsNbt.getCompound(regionName)
|
var compound = regionsNbt.getCompound(regionName)
|
||||||
.orElseThrow(() -> new IllegalStateException("Region " + regionName + " not found"));
|
.orElseThrow(() -> new IllegalStateException("Region " + regionName + " not found"));
|
||||||
var j = i++;
|
var j = i++;
|
||||||
@@ -46,8 +46,8 @@ public class LitematicConverter implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NbtCompound convertRegionToSchematic(int dataVersion, NbtCompound region) {
|
protected CompoundTag convertRegionToSchematic(int dataVersion, CompoundTag region) {
|
||||||
var worldEditTag = new NbtCompound();
|
var worldEditTag = new CompoundTag();
|
||||||
|
|
||||||
// prepare metadata
|
// prepare metadata
|
||||||
var size = readSizeTuple(region);
|
var size = readSizeTuple(region);
|
||||||
@@ -62,20 +62,20 @@ public class LitematicConverter implements AutoCloseable {
|
|||||||
// block & tile entities
|
// block & tile entities
|
||||||
var paletteNbt = region.getListOrEmpty("BlockStatePalette");
|
var paletteNbt = region.getListOrEmpty("BlockStatePalette");
|
||||||
var wePalette = convertToWEPalette(paletteNbt);
|
var wePalette = convertToWEPalette(paletteNbt);
|
||||||
worldEditTag.putInt("PaletteMax", wePalette.getKeys().size());
|
worldEditTag.putInt("PaletteMax", wePalette.keySet().size());
|
||||||
worldEditTag.put("Palette", wePalette);
|
worldEditTag.put("Palette", wePalette);
|
||||||
var tileEntities = region.getListOrEmpty("TileEntities");
|
var tileEntities = region.getListOrEmpty("TileEntities");
|
||||||
worldEditTag.put("BlockEntities", convertToWETileEntities(tileEntities));
|
worldEditTag.put("BlockEntities", convertToWETileEntities(tileEntities));
|
||||||
worldEditTag.putInt("Version", 2);
|
worldEditTag.putInt("Version", 2);
|
||||||
worldEditTag.putIntArray("Offset", new int[3]);
|
worldEditTag.putIntArray("Offset", new int[3]);
|
||||||
worldEditTag.putByteArray("BlockData", convertToWEBlocks(size, region));
|
worldEditTag.putByteArray("BlockData", convertToWEBlocks(size, region));
|
||||||
var schematicsRoot = new NbtCompound();
|
var schematicsRoot = new CompoundTag();
|
||||||
schematicsRoot.put("Schematic", worldEditTag);
|
schematicsRoot.put("Schematic", worldEditTag);
|
||||||
return schematicsRoot;
|
return schematicsRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SizeTuple readSizeTuple(NbtCompound region) {
|
protected SizeTuple readSizeTuple(CompoundTag region) {
|
||||||
var size = (NbtCompound) region.get("Size");
|
var size = (CompoundTag) region.get("Size");
|
||||||
if (size == null) {
|
if (size == null) {
|
||||||
throw new IllegalStateException("Size not found");
|
throw new IllegalStateException("Size not found");
|
||||||
}
|
}
|
||||||
@@ -88,12 +88,12 @@ public class LitematicConverter implements AutoCloseable {
|
|||||||
return new SizeTuple(sizeX, sizeY, sizeZ);
|
return new SizeTuple(sizeX, sizeY, sizeZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NbtList convertToWETileEntities(NbtList tileEntities) {
|
protected ListTag convertToWETileEntities(ListTag tileEntities) {
|
||||||
var weTEs = new TypedNbtList(Lists.newArrayList(), NbtElement.COMPOUND_TYPE);
|
var weTEs = new TypedNbtList(Lists.newArrayList(), Tag.TAG_COMPOUND);
|
||||||
|
|
||||||
for (NbtElement _tileEntity : tileEntities) {
|
for (Tag _tileEntity : tileEntities) {
|
||||||
var weTE = new NbtCompound();
|
var weTE = new CompoundTag();
|
||||||
var tE = (NbtCompound) _tileEntity;
|
var tE = (CompoundTag) _tileEntity;
|
||||||
weTE.putIntArray("Pos", new int[]{
|
weTE.putIntArray("Pos", new int[]{
|
||||||
tE.getInt("x")
|
tE.getInt("x")
|
||||||
.orElseThrow(() -> new IllegalStateException("Pos X not found")),
|
.orElseThrow(() -> new IllegalStateException("Pos X not found")),
|
||||||
@@ -114,17 +114,17 @@ public class LitematicConverter implements AutoCloseable {
|
|||||||
return weTEs;
|
return weTEs;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NbtCompound convertToWEPalette(NbtList paletteNbt) {
|
protected CompoundTag convertToWEPalette(ListTag paletteNbt) {
|
||||||
var wePalette = new NbtCompound();
|
var wePalette = new CompoundTag();
|
||||||
for (int i = 0; i < paletteNbt.size(); i++) {
|
for (int i = 0; i < paletteNbt.size(); i++) {
|
||||||
var entry = (NbtCompound) paletteNbt.get(i);
|
var entry = (CompoundTag) paletteNbt.get(i);
|
||||||
var name = new StringBuilder(entry.getString("Name").orElseThrow(() -> new IllegalStateException("Name not found")));
|
var name = new StringBuilder(entry.getString("Name").orElseThrow(() -> new IllegalStateException("Name not found")));
|
||||||
var _properties = entry.getCompound("Properties");
|
var _properties = entry.getCompound("Properties");
|
||||||
if (_properties.isPresent()) {
|
if (_properties.isPresent()) {
|
||||||
var properties = _properties.get();
|
var properties = _properties.get();
|
||||||
name.append("[");
|
name.append("[");
|
||||||
var props = new ArrayList<String>();
|
var props = new ArrayList<String>();
|
||||||
for (String key : properties.getKeys()) {
|
for (String key : properties.keySet()) {
|
||||||
props.add(key + "=" + properties.getString(key));
|
props.add(key + "=" + properties.getString(key));
|
||||||
}
|
}
|
||||||
name.append(String.join(",", props));
|
name.append(String.join(",", props));
|
||||||
@@ -135,25 +135,25 @@ public class LitematicConverter implements AutoCloseable {
|
|||||||
return wePalette;
|
return wePalette;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NbtElement convertToWeMeta(SizeTuple size, NbtCompound region) {
|
protected Tag convertToWeMeta(SizeTuple size, CompoundTag region) {
|
||||||
var pos = (NbtCompound) region.get("Position");
|
var pos = (CompoundTag) region.get("Position");
|
||||||
if (pos == null){
|
if (pos == null){
|
||||||
throw new IllegalStateException("Pos not found");
|
throw new IllegalStateException("Pos not found");
|
||||||
}
|
}
|
||||||
var nbt = new NbtCompound();
|
var nbt = new CompoundTag();
|
||||||
nbt.putInt("WEOffsetX", pos.getInt("x").orElseThrow() + (size.x < 0 ? size.x + 1 : 0));
|
nbt.putInt("WEOffsetX", pos.getInt("x").orElseThrow() + (size.x < 0 ? size.x + 1 : 0));
|
||||||
nbt.putInt("WEOffsetY", pos.getInt("y").orElseThrow() + (size.y < 0 ? size.y + 1 : 0));
|
nbt.putInt("WEOffsetY", pos.getInt("y").orElseThrow() + (size.y < 0 ? size.y + 1 : 0));
|
||||||
nbt.putInt("WEOffsetZ", pos.getInt("z").orElseThrow() + (size.z < 0 ? size.z + 1 : 0));
|
nbt.putInt("WEOffsetZ", pos.getInt("z").orElseThrow() + (size.z < 0 ? size.z + 1 : 0));
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] convertToWEBlocks(SizeTuple size, NbtCompound region) {
|
protected byte[] convertToWEBlocks(SizeTuple size, CompoundTag region) {
|
||||||
var blockCount = Math.abs(size.x * size.y * size.z);
|
var blockCount = Math.abs(size.x * size.y * size.z);
|
||||||
var blockStates = region.getLongArray("BlockStates").orElse(new long[0]);
|
var blockStates = region.getLongArray("BlockStates").orElse(new long[0]);
|
||||||
int bitsPerBlock = region.getListOrEmpty("BlockStatePalette").size();
|
int bitsPerBlock = region.getListOrEmpty("BlockStatePalette").size();
|
||||||
bitsPerBlock = Math.max(2, Integer.SIZE - Integer.numberOfLeadingZeros(bitsPerBlock - 1));
|
bitsPerBlock = Math.max(2, Integer.SIZE - Integer.numberOfLeadingZeros(bitsPerBlock - 1));
|
||||||
int maxEntryValue = (1 << bitsPerBlock) - 1;
|
int maxEntryValue = (1 << bitsPerBlock) - 1;
|
||||||
var buffer = new PacketByteBuf(Unpooled.buffer());
|
var buffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||||
for (int index = 0; index < blockCount; index++) {
|
for (int index = 0; index < blockCount; index++) {
|
||||||
int startBit = index * bitsPerBlock;
|
int startBit = index * bitsPerBlock;
|
||||||
int startLongIndex = startBit / 64;
|
int startLongIndex = startBit / 64;
|
||||||
|
|||||||
@@ -4,23 +4,22 @@ import io.netty.buffer.Unpooled;
|
|||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.core.Vec3i;
|
||||||
import net.minecraft.nbt.NbtElement;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtSizeTracker;
|
import net.minecraft.nbt.NbtAccounter;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.util.math.Vec3i;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
public class LitematicConverterV3 extends LitematicConverter {
|
public class LitematicConverterV3 extends LitematicConverter {
|
||||||
public LitematicConverterV3(InputStream input, NbtSizeTracker sizeTracker) {
|
public LitematicConverterV3(InputStream input, NbtAccounter sizeTracker) {
|
||||||
super(input, sizeTracker);
|
super(input, sizeTracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NbtCompound convertRegionToSchematic(int dataVersion, NbtCompound region) {
|
protected CompoundTag convertRegionToSchematic(int dataVersion, CompoundTag region) {
|
||||||
var schematicsTag = new NbtCompound();
|
var schematicsTag = new CompoundTag();
|
||||||
|
|
||||||
// prepare metadata
|
// prepare metadata
|
||||||
var size = readSizeTuple(region);
|
var size = readSizeTuple(region);
|
||||||
@@ -39,30 +38,30 @@ public class LitematicConverterV3 extends LitematicConverter {
|
|||||||
var wePalette = convertToWEPalette(paletteNbt);
|
var wePalette = convertToWEPalette(paletteNbt);
|
||||||
var tileEntities = region.getListOrEmpty("TileEntities");
|
var tileEntities = region.getListOrEmpty("TileEntities");
|
||||||
|
|
||||||
var blocksNbt = new NbtCompound();
|
var blocksNbt = new CompoundTag();
|
||||||
blocksNbt.put("Palette", wePalette);
|
blocksNbt.put("Palette", wePalette);
|
||||||
var weBlockData = convertToWEBlocks(size, region);
|
var weBlockData = convertToWEBlocks(size, region);
|
||||||
blocksNbt.putByteArray("Data", weBlockData);
|
blocksNbt.putByteArray("Data", weBlockData);
|
||||||
blocksNbt.put("BlockEntities", convertToWETileEntities(tileEntities));
|
blocksNbt.put("BlockEntities", convertToWETileEntities(tileEntities));
|
||||||
validateData(wePalette, weBlockData, Math.abs(size.x()), Math.abs(size.z()));
|
validateData(wePalette, weBlockData, Math.abs(size.x()), Math.abs(size.z()));
|
||||||
schematicsTag.put("Blocks", blocksNbt);
|
schematicsTag.put("Blocks", blocksNbt);
|
||||||
var schematicsRoot = new NbtCompound();
|
var schematicsRoot = new CompoundTag();
|
||||||
schematicsRoot.put("Schematic", schematicsTag);
|
schematicsRoot.put("Schematic", schematicsTag);
|
||||||
return schematicsRoot;
|
return schematicsRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateData(
|
private void validateData(
|
||||||
NbtCompound wePalette,
|
CompoundTag wePalette,
|
||||||
byte[] weBlockData,
|
byte[] weBlockData,
|
||||||
int width,
|
int width,
|
||||||
int length
|
int length
|
||||||
) {
|
) {
|
||||||
log.info("Validating schematic");
|
log.info("Validating schematic");
|
||||||
// find invalid palette ids
|
// find invalid palette ids
|
||||||
var buf = new PacketByteBuf(Unpooled.wrappedBuffer(weBlockData));
|
var buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(weBlockData));
|
||||||
var paletteIds = new Int2ObjectOpenHashMap<>();
|
var paletteIds = new Int2ObjectOpenHashMap<>();
|
||||||
var touchedIds = new IntOpenHashSet();
|
var touchedIds = new IntOpenHashSet();
|
||||||
for (String key : wePalette.getKeys()) {
|
for (String key : wePalette.keySet()) {
|
||||||
paletteIds.put(
|
paletteIds.put(
|
||||||
wePalette.getInt(key)
|
wePalette.getInt(key)
|
||||||
.orElseThrow(() -> new IllegalStateException("Cannot find key " + key + " in palette from worldedit schematic"))
|
.orElseThrow(() -> new IllegalStateException("Cannot find key " + key + " in palette from worldedit schematic"))
|
||||||
@@ -97,18 +96,18 @@ public class LitematicConverterV3 extends LitematicConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NbtElement convertToWeMeta(SizeTuple size, NbtCompound region) {
|
protected Tag convertToWeMeta(SizeTuple size, CompoundTag region) {
|
||||||
var pos = (NbtCompound) region.get("Position");
|
var pos = (CompoundTag) region.get("Position");
|
||||||
if (pos == null) {
|
if (pos == null) {
|
||||||
throw new IllegalStateException("Cannot find Position");
|
throw new IllegalStateException("Cannot find Position");
|
||||||
}
|
}
|
||||||
var worldEditNbt = new NbtCompound();
|
var worldEditNbt = new CompoundTag();
|
||||||
worldEditNbt.putIntArray("Origin", new int[]{
|
worldEditNbt.putIntArray("Origin", new int[]{
|
||||||
pos.getInt("x").orElseThrow() + (size.x() < 0 ? size.x() + 1 : 0),
|
pos.getInt("x").orElseThrow() + (size.x() < 0 ? size.x() + 1 : 0),
|
||||||
pos.getInt("y").orElseThrow() + (size.y() < 0 ? size.y() + 1 : 0),
|
pos.getInt("y").orElseThrow() + (size.y() < 0 ? size.y() + 1 : 0),
|
||||||
pos.getInt("z").orElseThrow() + (size.z() < 0 ? size.z() + 1 : 0)
|
pos.getInt("z").orElseThrow() + (size.z() < 0 ? size.z() + 1 : 0)
|
||||||
});
|
});
|
||||||
var Metadata = new NbtCompound();
|
var Metadata = new CompoundTag();
|
||||||
Metadata.put("WorldEdit", worldEditNbt);
|
Metadata.put("WorldEdit", worldEditNbt);
|
||||||
Metadata.putLong("Date", System.currentTimeMillis());
|
Metadata.putLong("Date", System.currentTimeMillis());
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
accessWidener v2 named
|
accessWidener v2 named
|
||||||
mutable field net/minecraft/item/Item registryEntry Lnet/minecraft/registry/entry/RegistryEntry$Reference;
|
accessible method net/minecraft/nbt/ListTag <init> (Ljava/util/List;)V
|
||||||
accessible method net/minecraft/nbt/NbtList <init> (Ljava/util/List;)V
|
extendable class net/minecraft/nbt/ListTag
|
||||||
extendable class net/minecraft/nbt/NbtList
|
|
||||||
Reference in new issue
Block a user