bump minecraft version to 26.2
This commit is contained in:
31 files changed
+119
-198
No files matched your search
+11
-20
@@ -2,7 +2,7 @@ plugins {
|
||||
id 'maven-publish'
|
||||
id("io.freefair.lombok") version "9.5.0"
|
||||
id("com.gradleup.shadow") version "9.3.1"
|
||||
id 'fabric-loom' version '1.17-SNAPSHOT'
|
||||
id 'net.fabricmc.fabric-loom' version '1.17-SNAPSHOT'
|
||||
}
|
||||
|
||||
version = project.mod_version
|
||||
@@ -13,23 +13,23 @@ base {
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Add repositories to retrieve artifacts from in here.
|
||||
// You should only use this when depending on other mods because
|
||||
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
|
||||
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
|
||||
// for more information about repositories.
|
||||
mavenCentral()
|
||||
maven {
|
||||
name "kalculosSnapshots"
|
||||
url "https://repo.sfclub.cc/snapshots"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// To change the versions see the gradle.properties file1
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings loom.officialMojangMappings()
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
modImplementation 'me.lucko:fabric-permissions-api:0.3.1'
|
||||
implementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
implementation 'me.lucko:fabric-permissions-api:0.7.0'
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
shadow('com.maxmind.geoip2:geoip2:4.2.0')
|
||||
shadow("io.javalin:javalin:6.4.0")
|
||||
include(implementation "io.ib67.kiwi:lang:1.2.3-SNAPSHOT")
|
||||
shadow('com.github.houbb:pinyin:0.4.0')
|
||||
shadow('com.google.inject:guice:7.0.0') {
|
||||
exclude group: 'com.google.guava', module: 'guava'
|
||||
@@ -42,15 +42,6 @@ configurations.implementation.extendsFrom(configurations.shadow)
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadow]
|
||||
exclude("META-INF")
|
||||
//relocate 'com.google', 'sfcraft.relocation.google'
|
||||
}
|
||||
|
||||
remapJar {
|
||||
// wait until the shadowJar is done
|
||||
dependsOn(shadowJar)
|
||||
mustRunAfter(shadowJar)
|
||||
// Set the input jar for the task. Here use the shadow Jar that include the .class of the transitive dependency
|
||||
inputFile = shadowJar.archiveFile
|
||||
}
|
||||
|
||||
processResources {
|
||||
@@ -66,7 +57,7 @@ processResources {
|
||||
}
|
||||
}
|
||||
|
||||
def targetJavaVersion = 21
|
||||
def targetJavaVersion = 25
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
||||
// this fixes some edge cases with special characters not displaying correctly
|
||||
|
||||
+6
-9
@@ -2,19 +2,16 @@
|
||||
org.gradle.jvmargs=-Xmx2G
|
||||
|
||||
# Fabric Properties
|
||||
# check these on https://modmuss50.me/fabric.html
|
||||
minecraft_version=1.21.8
|
||||
yarn_mappings=1.21.8+build.1
|
||||
loader_version=0.16.14
|
||||
# check these on https://modmuss50.me/fabric.html
|
||||
minecraft_version=26.2
|
||||
loader_version=0.19.3
|
||||
|
||||
|
||||
# Mod Properties
|
||||
mod_version=1.2
|
||||
mod_version=1.3
|
||||
maven_group=io.ib67
|
||||
archives_base_name=sfcraft
|
||||
|
||||
# Dependencies
|
||||
# check this on https://modmuss50.me/fabric.html
|
||||
fabric_version=0.129.0+1.21.8
|
||||
|
||||
|
||||
# check this on https://modmuss50.me/fabric.html
|
||||
fabric_version=0.155.0+26.2
|
||||
@@ -4,12 +4,12 @@ import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.world.item.Item;
|
||||
|
||||
public class SFRegistries {
|
||||
public static final Registry<Item> ITEMS = FabricRegistryBuilder
|
||||
.<Item>createSimple(ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "item")))
|
||||
.<Item>create(ResourceKey.createRegistryKey(Identifier.fromNamespaceAndPath(SFCraft.MOD_ID, "item")))
|
||||
.attribute(RegistryAttribute.MODDED)
|
||||
.buildAndRegister();
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ib67.sfcraft.mixin.common.fixes;
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.animal.Bee;
|
||||
import net.minecraft.world.entity.animal.bee.Bee;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.ib67.sfcraft.mixin.server;
|
||||
import io.ib67.sfcraft.mixin.common.bridge.ServerWorldBridge;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.gamerules.GameRules;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.AbstractFurnaceBlock;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
@@ -39,7 +39,7 @@ public abstract class AbstractFurnaceBlockMixin extends BaseEntityBlock {
|
||||
private static <E extends AbstractFurnaceBlockEntity> void tickMultiple(Level _world, BlockPos pos, BlockState state, E blockEntity) {
|
||||
var world = (ServerLevel) _world;
|
||||
AbstractFurnaceBlockEntity.serverTick(world, pos, state, blockEntity);
|
||||
int i = world.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||
int i = world.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
|
||||
if (((ServerWorldBridge) world).getDEEPSLATE_BRICKS().areEnoughSleeping(i)) {
|
||||
AbstractFurnaceBlockEntity.serverTick(world, pos, state, blockEntity); //todo: config support?
|
||||
AbstractFurnaceBlockEntity.serverTick(world, pos, state, blockEntity);
|
||||
|
||||
@@ -3,11 +3,11 @@ package io.ib67.sfcraft.mixin.server;
|
||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||
import io.netty.channel.local.LocalChannel;
|
||||
import io.netty.channel.local.LocalServerChannel;
|
||||
import net.minecraft.core.UUIDUtil;
|
||||
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.players.NameAndId;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -41,10 +41,11 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
||||
if (!(connection.getRemoteAddress() instanceof InetSocketAddress)) {
|
||||
return connection.isMemoryConnection(); // 碰上真 isLocal 了
|
||||
}
|
||||
var offlineProfile = UUIDUtil.createOfflineProfile(currentPlayer);
|
||||
var offlineProfile = NameAndId.createOffline(currentPlayer);
|
||||
boolean _r;
|
||||
if (server.getProfileCache() != null) {
|
||||
_r = server.getProfileCache().get(offlineProfile.getId()).isPresent();
|
||||
var nameCache = server.services().nameToIdCache();
|
||||
if (nameCache != null) {
|
||||
_r = nameCache.get(offlineProfile.id()).isPresent();
|
||||
}else{
|
||||
var wl = server.getPlayerList().getWhiteList();
|
||||
_r = wl.isWhiteListed(offlineProfile);
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
package io.ib67.sfcraft.mixin.server;
|
||||
|
||||
import io.ib67.sfcraft.SFCraft;
|
||||
import io.ib67.sfcraft.mixin.common.bridge.ServerWorldBridge;
|
||||
import io.ib67.sfcraft.module.RoomModule;
|
||||
import io.ib67.sfcraft.util.MixinHelper;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import net.minecraft.world.level.gamerules.GameRules;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ServerLevel.class)
|
||||
public abstract class ServerWorldMixin {
|
||||
@ModifyArg(method = "tickTime", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setDayTime(J)V"))
|
||||
@ModifyArg(method = "tickTime", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/ServerLevelData;setGameTime(J)V"))
|
||||
public long setTimeOfDay(long timeOfDay) {
|
||||
int i = ((ServerLevel) (Object) this).getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||
int i = ((ServerLevel) (Object) this).getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
|
||||
if (((ServerWorldBridge) this).getDEEPSLATE_BRICKS().areEnoughSleeping(i)) {
|
||||
MixinHelper.spedUp = true;
|
||||
return timeOfDay + 10;
|
||||
|
||||
@@ -18,7 +18,7 @@ public abstract class SleepManagerMixin {
|
||||
return;
|
||||
}
|
||||
var world = players.getFirst().level();
|
||||
if (world.getDayTime() % 24000 >= 12544) {
|
||||
if (world.getDefaultClockTime() % 24000 >= 12544) {
|
||||
if(!world.isRaining()){
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ib67.sfcraft.mixin.server.subserver;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.ib67.sfcraft.SFCraft;
|
||||
import io.ib67.sfcraft.mixin.common.bridge.ServerChunkManagerBridge;
|
||||
import io.ib67.sfcraft.module.RoomModule;
|
||||
@@ -22,6 +21,7 @@ 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.NameAndId;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
@@ -58,13 +58,13 @@ public abstract class PlayerManagerMixin {
|
||||
}
|
||||
|
||||
@Inject(method = "canPlayerLogin", cancellable = true, at = @At("HEAD"))
|
||||
private void sf$bypassJoinLimit(SocketAddress address, GameProfile profile, CallbackInfoReturnable<Component> cir) {
|
||||
if (RoomModule.isVirtual(profile.getId())) cir.setReturnValue(null);
|
||||
private void sf$bypassJoinLimit(SocketAddress address, NameAndId profile, CallbackInfoReturnable<Component> cir) {
|
||||
if (RoomModule.isVirtual(profile.id())) cir.setReturnValue(null);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void teleportToRoom(ServerPlayer player, GlobalPos spawn) {
|
||||
var world = player.getServer().getLevel(spawn.dimension());
|
||||
var world = player.level().getServer().getLevel(spawn.dimension());
|
||||
var pos = spawn.pos();
|
||||
((ServerChunkManagerBridge)world.getChunkSource()).getLevelManager().addPlayer(player.getLastSectionPos(), player);
|
||||
player.teleportTo(world, pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0, true);
|
||||
|
||||
+4
-3
@@ -25,6 +25,7 @@ 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.NameAndId;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
|
||||
import static io.ib67.sfcraft.room.CookieState.*;
|
||||
@@ -74,7 +75,7 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
||||
try {
|
||||
if (packet.payload().length == 0) {
|
||||
// clean reconnect.
|
||||
LOGGER.info("Player " + authenticatedProfile.getName() + " requested a clean reconnection");
|
||||
LOGGER.info("Player " + authenticatedProfile.name() + " requested a clean reconnection");
|
||||
clean = true;
|
||||
ci.cancel();
|
||||
return;
|
||||
@@ -128,8 +129,8 @@ public abstract class ServerLoginNetworkHandlerMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@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 Component sf$bypassRoomPlayer(PlayerList instance, SocketAddress address, GameProfile profile) {
|
||||
@Redirect(method = "verifyLoginAndFinishConnectionSetup", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lnet/minecraft/server/players/NameAndId;)Lnet/minecraft/network/chat/Component;"))
|
||||
private Component sf$bypassRoomPlayer(PlayerList instance, SocketAddress address, NameAndId profile) {
|
||||
if (sf$cookieState == DONE) return null;
|
||||
return instance.canPlayerLogin(address, profile);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class AFKModule extends ServerModule {
|
||||
|
||||
private void enAFK(ServerPlayer player) {
|
||||
chatPrefixModule.applyPrefix(player, prefix);
|
||||
player.getServer().getPlayerList().broadcastSystemMessage(
|
||||
player.level().getServer().getPlayerList().broadcastSystemMessage(
|
||||
Component.literal(" * " + player.getName().tryCollapseToString() + " 正在挂机.").withColor(CommonColors.LIGHT_GRAY),
|
||||
false
|
||||
);
|
||||
@@ -49,7 +49,7 @@ public class AFKModule extends ServerModule {
|
||||
public void deAFK(ServerPlayer player) {
|
||||
String playerName = player.getName().tryCollapseToString();
|
||||
chatPrefixModule.removePrefix(player, prefix);
|
||||
player.getServer().getPlayerList().broadcastSystemMessage(
|
||||
player.level().getServer().getPlayerList().broadcastSystemMessage(
|
||||
Component.literal(" * " + playerName + " 回来了.").withColor(CommonColors.LIGHT_GRAY),
|
||||
false
|
||||
);
|
||||
|
||||
@@ -52,13 +52,13 @@ public class ElytraSpeedMeterModule extends ServerModule {
|
||||
text.append(genPitchMeter(player.getXRot()));
|
||||
text.append(" ");
|
||||
text.append(generateDurabilityMeter(f, player));
|
||||
player.displayClientMessage(text, true);
|
||||
player.sendOverlayMessage(text);
|
||||
} else {
|
||||
clean((ServerPlayer) player);
|
||||
if (f > THRESHLD_OF_ELYTRA_FLY * 20) {
|
||||
player.displayClientMessage(Component.literal("!! LANDED !!").withColor(CommonColors.GREEN), true);
|
||||
player.sendOverlayMessage(Component.literal("!! LANDED !!").withColor(CommonColors.GREEN));
|
||||
} else {
|
||||
player.displayClientMessage(Component.empty(), true);
|
||||
player.sendOverlayMessage(Component.empty());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ public class FartFertilizerModule extends ServerModule {
|
||||
0.4
|
||||
);
|
||||
for (ServerPlayer serverPlayerEntity : PlayerLookup.around(wld, blockPos, 6f)) {
|
||||
serverPlayerEntity.playNotifySound(
|
||||
Helper.playNotifySound(
|
||||
serverPlayerEntity,
|
||||
SoundEvents.COMPOSTER_FILL,
|
||||
SoundSource.BLOCKS,
|
||||
((6 - serverPlayerEntity.distanceTo(player) + 1) / 6) * 50,
|
||||
|
||||
@@ -15,9 +15,9 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.core.UUIDUtil;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.players.NameAndId;
|
||||
import net.minecraft.server.players.UserWhiteListEntry;
|
||||
import net.minecraft.util.CommonColors;
|
||||
import java.util.List;
|
||||
@@ -43,14 +43,14 @@ public class OfflineExemptModule extends ServerModule {
|
||||
dispatcher.register(
|
||||
LiteralArgumentBuilder.<CommandSourceStack>literal("addwl")
|
||||
.requires(i -> isEnabled())
|
||||
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_ADDWL.hasPermission(it.getPlayer()))
|
||||
.requires(it -> Commands.LEVEL_GAMEMASTERS.check(it.permissions()) || SFConsts.COMMAND_ADDWL.hasPermission(it.getPlayer()))
|
||||
.then(RequiredArgumentBuilder.<CommandSourceStack, String>argument("player", StringArgumentType.string())
|
||||
.executes(it -> this.addPlayerOffline(it.getSource(), it.getArgument("player", String.class))))
|
||||
|
||||
);
|
||||
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("listoffline")
|
||||
.requires(i -> isEnabled())
|
||||
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_LISTOFFLINE.hasPermission(it.getPlayer()))
|
||||
.requires(it -> Commands.LEVEL_GAMEMASTERS.check(it.permissions()) || SFConsts.COMMAND_LISTOFFLINE.hasPermission(it.getPlayer()))
|
||||
.executes(this::listOffline)
|
||||
);
|
||||
}
|
||||
@@ -63,11 +63,11 @@ public class OfflineExemptModule extends ServerModule {
|
||||
source.sendFailure(Component.nullToEmpty(player + " is already whitelisted or this id is conflict with a online user."));
|
||||
return 0;
|
||||
}
|
||||
var profile = UUIDUtil.createOfflineProfile(player);
|
||||
var profile = NameAndId.createOffline(player);
|
||||
wl.add(new UserWhiteListEntry(profile));
|
||||
var uc = source.getServer().getProfileCache();
|
||||
var uc = source.getServer().services().nameToIdCache();
|
||||
if (uc != null) uc.add(profile);
|
||||
source.sendSystemMessage(Component.nullToEmpty("[" + profile.getName() + "/" + profile.getId() + "]" + " is added!"));
|
||||
source.sendSystemMessage(Component.nullToEmpty("[" + profile.name() + "/" + profile.id() + "]" + " is added!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class OfflineExemptModule extends ServerModule {
|
||||
var wl = server.getPlayerList().getWhiteList();
|
||||
var names = wl.getUserList();
|
||||
source.sendSystemMessage(Component.nullToEmpty("Offline Users:").copy().withColor(CommonColors.GREEN));
|
||||
var r = Stream.of(names).filter(name -> wl.isWhiteListed(UUIDUtil.createOfflineProfile(name))).collect(Collectors.joining(", "));
|
||||
var r = Stream.of(names).filter(name -> wl.isWhiteListed(NameAndId.createOffline(name))).collect(Collectors.joining(", "));
|
||||
source.sendSystemMessage(Component.nullToEmpty(r.isEmpty() ? "No offline users found in whitelist." : r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import io.ib67.kiwi.tuple.Tuple2;
|
||||
import io.ib67.sfcraft.ServerModule;
|
||||
import io.ib67.sfcraft.config.SFConfig;
|
||||
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
||||
@@ -21,9 +22,8 @@ import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.common.ClientboundStoreCookiePacket;
|
||||
import net.minecraft.network.protocol.common.ClientboundTransferPacket;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.TicketType;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -43,7 +43,7 @@ public class RoomModule extends ServerModule {
|
||||
private MinecraftServerSupplier serverSupplier;
|
||||
@Inject
|
||||
private SFConfig config;
|
||||
private final List<Tuple<ResourceKey<Level>, BlockPos>> pregenQueue = new ArrayList<>();
|
||||
private final List<Tuple2<ResourceKey<Level>, BlockPos>> pregenQueue = new ArrayList<>();
|
||||
private final Map<UUID, GameProfile> uuidMapper = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
@@ -53,13 +53,15 @@ public class RoomModule extends ServerModule {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
for (Tuple<ResourceKey<Level>, BlockPos> registryKeyBlockPosPair : pregenQueue) {
|
||||
var world = serverSupplier.get().getLevel(registryKeyBlockPosPair.getA());
|
||||
for (Tuple2<ResourceKey<Level>, BlockPos> registryKeyBlockPosPair : pregenQueue) {
|
||||
var world = serverSupplier.get().getLevel(registryKeyBlockPosPair.a());
|
||||
if (world == null) {
|
||||
log.warn("Cannot find world {}", registryKeyBlockPosPair.getA());
|
||||
log.warn("Cannot find world {}", registryKeyBlockPosPair.b());
|
||||
continue;
|
||||
}
|
||||
world.getChunkSource().addTicketWithRadius(TicketType.START, new ChunkPos(registryKeyBlockPosPair.getB()), 64);
|
||||
var blockPos = registryKeyBlockPosPair.b();
|
||||
var chunkPos = new ChunkPos(blockPos.getX() >> 4, blockPos.getZ() >> 4);
|
||||
world.getChunkSource().addTicketWithRadius(TicketType.PLAYER_SPAWN, chunkPos, 64);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,10 +90,10 @@ public class RoomModule extends ServerModule {
|
||||
}
|
||||
|
||||
public void enqueuePregen(ResourceKey<Level> world, BlockPos spawnPos) {
|
||||
pregenQueue.add(new Tuple<>(world, spawnPos));
|
||||
pregenQueue.add(new Tuple2<>(world, spawnPos));
|
||||
}
|
||||
|
||||
public UUID generateIdForRoom(GameProfile issuer, String name, ResourceLocation room) {
|
||||
public UUID generateIdForRoom(GameProfile issuer, String name, Identifier room) {
|
||||
var uuid = UUID.nameUUIDFromBytes((name + "@" + room.toString()).getBytes(StandardCharsets.UTF_8));
|
||||
var result = new UUID(uuid.getMostSignificantBits(), 0);
|
||||
if (issuer != null) uuidMapper.put(result, issuer);
|
||||
|
||||
@@ -60,12 +60,12 @@ public class WelcomeModule extends ServerModule {
|
||||
packetSender, MinecraftServer minecraftServer) {
|
||||
if (!isEnabled()) return;
|
||||
var player = serverPlayNetworkHandler.getPlayer();
|
||||
if (!player.getTags().contains("sf_unlock_recipe")) {
|
||||
if (!player.entityTags().contains("sf_unlock_recipe")) {
|
||||
player.addTag("sf_unlock_recipe");
|
||||
unlockRecipe(player);
|
||||
}
|
||||
for (String s : announcements.keySet()) {
|
||||
if (!player.getTags().contains(s)) {
|
||||
if (!player.entityTags().contains(s)) {
|
||||
player.addTag(s);
|
||||
announcements.get(s).lines().map(Component::nullToEmpty).forEach(player::sendSystemMessage);
|
||||
}
|
||||
@@ -75,6 +75,6 @@ public class WelcomeModule extends ServerModule {
|
||||
|
||||
private void unlockRecipe(ServerPlayer player) {
|
||||
var recipe = player.getRecipeBook();
|
||||
recipe.addRecipes(player.getServer().getRecipeManager().getRecipes(), player);
|
||||
recipe.addRecipes(player.level().getServer().getRecipeManager().getRecipes(), player);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.google.inject.Inject;
|
||||
import io.ib67.sfcraft.ServerModule;
|
||||
import io.ib67.sfcraft.registry.chat.SimpleMessageDecorator;
|
||||
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
||||
import io.ib67.sfcraft.util.Helper;
|
||||
import io.ib67.sfcraft.util.SFConsts;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -51,9 +52,10 @@ public class ChatPingModule extends ServerModule implements ChatDecorator {
|
||||
var r = Component.literal(match.replaceAll(it -> this.matchPlayer(it, names, foundPlayers)));
|
||||
for (Player foundPlayer : foundPlayers) {
|
||||
if (sender != null) {
|
||||
foundPlayer.displayClientMessage(Component.literal(sender.getName().tryCollapseToString() + " 正在叫你。").withColor(CommonColors.LIGHT_GRAY), true);
|
||||
foundPlayer.sendOverlayMessage(Component.literal(sender.getName().tryCollapseToString() + " 正在叫你。").withColor(CommonColors.LIGHT_GRAY));
|
||||
}
|
||||
foundPlayer.playNotifySound(
|
||||
Helper.playNotifySound(
|
||||
(ServerPlayer) foundPlayer,
|
||||
SoundEvents.ITEM_PICKUP,
|
||||
SoundSource.PLAYERS,
|
||||
0.8f,
|
||||
|
||||
@@ -36,7 +36,7 @@ public class BackModule extends ServerModule {
|
||||
public int onBack(CommandContext<CommandSourceStack> it) {
|
||||
var player = it.getSource().getPlayer();
|
||||
var pos = player.getLastDeathLocation().get();
|
||||
var wld = player.getServer().getLevel(pos.dimension());
|
||||
var wld = player.level().getServer().getLevel(pos.dimension());
|
||||
var _pos = pos.pos();
|
||||
if (wld == null) return 0;
|
||||
var nearby = wld.getNearestPlayer(_pos.getX(), _pos.getY(), _pos.getZ(), 100, true);
|
||||
@@ -55,7 +55,7 @@ public class BackModule extends ServerModule {
|
||||
|
||||
public void onPlayerDeath(Player player, DamageSource damageSource) {
|
||||
if (this.isEnabled() && Helper.canBack((ServerPlayer) player)) {
|
||||
player.displayClientMessage(Component.nullToEmpty("Tip: 死亡地点附近有玩家,可以使用 /back 传送到他们那里。(即使在对方也死亡的状态下)"), false);
|
||||
player.sendSystemMessage(Component.nullToEmpty("Tip: 死亡地点附近有玩家,可以使用 /back 传送到他们那里。(即使在对方也死亡的状态下)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,17 +47,17 @@ public class ManagementModule extends ServerModule {
|
||||
Commands.CommandSelection env) {
|
||||
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("sudo")
|
||||
.requires(it -> this.isEnabled())
|
||||
.requires(it -> it.hasPermission(2) && it.getPlayer() != null)
|
||||
.requires(it -> Commands.LEVEL_GAMEMASTERS.check(it.permissions()) && it.getPlayer() != null)
|
||||
.executes(this::enterSudoMode)
|
||||
);
|
||||
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("listperm")
|
||||
.requires(it -> this.isEnabled())
|
||||
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_LISTPERM.hasPermission(it.getPlayer()))
|
||||
.requires(it -> Commands.LEVEL_GAMEMASTERS.check(it.permissions()) || SFConsts.COMMAND_LISTPERM.hasPermission(it.getPlayer()))
|
||||
.executes(this::listPerms)
|
||||
);
|
||||
dispatcher.register(LiteralArgumentBuilder.<CommandSourceStack>literal("listgeo")
|
||||
.requires(it -> this.isEnabled())
|
||||
.requires(it -> it.hasPermission(2) || SFConsts.COMMAND_LISTGEO.hasPermission(it.getPlayer()))
|
||||
.requires(it -> Commands.LEVEL_GAMEMASTERS.check(it.permissions()) || SFConsts.COMMAND_LISTGEO.hasPermission(it.getPlayer()))
|
||||
.executes(this::listGeo)
|
||||
);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public class ManagementModule extends ServerModule {
|
||||
|
||||
public int enterSudoMode(CommandContext<CommandSourceStack> ctx) {
|
||||
var player = ctx.getSource().getPlayer();
|
||||
if (player.getTags().contains(SFConsts.SPECIAL_SUDO)) {
|
||||
if (player.entityTags().contains(SFConsts.SPECIAL_SUDO)) {
|
||||
player.removeTag(SFConsts.SPECIAL_SUDO);
|
||||
player.sendSystemMessage(Component.nullToEmpty("Sudo is off.").copy().withColor(CommonColors.GREEN));
|
||||
} else {
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package io.ib67.sfcraft.module.randomevt.longnight;
|
||||
|
||||
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.CommonColors;
|
||||
import net.minecraft.world.level.Level;
|
||||
import java.awt.*;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class DawnAfterLongNightEvent extends RandomEvent {
|
||||
private final Level world;
|
||||
|
||||
@Override
|
||||
public int start() {
|
||||
if (LongNightEvent.justExpirencedLongNight) {
|
||||
LongNightEvent.justExpirencedLongNight = false;
|
||||
world.getServer().getPlayerList().broadcastSystemMessage(
|
||||
Component.literal("\"月亮\"离开了。")
|
||||
.withColor(new Color(235, 91, 0).getRGB())
|
||||
.append(Component.literal("(永夜事件结束)").withColor(CommonColors.LIGHT_GRAY))
|
||||
, false);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(int ticks) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package io.ib67.sfcraft.module.randomevt.longnight;
|
||||
|
||||
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.CommonColors;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class LongNightEvent extends RandomEvent {
|
||||
static boolean justExpirencedLongNight;
|
||||
static boolean isAtLongNight;
|
||||
@Getter
|
||||
private static int remainingTicks;
|
||||
private final ServerLevel world;
|
||||
private boolean doDaylightCycle;
|
||||
private boolean doTraderSpawning;
|
||||
|
||||
@Override
|
||||
public int start() {
|
||||
var pm = world.getServer().getPlayerList();
|
||||
isAtLongNight = true;
|
||||
pm.broadcastSystemMessage(Component.literal("月亮停滞在空中...").withColor(CommonColors.BLUE), false);
|
||||
this.doDaylightCycle = world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT);
|
||||
this.doTraderSpawning = world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING);
|
||||
world.getGameRules().getRule(GameRules.RULE_DAYLIGHT).set(false, world.getServer());
|
||||
world.getGameRules().getRule(GameRules.RULE_DO_TRADER_SPAWNING).set(false, world.getServer());
|
||||
remainingTicks = world.random.nextIntBetweenInclusive(8400, 2 * 8400);
|
||||
return remainingTicks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(int ticks) {
|
||||
remainingTicks--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
isAtLongNight = false;
|
||||
justExpirencedLongNight = true;
|
||||
remainingTicks = 0;
|
||||
world.getGameRules().getRule(GameRules.RULE_DAYLIGHT).set(doDaylightCycle, world.getServer());
|
||||
world.getGameRules().getRule(GameRules.RULE_DO_TRADER_SPAWNING).set(doTraderSpawning, world.getServer());
|
||||
}
|
||||
|
||||
public static boolean isRunning() {
|
||||
return isAtLongNight;
|
||||
}
|
||||
}
|
||||
@@ -6,18 +6,18 @@ import io.ib67.sfcraft.subserver.RoomSession;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public interface RoomRegistry {
|
||||
Collection<? extends Room> getRooms();
|
||||
|
||||
Room getRoomBy(ResourceLocation identifier);
|
||||
Room getRoomBy(Identifier identifier);
|
||||
|
||||
RoomSession getRoomBy(UUID player);
|
||||
|
||||
<T extends Room> T createRoomOf(Class<T> type, ResourceLocation roomId, ServerPlayer issuer, String... arguments);
|
||||
<T extends Room> T createRoomOf(Class<T> type, Identifier roomId, ServerPlayer issuer, String... arguments);
|
||||
|
||||
boolean isRoomWorld(ResourceKey<Level> world);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class SimpleRandomEventRegistry implements RandomEventRegistry {
|
||||
private boolean shutdown;
|
||||
|
||||
protected SimpleRandomEventRegistry() {
|
||||
ServerTickEvents.END_WORLD_TICK.register(this::afterWorldTick);
|
||||
ServerTickEvents.END_LEVEL_TICK.register(this::afterWorldTick);
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register(this::onShutdown);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class SimpleRoomRegistry implements RoomRegistry {
|
||||
private final ConcurrentMap<ResourceLocation, Room> rooms = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<Identifier, Room> rooms = new ConcurrentHashMap<>();
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final Map<Class<?>, RoomFactory<?>> factories = new HashMap<>();
|
||||
private final Set<ResourceKey<Level>> roomWorlds = new HashSet<>();
|
||||
@@ -25,7 +25,7 @@ public class SimpleRoomRegistry implements RoomRegistry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Room getRoomBy(ResourceLocation identifier) {
|
||||
public Room getRoomBy(Identifier identifier) {
|
||||
return rooms.get(identifier);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class SimpleRoomRegistry implements RoomRegistry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Room> T createRoomOf(Class<T> type, ResourceLocation roomId, ServerPlayer issuer, String... arguments) {
|
||||
public <T extends Room> T createRoomOf(Class<T> type, Identifier roomId, ServerPlayer issuer, String... arguments) {
|
||||
if (getRoomBy(roomId) != null) {
|
||||
throw new IllegalArgumentException("duplicate room id: " + roomId);
|
||||
}
|
||||
|
||||
@@ -6,15 +6,15 @@ 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;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
public record RequestedRoom(
|
||||
ResourceLocation identifier,
|
||||
Identifier identifier,
|
||||
String profileName,
|
||||
UUID profileUuid
|
||||
) {
|
||||
public static final StreamCodec<ByteBuf, RequestedRoom> PACKET_CODEC = StreamCodec.composite(
|
||||
ResourceLocation.STREAM_CODEC, RequestedRoom::identifier,
|
||||
Identifier.STREAM_CODEC, RequestedRoom::identifier,
|
||||
ByteBufCodecs.STRING_UTF8, RequestedRoom::profileName,
|
||||
UUIDUtil.STREAM_CODEC, RequestedRoom::profileUuid,
|
||||
RequestedRoom::new
|
||||
|
||||
@@ -13,7 +13,7 @@ import net.minecraft.network.PacketSendListener;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.common.ClientboundStoreCookiePacket;
|
||||
import net.minecraft.network.protocol.common.ClientboundTransferPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.CommonColors;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class RoomTeleporter {
|
||||
@Inject
|
||||
private SFConfig config;
|
||||
|
||||
public static final ResourceLocation ROOM_COOKIE = ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "room");
|
||||
public static final Identifier ROOM_COOKIE = Identifier.fromNamespaceAndPath(SFCraft.MOD_ID, "room");
|
||||
|
||||
public void teleportTo(Room room, ServerPlayer player) {
|
||||
if (roomModule.isVirtual(player.getUUID())) {
|
||||
@@ -39,7 +39,8 @@ public class RoomTeleporter {
|
||||
var finalUuid = roomModule.generateIdForRoom(player.getGameProfile(), player.getName().tryCollapseToString(), room.getServerIdentifier());
|
||||
var sess = room.getPlayerManager().createSessionFor(finalUuid);
|
||||
var name = player.getName().tryCollapseToString();
|
||||
if (player.getServer().getLevel(sess.getSpawnPosition().dimension()) == null) {
|
||||
|
||||
if (player.level().getServer().getLevel(sess.getSpawnPosition().dimension()) == null) {
|
||||
throw new IllegalStateException("world isn't exist");
|
||||
}
|
||||
var networkHandler = player.connection;
|
||||
|
||||
@@ -9,13 +9,13 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class CreativeSpaceRoom implements Room {
|
||||
public static final ResourceKey<Level> WORLD = ResourceKey.create(Registries.DIMENSION, ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "playground"));
|
||||
public static final ResourceLocation IDENTIFIER = ResourceLocation.fromNamespaceAndPath(SFCraft.MOD_ID, "creative_space");
|
||||
public static final ResourceKey<Level> WORLD = ResourceKey.create(Registries.DIMENSION, Identifier.fromNamespaceAndPath(SFCraft.MOD_ID, "playground"));
|
||||
public static final Identifier IDENTIFIER = Identifier.fromNamespaceAndPath(SFCraft.MOD_ID, "creative_space");
|
||||
public static final BlockPos SPAWN_POS = new BlockPos(0, 66, 0);
|
||||
@Getter
|
||||
private final RoomPlayerManager playerManager;
|
||||
@@ -32,7 +32,7 @@ public class CreativeSpaceRoom implements Room {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getServerIdentifier() {
|
||||
public Identifier getServerIdentifier() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package io.ib67.sfcraft.subserver;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
public interface Room {
|
||||
ResourceLocation getServerIdentifier();
|
||||
Identifier getServerIdentifier();
|
||||
|
||||
RoomPlayerManager getPlayerManager();
|
||||
|
||||
|
||||
@@ -10,9 +10,13 @@ import io.ib67.sfcraft.geoip.GeoIPService;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundSoundPacket;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.CropBlock;
|
||||
@@ -37,7 +41,7 @@ public class Helper {
|
||||
public static boolean canBack(ServerPlayer player) {
|
||||
if (!SFConsts.COMMAND_BACK.hasPermission(player)) return false;
|
||||
var pos = player.getLastDeathLocation().get();
|
||||
var wld = player.getServer().getLevel(pos.dimension());
|
||||
var wld = player.level().getServer().getLevel(pos.dimension());
|
||||
var _pos = pos.pos();
|
||||
if (wld == null) return false;
|
||||
var nearby = wld.getNearestPlayer(_pos.getX(), _pos.getY(), _pos.getZ(), 100, true);
|
||||
@@ -106,6 +110,20 @@ public class Helper {
|
||||
|| block instanceof CropBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a sound only to the given player, at their own position.
|
||||
* Reproduces the pre-26.2 {@code ServerPlayer#playNotifySound}.
|
||||
*/
|
||||
public static void playNotifySound(ServerPlayer player, SoundEvent sound, SoundSource source, float volume, float pitch) {
|
||||
player.connection.send(new ClientboundSoundPacket(
|
||||
BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound),
|
||||
source,
|
||||
player.getX(), player.getY(), player.getZ(),
|
||||
volume, pitch,
|
||||
player.getRandom().nextLong()
|
||||
));
|
||||
}
|
||||
|
||||
public static String hideIp(InetAddress addr) {
|
||||
var _addr = addr.getHostAddress();
|
||||
var q = _addr.split("\\.");
|
||||
|
||||
@@ -24,7 +24,7 @@ public record Permission<T extends Entity>(String key, boolean byDefault) {
|
||||
|
||||
private boolean check(T t, String permission){
|
||||
if(t instanceof Player player) {
|
||||
if (player.getTags().contains(permission)){
|
||||
if (player.entityTags().contains(permission)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
accessWidener v2 named
|
||||
accessWidener v2 official
|
||||
accessible method net/minecraft/nbt/ListTag <init> (Ljava/util/List;)V
|
||||
extendable class net/minecraft/nbt/ListTag
|
||||
Reference in new issue
Block a user