forked from SteamWar/SteamWar
Cleanup SpigotCore
This commit is contained in:
@@ -25,6 +25,21 @@ tasks.compileJava {
|
||||
options.isWarnings = false
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.compilerArgs.addAll(listOf(
|
||||
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"
|
||||
))
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
jvmArgs("--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.classindex)
|
||||
annotationProcessor(libs.classindex)
|
||||
@@ -32,11 +47,15 @@ dependencies {
|
||||
compileOnly(project(":CommandFramework", "default"))
|
||||
compileOnly(project(":SpigotCore:CRIUDummy", "default"))
|
||||
|
||||
compileOnly(libs.worldedit12)
|
||||
compileOnly(libs.fawe21)
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
compileOnly(libs.paperapi21)
|
||||
compileOnly(libs.nms21)
|
||||
compileOnly(libs.authlib2)
|
||||
compileOnly(libs.datafixer)
|
||||
compileOnly(libs.netty)
|
||||
compileOnly(libs.authlib)
|
||||
compileOnly(libs.brigadier)
|
||||
compileOnly(libs.fastutil)
|
||||
|
||||
implementation(libs.anvilgui)
|
||||
|
||||
@@ -19,28 +19,100 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.minecraft.world.entity.PositionMoveRotation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BountifulWrapper {
|
||||
private BountifulWrapper() {}
|
||||
public static final BountifulWrapper impl = new BountifulWrapper();
|
||||
|
||||
public static final IBountifulWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public void playPling(Player player) {
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1);
|
||||
}
|
||||
|
||||
public interface IBountifulWrapper {
|
||||
void playPling(Player player);
|
||||
public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) {
|
||||
if(type == ChatMessageType.CHAT)
|
||||
type = ChatMessageType.SYSTEM;
|
||||
|
||||
void sendMessage(Player player, ChatMessageType type, BaseComponent... msg);
|
||||
player.spigot().sendMessage(type, msg);
|
||||
}
|
||||
|
||||
Object getDataWatcherObject(int index, Class<?> type);
|
||||
Object getDataWatcherItem(Object dataWatcherObject, Object value);
|
||||
private static final Class<?> dataWatcherObject = Reflection.getClass("net.minecraft.network.syncher.EntityDataAccessor");
|
||||
private static final Class<?> dataWatcherRegistry = Reflection.getClass("net.minecraft.network.syncher.EntityDataSerializers");
|
||||
private static final Class<?> dataWatcherSerializer = Reflection.getClass("net.minecraft.network.syncher.EntityDataSerializer");
|
||||
private static final Reflection.Constructor dataWatcherObjectConstructor = Reflection.getConstructor(dataWatcherObject, int.class, dataWatcherSerializer);
|
||||
public Object getDataWatcherObject(int index, Class<?> type) {
|
||||
return dataWatcherObjectConstructor.invoke(index, Reflection.getField(dataWatcherRegistry, dataWatcherSerializer, 0, type).get(null));
|
||||
}
|
||||
|
||||
PositionSetter getPositionSetter(Class<?> packetClass, int fieldOffset);
|
||||
PositionSetter getRelMoveSetter(Class<?> packetClass);
|
||||
UUIDSetter getUUIDSetter(Class<?> packetClass);
|
||||
private static final Class<?> item = Reflection.getClass("net.minecraft.network.syncher.SynchedEntityData$DataItem");
|
||||
private static final Reflection.Constructor itemConstructor = Reflection.getConstructor(item, dataWatcherObject, Object.class);
|
||||
public Object getDataWatcherItem(Object dwo, Object value) {
|
||||
return itemConstructor.invoke(dwo, value);
|
||||
}
|
||||
|
||||
public BountifulWrapper.PositionSetter getPositionSetter(Class<?> packetClass, int fieldOffset) {
|
||||
try {
|
||||
Reflection.Field<PositionMoveRotation> field = Reflection.getField(packetClass, PositionMoveRotation.class, 0);
|
||||
|
||||
return (packet, x, y, z, pitch, yaw) -> {
|
||||
PositionMoveRotation pos = field.get(packet);
|
||||
|
||||
field.set(packet, new PositionMoveRotation(new Vec3(x, y, z), pos.deltaMovement(), yaw, pitch));
|
||||
};
|
||||
} catch (IllegalArgumentException e) {
|
||||
Reflection.Field<Double> posX = Reflection.getField(packetClass, double.class, fieldOffset);
|
||||
Reflection.Field<Double> posY = Reflection.getField(packetClass, double.class, fieldOffset+1);
|
||||
Reflection.Field<Double> posZ = Reflection.getField(packetClass, double.class, fieldOffset+2);
|
||||
boolean isByteClass = packetClass.getSimpleName().contains("PacketPlayOutEntityTeleport") || packetClass.getSimpleName().contains("PacketPlayOutNamedEntitySpawn");
|
||||
Class<?> pitchYawType = isByteClass ? byte.class : int.class;
|
||||
Reflection.Field<?> lookYaw = Reflection.getField(packetClass, pitchYawType, isByteClass ? 0 : 1);
|
||||
Reflection.Field<?> lookPitch = Reflection.getField(packetClass, pitchYawType, isByteClass ? 1 : 2);
|
||||
|
||||
return (packet, x, y, z, pitch, yaw) -> {
|
||||
posX.set(packet, x);
|
||||
posY.set(packet, y);
|
||||
posZ.set(packet, z);
|
||||
if (isByteClass) {
|
||||
lookYaw.set(packet, (byte) (yaw*256/360));
|
||||
lookPitch.set(packet, (byte) (pitch*256/360));
|
||||
} else {
|
||||
lookYaw.set(packet, (int) (yaw*256/360));
|
||||
lookPitch.set(packet, (int) (pitch*256/360));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BountifulWrapper.PositionSetter getRelMoveSetter(Class<?> packetClass) {
|
||||
Class<?> type = Core.getVersion() > 12 ? short.class : int.class;
|
||||
int fieldOffset = Core.getVersion() > 12 ? 0 : 1;
|
||||
Reflection.Field<?> moveX = Reflection.getField(packetClass, type, 0 + fieldOffset);
|
||||
Reflection.Field<?> moveY = Reflection.getField(packetClass, type, 1 + fieldOffset);
|
||||
Reflection.Field<?> moveZ = Reflection.getField(packetClass, type, 2 + fieldOffset);
|
||||
Reflection.Field<Byte> moveYaw = Reflection.getField(packetClass, byte.class, 0);
|
||||
Reflection.Field<Byte> movePitch = Reflection.getField(packetClass, byte.class, 1);
|
||||
|
||||
return (packet, x, y, z, pitch, yaw) -> {
|
||||
moveX.set(packet, (short)(x*4096));
|
||||
moveY.set(packet, (short)(y*4096));
|
||||
moveZ.set(packet, (short)(z*4096));
|
||||
moveYaw.set(packet, (byte)(yaw*256/360));
|
||||
movePitch.set(packet, (byte)(pitch*256/360));
|
||||
};
|
||||
}
|
||||
|
||||
public BountifulWrapper.UUIDSetter getUUIDSetter(Class<?> packetClass) {
|
||||
Reflection.Field<UUID> uuidField = Reflection.getField(packetClass, UUID.class, 0);
|
||||
|
||||
return uuidField::set;
|
||||
}
|
||||
|
||||
public interface PositionSetter {
|
||||
|
||||
@@ -19,11 +19,26 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
public interface ChatWrapper {
|
||||
ChatWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.contents.PlainTextContents;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
Object stringToChatComponent(String text);
|
||||
public class ChatWrapper {
|
||||
public static final ChatWrapper impl = new ChatWrapper();
|
||||
|
||||
Object getDataWatcherPacket(int entityId, Object... dataWatcherKeyValues);
|
||||
public Object stringToChatComponent(String text) {
|
||||
return MutableComponent.create(PlainTextContents.create(text));
|
||||
}
|
||||
|
||||
public Object getDataWatcherPacket(int entityId, Object... dataWatcherKeyValues) {
|
||||
ArrayList<SynchedEntityData.DataValue<?>> nativeWatchers = new ArrayList<>(1);
|
||||
for(int i = 0; i < dataWatcherKeyValues.length; i+=2) {
|
||||
nativeWatchers.add(((SynchedEntityData.DataItem<?>) BountifulWrapper.impl.getDataWatcherItem(dataWatcherKeyValues[i], dataWatcherKeyValues[i+1])).value());
|
||||
}
|
||||
|
||||
return new ClientboundSetEntityDataPacket(entityId, nativeWatchers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,22 +19,20 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@UtilityClass
|
||||
public class CommandRemover {
|
||||
private static final Reflection.Field<SimpleCommandMap> commandMap = Reflection.getField("org.bukkit.craftbukkit.CraftServer", "commandMap", SimpleCommandMap.class);
|
||||
private static final Reflection.Field<Map> knownCommands = Reflection.getField(SimpleCommandMap.class, "knownCommands", Map.class);
|
||||
private static final Map<String, Command> knownCommands = ((CraftServer) Bukkit.getServer()).getCommandMap().getKnownCommands();
|
||||
|
||||
public static void removeAll(String... cmds) {
|
||||
Map<String, Command> knownCmds = knownCommands.get(commandMap.get(Bukkit.getServer()));
|
||||
for (String cmd : cmds) {
|
||||
knownCmds.remove(cmd.toLowerCase());
|
||||
knownCommands.remove(cmd.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,11 @@ package de.steamwar.core;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.command.*;
|
||||
import de.steamwar.core.authlib.SteamwarGameProfileRepository;
|
||||
import de.steamwar.core.events.AntiNocom;
|
||||
import de.steamwar.core.events.ChattingEvent;
|
||||
import de.steamwar.core.events.PlayerJoinedEvent;
|
||||
import de.steamwar.core.events.WorldLoadEvent;
|
||||
import de.steamwar.command.SWCommandUtils;
|
||||
import de.steamwar.command.SWTypeMapperCreator;
|
||||
import de.steamwar.command.TabCompletionCache;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
import de.steamwar.core.authlib.SteamwarGameProfileRepository;
|
||||
import de.steamwar.linkage.AbstractLinker;
|
||||
import de.steamwar.linkage.SpigotLinker;
|
||||
import de.steamwar.message.Message;
|
||||
@@ -54,6 +49,7 @@ public class Core extends JavaPlugin {
|
||||
|
||||
public static final Message MESSAGE = new Message("SpigotCore", Core.class.getClassLoader());
|
||||
|
||||
@Deprecated
|
||||
public static int getVersion(){
|
||||
return Reflection.MAJOR_VERSION;
|
||||
}
|
||||
@@ -108,9 +104,8 @@ public class Core extends JavaPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().registerEvents(RecipeDiscoverWrapper.impl, this);
|
||||
if(!Statement.productionDatabase()) {
|
||||
getServer().getPluginManager().registerEvents(LocaleChangeWrapper.impl, this);
|
||||
getServer().getPluginManager().registerEvents(new LocaleChangeWrapper(), this);
|
||||
}
|
||||
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new NetworkReceiver());
|
||||
|
||||
@@ -19,14 +19,18 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import org.bukkit.craftbukkit.CraftChunk;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CraftbukkitWrapper {
|
||||
private CraftbukkitWrapper() {}
|
||||
public static final CraftbukkitWrapper impl = new CraftbukkitWrapper();
|
||||
|
||||
public static final ICraftbukkitWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
|
||||
public interface ICraftbukkitWrapper {
|
||||
void sendChunk(Player p, int chunkX, int chunkZ);
|
||||
public void sendChunk(Player p, int chunkX, int chunkZ) {
|
||||
LevelChunk chunk = (LevelChunk) ((CraftChunk) p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(ChunkStatus.FULL);
|
||||
TinyProtocol.instance.sendPacket(p, new ClientboundLevelChunkWithLightPacket(chunk, chunk.level.getLightEngine(), null, null, true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package de.steamwar.core;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.sql.SWException;
|
||||
import org.spigotmc.WatchdogThread;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
@@ -39,10 +40,8 @@ public class ErrorHandler extends Handler {
|
||||
public ErrorHandler(){
|
||||
Logger.getLogger("").addHandler(this);
|
||||
|
||||
Class<?> watchdogThread = Reflection.getClass("org.spigotmc.WatchdogThread");
|
||||
Reflection.Field<?> getInstance = Reflection.getField(watchdogThread, watchdogThread, 0);
|
||||
Thread watchdog = (Thread) getInstance.get(null);
|
||||
watchdogThreadId = watchdog.getId();
|
||||
Reflection.Field<WatchdogThread> getInstance = Reflection.getField(WatchdogThread.class, WatchdogThread.class, 0);
|
||||
watchdogThreadId = getInstance.get(null).getId();
|
||||
}
|
||||
|
||||
void unregister() {
|
||||
|
||||
@@ -19,38 +19,343 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import de.steamwar.Reflection;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetScorePacket;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FlatteningWrapper {
|
||||
private FlatteningWrapper() {}
|
||||
|
||||
public static final Class<?> scoreboardObjective = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetObjectivePacket");
|
||||
public static final Class<?> scoreboardScore = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetScorePacket");
|
||||
public static final FlatteningWrapper impl = new FlatteningWrapper();
|
||||
|
||||
public static final IFlatteningWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
private static final Map<String, Material> renamedLegacy = new HashMap<>();
|
||||
|
||||
public interface IFlatteningWrapper {
|
||||
void setScoreboardTitle(Object packet, String title);
|
||||
void setScoreAction(Object packet);
|
||||
static{
|
||||
renamedLegacy.put("WOOD", Material.OAK_WOOD);
|
||||
renamedLegacy.put("SAPLING", Material.OAK_SAPLING);
|
||||
renamedLegacy.put("STATIONARY_WATER", Material.WATER);
|
||||
renamedLegacy.put("STATIONARY_LAVA", Material.LAVA);
|
||||
renamedLegacy.put("LOG", Material.OAK_LOG);
|
||||
renamedLegacy.put("LEAVES", Material.OAK_LEAVES);
|
||||
renamedLegacy.put("BED_BLOCK", Material.RED_BED);
|
||||
renamedLegacy.put("BED", Material.RED_BED);
|
||||
renamedLegacy.put("PISTON_STICKY_BASE", Material.STICKY_PISTON);
|
||||
renamedLegacy.put("WEB", Material.COBWEB);
|
||||
renamedLegacy.put("LONG_GRASS", Material.TALL_GRASS);
|
||||
renamedLegacy.put("PISTON_BASE", Material.PISTON);
|
||||
renamedLegacy.put("PISTON_EXTENSION", Material.PISTON_HEAD);
|
||||
renamedLegacy.put("WOOL", Material.WHITE_WOOL);
|
||||
renamedLegacy.put("PISTON_MOVING_PIECE", Material.MOVING_PISTON);
|
||||
renamedLegacy.put("YELLOW_FLOWER", Material.DANDELION);
|
||||
renamedLegacy.put("RED_ROSE", Material.POPPY);
|
||||
renamedLegacy.put("DOUBLE_STEP", Material.SMOOTH_STONE);
|
||||
renamedLegacy.put("STEP", Material.SMOOTH_STONE_SLAB);
|
||||
renamedLegacy.put("MOB_SPAWNER", Material.SPAWNER);
|
||||
renamedLegacy.put("WOOD_STAIRS", Material.OAK_STAIRS);
|
||||
renamedLegacy.put("WORKBENCH", Material.CRAFTING_TABLE);
|
||||
renamedLegacy.put("CROPS", Material.WHEAT_SEEDS);
|
||||
renamedLegacy.put("SEEDS", Material.WHEAT_SEEDS);
|
||||
renamedLegacy.put("SOIL", Material.FARMLAND);
|
||||
renamedLegacy.put("BURNING_FURNACE", Material.FURNACE);
|
||||
renamedLegacy.put("SIGN_POST", Material.OAK_SIGN);
|
||||
renamedLegacy.put("SIGN", Material.OAK_SIGN);
|
||||
renamedLegacy.put("WOODEN_DOOR", Material.OAK_DOOR);
|
||||
renamedLegacy.put("WOOD_DOOR", Material.OAK_DOOR);
|
||||
renamedLegacy.put("RAILS", Material.RAIL);
|
||||
renamedLegacy.put("WALL_SIGN", Material.OAK_WALL_SIGN);
|
||||
renamedLegacy.put("STONE_PLATE", Material.STONE_PRESSURE_PLATE);
|
||||
renamedLegacy.put("WOOD_PLATE", Material.OAK_PRESSURE_PLATE);
|
||||
renamedLegacy.put("GLOWING_REDSTONE_ORE", Material.REDSTONE_ORE);
|
||||
renamedLegacy.put("REDSTONE_TORCH_OFF", Material.REDSTONE_TORCH);
|
||||
renamedLegacy.put("REDSTONE_TORCH_ON", Material.REDSTONE_TORCH);
|
||||
renamedLegacy.put("IRON_DOOR_BLOCK", Material.IRON_DOOR);
|
||||
renamedLegacy.put("SUGAR_CANE_BLOCK", Material.SUGAR_CANE);
|
||||
renamedLegacy.put("CAKE_BLOCK", Material.CAKE);
|
||||
renamedLegacy.put("MELON_BLOCK", Material.MELON);
|
||||
renamedLegacy.put("BEETROOT_BLOCK", Material.BEETROOT);
|
||||
renamedLegacy.put("FENCE", Material.OAK_FENCE);
|
||||
renamedLegacy.put("PORTAL", Material.NETHER_PORTAL);
|
||||
renamedLegacy.put("DIODE_BLOCK_OFF", Material.REPEATER);
|
||||
renamedLegacy.put("DIODE_BLOCK_ON", Material.REPEATER);
|
||||
renamedLegacy.put("DIODE", Material.REPEATER);
|
||||
renamedLegacy.put("STAINED_GLASS", Material.WHITE_STAINED_GLASS);
|
||||
renamedLegacy.put("TRAP_DOOR", Material.OAK_TRAPDOOR);
|
||||
renamedLegacy.put("MONSTER_EGGS", Material.SKELETON_SPAWN_EGG);
|
||||
renamedLegacy.put("MONSTER_EGG", Material.SKELETON_SPAWN_EGG);
|
||||
renamedLegacy.put("SMOOTH_BRICK", Material.STONE_BRICKS);
|
||||
renamedLegacy.put("HUGE_MUSHROOM_1", Material.MUSHROOM_STEM);
|
||||
renamedLegacy.put("HUGE_MUSHROOM_2", Material.RED_MUSHROOM);
|
||||
renamedLegacy.put("IRON_FENCE", Material.IRON_BARS);
|
||||
renamedLegacy.put("THIN_GLASS", Material.GLASS_PANE);
|
||||
renamedLegacy.put("FENCE_GATE", Material.OAK_FENCE_GATE);
|
||||
renamedLegacy.put("SMOOTH_STAIRS", Material.STONE_BRICK_STAIRS);
|
||||
renamedLegacy.put("MYCEL", Material.MYCELIUM);
|
||||
renamedLegacy.put("WATER_LILY", Material.LILY_PAD);
|
||||
renamedLegacy.put("NETHER_FENCE", Material.NETHER_BRICK_FENCE);
|
||||
renamedLegacy.put("NETHER_WARTS", Material.NETHER_WART);
|
||||
renamedLegacy.put("NETHER_STALK", Material.NETHER_WART);
|
||||
renamedLegacy.put("ENCHANTMENT_TABLE", Material.ENCHANTING_TABLE);
|
||||
renamedLegacy.put("ENDER_PORTAL", Material.END_PORTAL);
|
||||
renamedLegacy.put("ENDER_PORTAL_FRAME", Material.END_PORTAL_FRAME);
|
||||
renamedLegacy.put("ENDER_STONE", Material.END_STONE);
|
||||
renamedLegacy.put("REDSTONE_LAMP_OFF", Material.REDSTONE_LAMP);
|
||||
renamedLegacy.put("REDSTONE_LAMP_ON", Material.REDSTONE_LAMP);
|
||||
renamedLegacy.put("WOOD_DOUBLE_STEP", Material.OAK_SLAB);
|
||||
renamedLegacy.put("WOOD_STEP", Material.OAK_SLAB);
|
||||
renamedLegacy.put("SPRUCE_WOOD_STAIRS", Material.SPRUCE_STAIRS);
|
||||
renamedLegacy.put("BIRCH_WOOD_STAIRS", Material.BIRCH_STAIRS);
|
||||
renamedLegacy.put("JUNGLE_WOOD_STAIRS", Material.JUNGLE_STAIRS);
|
||||
renamedLegacy.put("COMMAND", Material.COMMAND_BLOCK);
|
||||
renamedLegacy.put("COBBLE_WALL", Material.COBBLESTONE_WALL);
|
||||
renamedLegacy.put("WOOD_BUTTON", Material.OAK_BUTTON);
|
||||
renamedLegacy.put("SKULL", Material.SKELETON_SKULL);
|
||||
renamedLegacy.put("SKULL_ITEM", Material.SKELETON_SKULL);
|
||||
renamedLegacy.put("GOLD_PLATE", Material.LIGHT_WEIGHTED_PRESSURE_PLATE);
|
||||
renamedLegacy.put("IRON_PLATE", Material.HEAVY_WEIGHTED_PRESSURE_PLATE);
|
||||
renamedLegacy.put("REDSTONE_COMPARATOR_OFF", Material.COMPARATOR);
|
||||
renamedLegacy.put("REDSTONE_COMPARATOR_ON", Material.COMPARATOR);
|
||||
renamedLegacy.put("REDSTONE_COMPARATOR", Material.COMPARATOR);
|
||||
renamedLegacy.put("QUARTZ_ORE", Material.QUARTZ);
|
||||
renamedLegacy.put("STAINED_CLAY", Material.WHITE_TERRACOTTA);
|
||||
renamedLegacy.put("STAINED_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE);
|
||||
renamedLegacy.put("LEAVES_2", Material.ACACIA_LEAVES);
|
||||
renamedLegacy.put("LOG_2", Material.ACACIA_LOG);
|
||||
renamedLegacy.put("CARPET", Material.WHITE_CARPET);
|
||||
renamedLegacy.put("HARD_CLAY", Material.TERRACOTTA);
|
||||
renamedLegacy.put("DOUBLE_PLANT", Material.SUNFLOWER);
|
||||
renamedLegacy.put("STANDING_BANNER", Material.WHITE_BANNER);
|
||||
renamedLegacy.put("BANNER", Material.WHITE_BANNER);
|
||||
renamedLegacy.put("WALL_BANNER", Material.WHITE_WALL_BANNER);
|
||||
renamedLegacy.put("DAYLIGHT_DETECTOR_INVERTED", Material.DAYLIGHT_DETECTOR);
|
||||
renamedLegacy.put("DOUBLE_STONE_SLAB2", Material.RED_SANDSTONE_SLAB);
|
||||
renamedLegacy.put("STONE_SLAB2", Material.RED_SANDSTONE_SLAB);
|
||||
renamedLegacy.put("PURPUR_DOUBLE_SLAB", Material.PURPUR_SLAB);
|
||||
renamedLegacy.put("END_BRICKS", Material.END_STONE_BRICKS);
|
||||
renamedLegacy.put("COMMAND_REPEATING", Material.REPEATING_COMMAND_BLOCK);
|
||||
renamedLegacy.put("COMMAND_CHAIN", Material.CHAIN_COMMAND_BLOCK);
|
||||
renamedLegacy.put("MAGMA", Material.MAGMA_BLOCK);
|
||||
renamedLegacy.put("RED_NETHER_BRICK", Material.RED_NETHER_BRICKS);
|
||||
renamedLegacy.put("SILVER_SHULKER_BOX", Material.LIGHT_GRAY_SHULKER_BOX);
|
||||
renamedLegacy.put("SILVER_GLAZED_TERRACOTTA", Material.LIGHT_GRAY_TERRACOTTA);
|
||||
renamedLegacy.put("CONCRETE", Material.WHITE_CONCRETE);
|
||||
renamedLegacy.put("CONCRETE_POWDER", Material.WHITE_CONCRETE_POWDER);
|
||||
renamedLegacy.put("IRON_SPADE", Material.IRON_SHOVEL);
|
||||
renamedLegacy.put("WOOD_SWORD", Material.WOODEN_SWORD);
|
||||
renamedLegacy.put("WOOD_SPADE", Material.WOODEN_SHOVEL);
|
||||
renamedLegacy.put("WOOD_PICKAXE", Material.WOODEN_PICKAXE);
|
||||
renamedLegacy.put("WOOD_AXE", Material.WOODEN_AXE);
|
||||
renamedLegacy.put("STONE_SPADE", Material.STONE_SHOVEL);
|
||||
renamedLegacy.put("DIAMOND_SPADE", Material.DIAMOND_SHOVEL);
|
||||
renamedLegacy.put("MUSHROOM_SOUP", Material.MUSHROOM_STEW);
|
||||
renamedLegacy.put("GOLD_SWORD", Material.GOLDEN_SWORD);
|
||||
renamedLegacy.put("GOLD_SPADE", Material.GOLDEN_SHOVEL);
|
||||
renamedLegacy.put("GOLD_PICKAXE", Material.GOLDEN_PICKAXE);
|
||||
renamedLegacy.put("GOLD_AXE", Material.GOLDEN_AXE);
|
||||
renamedLegacy.put("SULPHUR", Material.GUNPOWDER);
|
||||
renamedLegacy.put("WOOD_HOE", Material.WOODEN_HOE);
|
||||
renamedLegacy.put("GOLD_HOE", Material.GOLDEN_HOE);
|
||||
renamedLegacy.put("GOLD_HELMET", Material.GOLDEN_HELMET);
|
||||
renamedLegacy.put("GOLD_CHESTPLATE", Material.GOLDEN_CHESTPLATE);
|
||||
renamedLegacy.put("GOLD_LEGGINGS", Material.GOLDEN_LEGGINGS);
|
||||
renamedLegacy.put("GOLD_BOOTS", Material.GOLDEN_BOOTS);
|
||||
renamedLegacy.put("PORK", Material.PORKCHOP);
|
||||
renamedLegacy.put("GRILLED_PORK", Material.COOKED_PORKCHOP);
|
||||
renamedLegacy.put("SNOW_BALL", Material.SNOWBALL);
|
||||
renamedLegacy.put("BOAT", Material.OAK_BOAT);
|
||||
renamedLegacy.put("CLAY_BRICK", Material.BRICKS);
|
||||
renamedLegacy.put("STORAGE_MINECART", Material.CHEST_MINECART);
|
||||
renamedLegacy.put("POWERED_MINECART", Material.FURNACE_MINECART);
|
||||
renamedLegacy.put("WATCH", Material.CLOCK);
|
||||
renamedLegacy.put("RAW_FISH", Material.SALMON);
|
||||
renamedLegacy.put("COOKED_FISH", Material.COOKED_SALMON);
|
||||
renamedLegacy.put("INK_SACK", Material.INK_SAC);
|
||||
renamedLegacy.put("RAW_BEEF", Material.BEEF);
|
||||
renamedLegacy.put("RAW_CHICKEN", Material.CHICKEN);
|
||||
renamedLegacy.put("EYE_OF_ENDER", Material.ENDER_EYE);
|
||||
renamedLegacy.put("SPECKLED_MELON", Material.GLISTERING_MELON_SLICE);
|
||||
renamedLegacy.put("EXP_BOTTLE", Material.EXPERIENCE_BOTTLE);
|
||||
renamedLegacy.put("FIREBALL", Material.FIRE_CHARGE);
|
||||
renamedLegacy.put("BOOK_AND_QUILL", Material.WRITABLE_BOOK);
|
||||
renamedLegacy.put("FLOWER_POT_ITEM", Material.FLOWER_POT);
|
||||
renamedLegacy.put("EMPTY_MAP", Material.MAP);
|
||||
renamedLegacy.put("BREWING_STAND_ITEM", Material.BREWING_STAND);
|
||||
renamedLegacy.put("CAULDRON_ITEM", Material.CAULDRON);
|
||||
renamedLegacy.put("CARROT_ITEM", Material.CARROT);
|
||||
renamedLegacy.put("POTATO_ITEM", Material.POTATO);
|
||||
renamedLegacy.put("SPRUCE_DOOR_ITEM", Material.SPRUCE_DOOR);
|
||||
renamedLegacy.put("BIRCH_DOOR_ITEM", Material.BIRCH_DOOR);
|
||||
renamedLegacy.put("JUNGLE_DOOR_ITEM", Material.JUNGLE_DOOR);
|
||||
renamedLegacy.put("ACACIA_DOOR_ITEM", Material.ACACIA_DOOR);
|
||||
renamedLegacy.put("DARK_OAK_DOOR_ITEM", Material.DARK_OAK_DOOR);
|
||||
renamedLegacy.put("CARROT_STICK", Material.CARROT_ON_A_STICK);
|
||||
renamedLegacy.put("FIREWORK", Material.FIREWORK_ROCKET);
|
||||
renamedLegacy.put("FIREWORK_CHARGE", Material.FIREWORK_STAR);
|
||||
renamedLegacy.put("NETHER_BRICK_ITEM", Material.NETHER_BRICKS);
|
||||
renamedLegacy.put("EXPLOSIVE_MINECART", Material.TNT_MINECART);
|
||||
renamedLegacy.put("IRON_BARDING", Material.IRON_HORSE_ARMOR);
|
||||
renamedLegacy.put("GOLD_BARDING", Material.GOLDEN_HORSE_ARMOR);
|
||||
renamedLegacy.put("DIAMOND_BARDING", Material.DIAMOND_HORSE_ARMOR);
|
||||
renamedLegacy.put("LEASH", Material.LEAD);
|
||||
renamedLegacy.put("COMMAND_MINECART", Material.COMMAND_BLOCK_MINECART);
|
||||
renamedLegacy.put("CHORUS_FRUIT_POPPED", Material.POPPED_CHORUS_FRUIT);
|
||||
renamedLegacy.put("DRAGONS_BREATH", Material.DRAGON_BREATH);
|
||||
renamedLegacy.put("BOAT_SPRUCE", Material.SPRUCE_BOAT);
|
||||
renamedLegacy.put("BOAT_BIRCH", Material.BIRCH_BOAT);
|
||||
renamedLegacy.put("BOAT_JUNGLE", Material.JUNGLE_BOAT);
|
||||
renamedLegacy.put("BOAT_ACACIA", Material.ACACIA_BOAT);
|
||||
renamedLegacy.put("BOAT_DARK_OAK", Material.DARK_OAK_BOAT);
|
||||
renamedLegacy.put("TOTEM", Material.TOTEM_OF_UNDYING);
|
||||
renamedLegacy.put("GOLD_RECORD", Material.MUSIC_DISC_13);
|
||||
renamedLegacy.put("GREEN_RECORD", Material.MUSIC_DISC_CAT);
|
||||
renamedLegacy.put("RECORD_3", Material.MUSIC_DISC_BLOCKS);
|
||||
renamedLegacy.put("RECORD_4", Material.MUSIC_DISC_CHIRP);
|
||||
renamedLegacy.put("RECORD_5", Material.MUSIC_DISC_FAR);
|
||||
renamedLegacy.put("RECORD_6", Material.MUSIC_DISC_MALL);
|
||||
renamedLegacy.put("RECORD_7", Material.MUSIC_DISC_MELLOHI);
|
||||
renamedLegacy.put("RECORD_8", Material.MUSIC_DISC_STAL);
|
||||
renamedLegacy.put("RECORD_9", Material.MUSIC_DISC_STRAD);
|
||||
renamedLegacy.put("RECORD_10", Material.MUSIC_DISC_WARD);
|
||||
renamedLegacy.put("RECORD_11", Material.MUSIC_DISC_11);
|
||||
renamedLegacy.put("RECORD_12", Material.MUSIC_DISC_WAIT);
|
||||
}
|
||||
|
||||
Material getMaterial(String material);
|
||||
Material getDye(int colorCode);
|
||||
ItemStack setSkullOwner(String player);
|
||||
private static final Reflection.Field<?> scoreboardName = Reflection.getField(ClientboundSetObjectivePacket.class, Reflection.getClass("net.minecraft.network.chat.Component"), 0);
|
||||
public void setScoreboardTitle(Object packet, String title) {
|
||||
scoreboardName.set(packet, ChatWrapper.impl.stringToChatComponent(title));
|
||||
}
|
||||
|
||||
Object getPose(EntityPose pose);
|
||||
void setNamedSpawnPacketDataWatcher(Object packet);
|
||||
Object formatDisplayName(String displayName);
|
||||
private static final Class<?> scoreActionEnum = Core.getVersion() < 21 ? Reflection.getClass("net.minecraft.server.ServerScoreboard$Method") : null;
|
||||
private static final Reflection.Field<?> scoreAction = Core.getVersion() < 21 ? Reflection.getField(ClientboundSetScorePacket.class, scoreActionEnum, 0) : null;
|
||||
private static final Object scoreActionChange = Core.getVersion() < 21 ? scoreActionEnum.getEnumConstants()[0] : null;
|
||||
|
||||
void setSpawnPacketType(Object packet, EntityType type);
|
||||
public void setScoreAction(Object packet) {
|
||||
scoreAction.set(packet, scoreActionChange);
|
||||
}
|
||||
|
||||
int getViewDistance(Player player);
|
||||
public Material getMaterial(String material) {
|
||||
try{
|
||||
return Material.valueOf(material);
|
||||
}catch(IllegalArgumentException e){
|
||||
return renamedLegacy.get(material);
|
||||
}
|
||||
}
|
||||
|
||||
void syncSave(World world);
|
||||
public Material getDye(int colorCode) {
|
||||
switch(colorCode){
|
||||
case 1:
|
||||
return Material.RED_DYE;
|
||||
case 2:
|
||||
return Material.GREEN_DYE;
|
||||
case 3:
|
||||
return Material.BROWN_DYE;
|
||||
case 4:
|
||||
return Material.LAPIS_LAZULI;
|
||||
case 5:
|
||||
return Material.PURPLE_DYE;
|
||||
case 6:
|
||||
return Material.CYAN_DYE;
|
||||
case 7:
|
||||
return Material.LIGHT_GRAY_DYE;
|
||||
case 8:
|
||||
return Material.GRAY_DYE;
|
||||
case 9:
|
||||
return Material.PINK_DYE;
|
||||
case 10:
|
||||
return Material.LIME_DYE;
|
||||
case 11:
|
||||
return Material.YELLOW_DYE;
|
||||
case 12:
|
||||
return Material.LIGHT_BLUE_DYE;
|
||||
case 13:
|
||||
return Material.MAGENTA_DYE;
|
||||
case 14:
|
||||
return Material.ORANGE_DYE;
|
||||
case 15:
|
||||
return Material.WHITE_DYE;
|
||||
default:
|
||||
return Material.BLACK_DYE;
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack setSkullOwner(String player) {
|
||||
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
head.editMeta(SkullMeta.class, skullMeta -> {
|
||||
try {
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.startsWith(".") ? player.substring(1) : player);
|
||||
PlayerProfile playerProfile = offlinePlayer.getPlayerProfile();
|
||||
playerProfile.complete();
|
||||
skullMeta.setPlayerProfile(playerProfile);
|
||||
} catch (Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
return head;
|
||||
}
|
||||
|
||||
protected static final Class<?> entityPose = Reflection.getClass("net.minecraft.world.entity.Pose");
|
||||
protected static final Object shooting = entityPose.getEnumConstants()[16];
|
||||
protected static final Object standing = entityPose.getEnumConstants()[0];
|
||||
protected static final Object swimming = entityPose.getEnumConstants()[3];
|
||||
protected static final Object sneaking = entityPose.getEnumConstants()[5];
|
||||
public Object getPose(FlatteningWrapper.EntityPose pose) {
|
||||
switch (pose) {
|
||||
case SHOOTING:
|
||||
return shooting;
|
||||
case SNEAKING:
|
||||
return sneaking;
|
||||
case SWIMMING:
|
||||
return swimming;
|
||||
case NORMAL:
|
||||
default:
|
||||
return standing;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNamedSpawnPacketDataWatcher(Object packet) {
|
||||
// field not present
|
||||
}
|
||||
|
||||
public Object formatDisplayName(String displayName) {
|
||||
return displayName != null ? Optional.of(ChatWrapper.impl.stringToChatComponent(displayName)) : Optional.empty();
|
||||
}
|
||||
|
||||
private static final Class<?> registryBlocks = Reflection.getClass("net.minecraft.core.DefaultedRegistry");
|
||||
private static final Class<?> entityTypes = Reflection.getClass("net.minecraft.world.entity.EntityType");
|
||||
private static final Object entityTypesRegistry = Reflection.getField(Reflection.getClass(Core.getVersion() > 18 ? "net.minecraft.core.registries.BuiltInRegistries" : "net.minecraft.core.IRegistry"), registryBlocks, 0, entityTypes).get(null);
|
||||
private static final Reflection.Method get = Reflection.getMethod(registryBlocks, null, Reflection.getClass("net.minecraft.resources.ResourceLocation"));
|
||||
private static final Reflection.Field<?> spawnType = Reflection.getField(ProtocolWrapper.spawnPacket, entityTypes, 0);
|
||||
private static final Reflection.Field<?> spawnLivingType = Core.getVersion() > 18 ? spawnType : Reflection.getField(ProtocolWrapper.spawnLivingPacket, int.class, 1);
|
||||
private static final Reflection.Method toMinecraft = Reflection.getMethod("org.bukkit.craftbukkit.util.CraftNamespacedKey", "toMinecraft", NamespacedKey.class);
|
||||
private static final Map<EntityType, Object> types = new HashMap<>();
|
||||
static {
|
||||
types.put(EntityType.ARMOR_STAND, 1);
|
||||
}
|
||||
public void setSpawnPacketType(Object packet, EntityType type) {
|
||||
if(type.isAlive()) {
|
||||
spawnLivingType.set(packet, Core.getVersion() > 18 ? get.invoke(entityTypesRegistry, toMinecraft.invoke(null, type.getKey())) : types.get(type));
|
||||
} else {
|
||||
spawnType.set(packet, get.invoke(entityTypesRegistry, toMinecraft.invoke(null, type.getKey())));
|
||||
}
|
||||
}
|
||||
|
||||
public int getViewDistance(Player player) {
|
||||
return player.getClientViewDistance();
|
||||
}
|
||||
|
||||
private static final Reflection.Method getHandle = Reflection.getMethod("org.bukkit.craftbukkit.CraftWorld", "getHandle");
|
||||
private static final Reflection.Method save = Reflection.getMethod("net.minecraft.server.level.ServerLevel", null, Reflection.getClass("net.minecraft.util.ProgressListener"), boolean.class, boolean.class);
|
||||
public void syncSave(World world) {
|
||||
save.invoke(getHandle.invoke(world), null, true, false);
|
||||
}
|
||||
|
||||
public enum EntityPose {
|
||||
|
||||
@@ -19,8 +19,17 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLocaleChangeEvent;
|
||||
|
||||
public interface LocaleChangeWrapper extends Listener {
|
||||
LocaleChangeWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
import java.util.Locale;
|
||||
|
||||
public class LocaleChangeWrapper implements Listener {
|
||||
|
||||
@EventHandler
|
||||
private void onLocale(PlayerLocaleChangeEvent event) {
|
||||
SteamwarUser.get(event.getPlayer().getUniqueId()).setLocale(Locale.forLanguageTag(event.getLocale()), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,37 +19,50 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
|
||||
public interface ProtocolWrapper {
|
||||
public class ProtocolWrapper {
|
||||
|
||||
Class<?> itemStack = Reflection.getClass("net.minecraft.world.item.ItemStack");
|
||||
Class<?> spawnPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundAddEntityPacket");
|
||||
Class<?> spawnLivingPacket = Core.getVersion() > 18 ? ProtocolWrapper.spawnPacket : Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving");
|
||||
Class<?> equipmentPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket");
|
||||
public static final Class<?> itemStack = Reflection.getClass("net.minecraft.world.item.ItemStack");
|
||||
public static final Class<?> spawnPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundAddEntityPacket");
|
||||
public static final Class<?> spawnLivingPacket = Core.getVersion() > 18 ? ProtocolWrapper.spawnPacket : Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityLiving");
|
||||
public static final Class<?> equipmentPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket");
|
||||
|
||||
Class<?> enumGamemode = Reflection.getClass(Core.getVersion() > 9 ? "net.minecraft.world.level.GameType" : "net.minecraft.WorldSettings$EnumGamemode");
|
||||
Reflection.Method getGameModeById = Reflection.getTypedMethod(enumGamemode, null, enumGamemode, int.class);
|
||||
public static final Class<?> enumGamemode = Reflection.getClass(Core.getVersion() > 9 ? "net.minecraft.world.level.GameType" : "net.minecraft.WorldSettings$EnumGamemode");
|
||||
public static final Reflection.Method getGameModeById = Reflection.getTypedMethod(enumGamemode, null, enumGamemode, int.class);
|
||||
|
||||
// 0: hand, 1: offhand, 2: feet, 3: legs, 4: chest, 5: head
|
||||
Object[] itemSlots = Core.getVersion() > 8 ? Reflection.getClass("net.minecraft.world.entity.EnumItemSlot").getEnumConstants() : new Integer[]{0, 0, 1, 2, 3, 4};
|
||||
public static final Object[] itemSlots = Core.getVersion() > 8 ? Reflection.getClass("net.minecraft.world.entity.EnumItemSlot").getEnumConstants() : new Integer[]{0, 0, 1, 2, 3, 4};
|
||||
|
||||
ProtocolWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public static final ProtocolWrapper impl = new ProtocolWrapper();
|
||||
|
||||
void setEquipmentPacketStack(Object packet, Object slot, Object stack);
|
||||
|
||||
Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode);
|
||||
|
||||
default void initTPSWarp(LongSupplier longSupplier) {
|
||||
Class<?> systemUtils = Reflection.getClass("net.minecraft.Util");
|
||||
Reflection.getField(systemUtils, LongSupplier.class, 0).set(systemUtils, (LongSupplier) () -> System.nanoTime() + longSupplier.getAsLong());
|
||||
public void setEquipmentPacketStack(Object packet, Object slot, Object stack) {
|
||||
ClientboundSetEquipmentPacket setEquipmentPacket = (ClientboundSetEquipmentPacket) packet;
|
||||
setEquipmentPacket.getSlots().add(Pair.of((EquipmentSlot) slot, (ItemStack) stack));
|
||||
}
|
||||
|
||||
enum PlayerInfoAction {
|
||||
public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) {
|
||||
if(action == PlayerInfoAction.REMOVE)
|
||||
return new ClientboundPlayerInfoRemovePacket(Collections.singletonList(profile.getId()));
|
||||
|
||||
return new ClientboundPlayerInfoUpdatePacket(action == PlayerInfoAction.ADD ?
|
||||
EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE) : EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE),
|
||||
Collections.singletonList(new ClientboundPlayerInfoUpdatePacket.Entry(profile.getId(), profile, false, 0, GameType.byId(mode.getValue()), null, false, 0, null)));
|
||||
}
|
||||
|
||||
public enum PlayerInfoAction {
|
||||
ADD,
|
||||
GAMEMODE,
|
||||
REMOVE
|
||||
|
||||
@@ -19,8 +19,15 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import de.steamwar.linkage.Linked;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerRecipeDiscoverEvent;
|
||||
|
||||
public interface RecipeDiscoverWrapper extends Listener {
|
||||
RecipeDiscoverWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
@Linked
|
||||
public class RecipeDiscoverWrapper implements Listener {
|
||||
@EventHandler
|
||||
public void onRecipeDiscover(PlayerRecipeDiscoverEvent e) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
@UtilityClass
|
||||
public class TPSWarpUtils {
|
||||
|
||||
private static long nanoOffset = 0;
|
||||
private static long nanoDOffset = 0;
|
||||
private static BukkitTask bukkitTask = null;
|
||||
|
||||
static {
|
||||
ProtocolWrapper.impl.initTPSWarp(() -> nanoOffset);
|
||||
}
|
||||
|
||||
public static void warp(double tps) {
|
||||
double d = 50 - (50 / (tps / 20.0));
|
||||
nanoDOffset = Math.max(0, (long) (d * 1000000));
|
||||
if (nanoDOffset == 0) {
|
||||
if (bukkitTask == null) return;
|
||||
bukkitTask.cancel();
|
||||
bukkitTask = null;
|
||||
} else if (bukkitTask == null) {
|
||||
bukkitTask = Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> nanoOffset += nanoDOffset, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isWarping() {
|
||||
return nanoDOffset > 0;
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,10 @@ package de.steamwar.core;
|
||||
|
||||
import org.bukkit.Particle;
|
||||
|
||||
public interface TrickyParticleWrapper {
|
||||
public TrickyParticleWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public class TrickyParticleWrapper {
|
||||
public static final TrickyParticleWrapper impl = new TrickyParticleWrapper();
|
||||
|
||||
Particle getVillagerHappy();
|
||||
public Particle getVillagerHappy() {
|
||||
return Particle.HAPPY_VILLAGER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,22 @@ import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
public interface TrickyTrialsWrapper {
|
||||
TrickyTrialsWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public class TrickyTrialsWrapper {
|
||||
public static final TrickyTrialsWrapper impl = new TrickyTrialsWrapper();
|
||||
|
||||
EntityType getTntEntityType();
|
||||
public EntityType getTntEntityType() {
|
||||
return EntityType.TNT;
|
||||
}
|
||||
|
||||
Enchantment getUnbreakingEnchantment();
|
||||
public Enchantment getUnbreakingEnchantment() {
|
||||
return Enchantment.UNBREAKING;
|
||||
}
|
||||
|
||||
Material getTurtleScute();
|
||||
public Material getTurtleScute() {
|
||||
return Material.TURTLE_SCUTE;
|
||||
}
|
||||
|
||||
String getValue(Property property);
|
||||
public String getValue(Property property) {
|
||||
return property.value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@@ -23,6 +23,7 @@ import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@Deprecated
|
||||
public class VersionDependent {
|
||||
private VersionDependent() {}
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class WorldEditRendererFallback {
|
||||
|
||||
private static final int VIEW_DISTANCE = 64;
|
||||
private static final int SQ_VIEW_DISTANCE = VIEW_DISTANCE * VIEW_DISTANCE;
|
||||
|
||||
private static final double STEP_SIZE = 0.5;
|
||||
private static final Vector ONES = new Vector(1, 1, 1);
|
||||
private static final Vector STEPS = new Vector(STEP_SIZE, STEP_SIZE, STEP_SIZE);
|
||||
|
||||
public void draw(Player player, boolean scheduled, boolean clipboard, Vector min, Vector max) {
|
||||
if (!scheduled) return;
|
||||
|
||||
max = max.clone().add(ONES);
|
||||
drawLine(player, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(max.getX(), min.getY(), min.getZ()));
|
||||
drawLine(player, clipboard, new Vector(min.getX(), max.getY(), min.getZ()), new Vector(max.getX(), max.getY(), min.getZ()));
|
||||
drawLine(player, clipboard, new Vector(min.getX(), min.getY(), max.getZ()), new Vector(max.getX(), min.getY(), max.getZ()));
|
||||
drawLine(player, clipboard, new Vector(min.getX(), max.getY(), max.getZ()), new Vector(max.getX(), max.getY(), max.getZ()));
|
||||
|
||||
drawLine(player, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(min.getX(), max.getY(), min.getZ()));
|
||||
drawLine(player, clipboard, new Vector(max.getX(), min.getY(), min.getZ()), new Vector(max.getX(), max.getY(), min.getZ()));
|
||||
drawLine(player, clipboard, new Vector(min.getX(), min.getY(), max.getZ()), new Vector(min.getX(), max.getY(), max.getZ()));
|
||||
drawLine(player, clipboard, new Vector(max.getX(), min.getY(), max.getZ()), new Vector(max.getX(), max.getY(), max.getZ()));
|
||||
|
||||
drawLine(player, clipboard, new Vector(min.getX(), min.getY(), min.getZ()), new Vector(min.getX(), min.getY(), max.getZ()));
|
||||
drawLine(player, clipboard, new Vector(max.getX(), min.getY(), min.getZ()), new Vector(max.getX(), min.getY(), max.getZ()));
|
||||
drawLine(player, clipboard, new Vector(min.getX(), max.getY(), min.getZ()), new Vector(min.getX(), max.getY(), max.getZ()));
|
||||
drawLine(player, clipboard, new Vector(max.getX(), max.getY(), min.getZ()), new Vector(max.getX(), max.getY(), max.getZ()));
|
||||
}
|
||||
|
||||
private void drawLine(Player player, boolean clipboard, Vector min, Vector max) {
|
||||
Particle particle;
|
||||
if (clipboard) {
|
||||
particle = TrickyParticleWrapper.impl.getVillagerHappy();
|
||||
} else {
|
||||
particle = Particle.DRAGON_BREATH;
|
||||
}
|
||||
|
||||
Vector stepSize = max.clone().subtract(min).normalize().multiply(STEPS);
|
||||
while (min.getX() <= max.getX() && min.getY() <= max.getY() && min.getZ() <= max.getZ()) {
|
||||
Location location = player.getLocation();
|
||||
double dx = min.getX() - location.getX();
|
||||
double dy = min.getY() - location.getY();
|
||||
double dz = min.getZ() - location.getZ();
|
||||
if (dx * dx + dy * dy + dz * dz > SQ_VIEW_DISTANCE) {
|
||||
min.add(stepSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
player.spawnParticle(particle, min.getX(), min.getY(), min.getZ(), 1, 0.0, 0.0, 0.0, 0.0);
|
||||
min.add(stepSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,19 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import de.steamwar.entity.CWireframe;
|
||||
import de.steamwar.entity.REntityServer;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public interface WorldEditRendererWrapper {
|
||||
WorldEditRendererWrapper fallback = VersionDependent.getVersionImpl(Core.getInstance(), 9);
|
||||
WorldEditRendererWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WorldEditRendererWrapper {
|
||||
public static final WorldEditRendererFallback fallback = new WorldEditRendererFallback();
|
||||
public static final WorldEditRendererWrapper impl = new WorldEditRendererWrapper();
|
||||
|
||||
static void safeDraw(Player player, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2) {
|
||||
if (PlayerVersion.isBedrock(player) || PlayerVersion.getVersion(player) < 20) {
|
||||
@@ -34,11 +41,83 @@ public interface WorldEditRendererWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
void draw(Player player, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2);
|
||||
private static final class BoxPair {
|
||||
private CWireframe regionBox;
|
||||
private CWireframe clipboardBox;
|
||||
|
||||
void tick(Player player);
|
||||
public CWireframe get(boolean clipboard) {
|
||||
if (clipboard) {
|
||||
return clipboardBox;
|
||||
} else {
|
||||
return regionBox;
|
||||
}
|
||||
}
|
||||
|
||||
void hide(Player player, boolean clipboard, boolean hide);
|
||||
public void set(boolean clipboard, CWireframe box) {
|
||||
if (clipboard) {
|
||||
this.clipboardBox = box;
|
||||
} else {
|
||||
this.regionBox = box;
|
||||
}
|
||||
}
|
||||
|
||||
void remove(Player player);
|
||||
public void die() {
|
||||
if (clipboardBox != null) {
|
||||
clipboardBox.die();
|
||||
}
|
||||
if (regionBox != null) {
|
||||
regionBox.die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Player, REntityServer> servers = new HashMap<>();
|
||||
private static final Map<Player, BoxPair> boxes = new HashMap<>();
|
||||
|
||||
public void draw(Player player, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2) {
|
||||
REntityServer server = servers.computeIfAbsent(player, __ -> {
|
||||
REntityServer entityServer = new REntityServer();
|
||||
entityServer.addPlayer(player);
|
||||
return entityServer;
|
||||
});
|
||||
|
||||
WorldEditRendererCUIEditor.Type type = clipboard ? WorldEditRendererCUIEditor.Type.CLIPBOARD : WorldEditRendererCUIEditor.Type.SELECTION;
|
||||
float width = type.getWidth(player).value;
|
||||
Material material = type.getMaterial(player);
|
||||
if (material == Material.BARRIER) {
|
||||
hide(player, clipboard, true);
|
||||
return;
|
||||
}
|
||||
BlockData block = material.createBlockData();
|
||||
|
||||
BoxPair boxPair = boxes.computeIfAbsent(player, __ -> new BoxPair());
|
||||
CWireframe box = boxPair.get(clipboard);
|
||||
if (box == null) {
|
||||
box = new CWireframe(server);
|
||||
boxPair.set(clipboard, box);
|
||||
}
|
||||
box.setPos1And2(pos1.toLocation(player.getWorld()), pos2.toLocation(player.getWorld()));
|
||||
box.setWidth(width);
|
||||
box.setBlock(block);
|
||||
}
|
||||
|
||||
public void tick(Player player) {
|
||||
REntityServer server = servers.get(player);
|
||||
if (server != null) server.tick();
|
||||
}
|
||||
|
||||
public void hide(Player player, boolean clipboard, boolean hide) {
|
||||
BoxPair boxPair = boxes.get(player);
|
||||
if (boxPair == null) return;
|
||||
CWireframe box = boxPair.get(clipboard);
|
||||
if (box == null) return;
|
||||
box.hide(hide);
|
||||
}
|
||||
|
||||
public void remove(Player player) {
|
||||
BoxPair boxPair = boxes.remove(player);
|
||||
if (boxPair != null) boxPair.die();
|
||||
REntityServer server = servers.remove(player);
|
||||
if (server != null) server.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,18 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.worldedit.EmptyClipboardException;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.*;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV1Reader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV2Reader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Reader;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
@@ -30,25 +39,140 @@ import de.steamwar.sql.NodeData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.enginehub.linbus.stream.LinBinaryIO;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public interface WorldEditWrapper {
|
||||
WorldEditWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public class WorldEditWrapper {
|
||||
public static final WorldEditWrapper impl = new WorldEditWrapper();
|
||||
|
||||
InputStream getPlayerClipboard(Player player);
|
||||
public InputStream getPlayerClipboard(Player player) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, (outputStream, clipboard, clipboardHolder) -> {
|
||||
ClipboardWriter writer = BuiltInClipboardFormat.FAST_V3.getWriter(outputStream);
|
||||
writer.write(clipboard);
|
||||
writer.close();
|
||||
});
|
||||
}
|
||||
|
||||
void setPlayerClipboard(Player player, Clipboard clipboard);
|
||||
Clipboard getClipboard(NodeData data) throws IOException;
|
||||
Clipboard getClipboard(InputStream inputStream) throws IOException;
|
||||
public void setPlayerClipboard(Player player, Clipboard clipboard) {
|
||||
Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player);
|
||||
WorldEditWrapper.getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard));
|
||||
}
|
||||
|
||||
Vector getOrigin(Clipboard clipboard);
|
||||
Vector getMinimum(Region region);
|
||||
Vector getMaximum(Region region);
|
||||
Vector applyTransform(Vector vector, Transform transform);
|
||||
public Clipboard getClipboard(NodeData data) throws IOException {
|
||||
ResetableInputStream is = new ResetableInputStream(data.schemData(false));
|
||||
for (ClipboardFormat clipboardFormat : ClipboardFormats.getAll()) {
|
||||
FilterInputStream fis = new FilterInputStream(is) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// Ignore close call!
|
||||
}
|
||||
};
|
||||
boolean canBeRead = clipboardFormat.isFormat(fis);
|
||||
is.reset();
|
||||
if (!canBeRead) continue;
|
||||
return clipboardFormat.load(is);
|
||||
}
|
||||
throw new IOException("No clipboard found");
|
||||
}
|
||||
|
||||
NodeData.SchematicFormat getNativeFormat();
|
||||
private static final Function<InputStream, ClipboardReader> FastV3 = FastSchematicReaderV3::new;
|
||||
@SuppressWarnings("removal")
|
||||
private static final Function<InputStream, ClipboardReader> FastV2 = inputStream -> new FastSchematicReaderV2(new NBTInputStream(inputStream));
|
||||
@SuppressWarnings("removal")
|
||||
private static final Function<InputStream, ClipboardReader> McEdit = inputStream -> new MCEditSchematicReader(new NBTInputStream(inputStream));
|
||||
private static final Function<InputStream, ClipboardReader> SpongeV3 = inputStream -> new SpongeSchematicV3Reader(LinBinaryIO.read(new DataInputStream(inputStream)));
|
||||
private static final Function<InputStream, ClipboardReader> SpongeV2 = inputStream -> new SpongeSchematicV2Reader(LinBinaryIO.read(new DataInputStream(inputStream)));
|
||||
private static final Function<InputStream, ClipboardReader> SpongeV1 = inputStream -> new SpongeSchematicV1Reader(LinBinaryIO.read(new DataInputStream(inputStream)));
|
||||
|
||||
private static final Function<InputStream, ClipboardReader>[] READERS = new Function[]{
|
||||
FastV3,
|
||||
FastV2,
|
||||
SpongeV3,
|
||||
SpongeV2,
|
||||
SpongeV1,
|
||||
McEdit
|
||||
};
|
||||
|
||||
public Clipboard getClipboard(InputStream inputStream) throws IOException {
|
||||
ResetableInputStream is = new ResetableInputStream(inputStream);
|
||||
for (Function<InputStream, ClipboardReader> reader : READERS) {
|
||||
FilterInputStream fis = new FilterInputStream(is) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// Ignore close call!
|
||||
}
|
||||
};
|
||||
try {
|
||||
return reader.apply(fis).read();
|
||||
} catch (Exception e) {
|
||||
is.reset();
|
||||
}
|
||||
}
|
||||
is.close();
|
||||
throw new IOException("No clipboard found");
|
||||
}
|
||||
|
||||
private static class ResetableInputStream extends InputStream {
|
||||
|
||||
private InputStream inputStream;
|
||||
private int pointer = 0;
|
||||
private List<Integer> list = new ArrayList<>();
|
||||
|
||||
public ResetableInputStream(InputStream in) {
|
||||
this.inputStream = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (pointer >= list.size()) {
|
||||
int data = inputStream.read();
|
||||
list.add(data);
|
||||
pointer++;
|
||||
return data;
|
||||
}
|
||||
int data = list.get(pointer);
|
||||
pointer++;
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
pointer = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
list.clear();
|
||||
pointer = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public org.bukkit.util.Vector getOrigin(Clipboard clipboard) {
|
||||
return new org.bukkit.util.Vector(clipboard.getOrigin().x(), clipboard.getOrigin().y(), clipboard.getOrigin().z());
|
||||
}
|
||||
|
||||
public Vector getMinimum(Region region) {
|
||||
return new Vector(region.getMinimumPoint().x(), region.getMinimumPoint().y(), region.getMinimumPoint().z());
|
||||
}
|
||||
|
||||
public Vector getMaximum(Region region) {
|
||||
return new Vector(region.getMaximumPoint().x(), region.getMaximumPoint().y(), region.getMaximumPoint().z());
|
||||
}
|
||||
|
||||
public Vector applyTransform(Vector vector, Transform transform) {
|
||||
Vector3 v = Vector3.at(vector.getX(), vector.getY(), vector.getZ());
|
||||
v = transform.apply(v);
|
||||
return new org.bukkit.util.Vector(v.x(), v.y(), v.z());
|
||||
}
|
||||
|
||||
public NodeData.SchematicFormat getNativeFormat() {
|
||||
return NodeData.SchematicFormat.SPONGE_V3;
|
||||
}
|
||||
|
||||
static WorldEditPlugin getWorldEditPlugin() {
|
||||
return (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
|
||||
|
||||
@@ -19,15 +19,56 @@
|
||||
|
||||
package de.steamwar.core;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
|
||||
import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
@Linked
|
||||
public class WorldIdentifier {
|
||||
|
||||
private static final IWorldIdentifier impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
private static ResourceKey<Level> resourceKey = null;
|
||||
|
||||
private static final Class<?> resourceKeyClass = Reflection.getClass("net.minecraft.resources.ResourceKey");
|
||||
private static final Class<?> minecraftKeyClass = Reflection.getClass("net.minecraft.resources.MinecraftKey");
|
||||
private static final Reflection.Constructor resourceKeyConstructor = Reflection.getConstructor(resourceKeyClass, minecraftKeyClass, minecraftKeyClass);
|
||||
private static final Reflection.Constructor minecraftKeyConstructor = Reflection.getConstructor(minecraftKeyClass, String.class, String.class);
|
||||
|
||||
public static void set(String name) {
|
||||
impl.setResourceKey(name);
|
||||
resourceKey = (ResourceKey<Level>) resourceKeyConstructor.invoke(minecraftKeyConstructor.invoke("minecraft", "dimension"), minecraftKeyConstructor.invoke("steamwar", name));
|
||||
}
|
||||
|
||||
protected interface IWorldIdentifier {
|
||||
void setResourceKey(String name);
|
||||
public WorldIdentifier() {
|
||||
TinyProtocol.instance.addFilter(ClientboundLoginPacket.class, (player, o) -> {
|
||||
if (resourceKey == null) return o;
|
||||
ClientboundLoginPacket packet = (ClientboundLoginPacket) o;
|
||||
|
||||
return new ClientboundLoginPacket(packet.playerId(),
|
||||
packet.hardcore(),
|
||||
packet.levels(),
|
||||
packet.maxPlayers(),
|
||||
packet.chunkRadius(),
|
||||
packet.simulationDistance(),
|
||||
packet.reducedDebugInfo(),
|
||||
packet.showDeathScreen(),
|
||||
packet.doLimitedCrafting(),
|
||||
new CommonPlayerSpawnInfo(
|
||||
packet.commonPlayerSpawnInfo().dimensionType(),
|
||||
resourceKey,
|
||||
packet.commonPlayerSpawnInfo().seed(),
|
||||
packet.commonPlayerSpawnInfo().gameType(),
|
||||
packet.commonPlayerSpawnInfo().previousGameType(),
|
||||
packet.commonPlayerSpawnInfo().isDebug(),
|
||||
packet.commonPlayerSpawnInfo().isFlat(),
|
||||
packet.commonPlayerSpawnInfo().lastDeathLocation(),
|
||||
packet.commonPlayerSpawnInfo().portalCooldown(),
|
||||
packet.commonPlayerSpawnInfo().seaLevel()
|
||||
),
|
||||
packet.enforcesSecureChat()
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+49
-5
@@ -19,12 +19,56 @@
|
||||
|
||||
package de.steamwar.core.authlib;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.GameProfileRepository;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import com.mojang.authlib.ProfileLookupCallback;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.Services;
|
||||
|
||||
public abstract class SteamwarGameProfileRepository implements GameProfileRepository {
|
||||
public static final SteamwarGameProfileRepository impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract void inject();
|
||||
public class SteamwarGameProfileRepository implements GameProfileRepository {
|
||||
public static final SteamwarGameProfileRepository impl = new SteamwarGameProfileRepository();
|
||||
|
||||
private static final GameProfileRepository fallback;
|
||||
private static final Reflection.Field<Services> field;
|
||||
private static final Services current;
|
||||
|
||||
static {
|
||||
Class<?> clazz = MinecraftServer.getServer().getClass();
|
||||
field = Reflection.getField(clazz, Services.class, 0);
|
||||
current = field.get(MinecraftServer.getServer());
|
||||
fallback = current.profileRepository();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findProfilesByNames(String[] strings, ProfileLookupCallback profileLookupCallback) {
|
||||
List<String> unknownNames = new ArrayList<>();
|
||||
for (String name:strings) {
|
||||
SteamwarUser user = SteamwarUser.get(name);
|
||||
if(user == null) {
|
||||
unknownNames.add(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
profileLookupCallback.onProfileLookupSucceeded(new GameProfile(user.getUUID(), user.getUserName()));
|
||||
}
|
||||
if(!unknownNames.isEmpty()) {
|
||||
fallback.findProfilesByNames(unknownNames.toArray(new String[0]), profileLookupCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<GameProfile> findProfileByName(String s) {
|
||||
return fallback.findProfileByName(s);
|
||||
}
|
||||
|
||||
public void inject() {
|
||||
Services newServices = new Services(current.sessionService(), current.servicesKeySet(), this, current.profileCache(), current.paperConfigurations());
|
||||
field.set(MinecraftServer.getServer(), newServices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,35 @@
|
||||
|
||||
package de.steamwar.entity;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.PositionMoveRotation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public interface PacketConstructor {
|
||||
PacketConstructor impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
import java.util.Collections;
|
||||
|
||||
Object teleportPacket(int entityId, double x, double y, double z, float yaw, float pitch);
|
||||
Object createRPlayerSpawn(RPlayer player);
|
||||
public class PacketConstructor {
|
||||
public static final PacketConstructor impl = new PacketConstructor();
|
||||
|
||||
public Object teleportPacket(int entityId, double x, double y, double z, float yaw, float pitch) {
|
||||
PositionMoveRotation rot = new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, pitch, yaw);
|
||||
return new ClientboundTeleportEntityPacket(entityId, rot, Collections.emptySet(), false);
|
||||
}
|
||||
|
||||
public Object createRPlayerSpawn(RPlayer player) {
|
||||
return new ClientboundAddEntityPacket(
|
||||
player.entityId,
|
||||
player.uuid,
|
||||
player.x,
|
||||
player.y,
|
||||
player.z,
|
||||
player.yaw,
|
||||
player.pitch,
|
||||
EntityType.PLAYER,
|
||||
0,
|
||||
Vec3.ZERO,
|
||||
player.headYaw
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,54 @@ package de.steamwar.scoreboard;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
|
||||
public interface SWScoreboard {
|
||||
public static final SWScoreboard impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
boolean createScoreboard(Player player, ScoreboardCallback callback);
|
||||
void removeScoreboard(Player player);
|
||||
public class SWScoreboard {
|
||||
public static final SWScoreboard impl = new SWScoreboard();
|
||||
|
||||
private static final HashMap<Player, ScoreboardCallback> playerBoards = new HashMap<>();
|
||||
private static final String SIDEBAR = "sw-sidebar";
|
||||
|
||||
static {
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
|
||||
for(Map.Entry<Player, ScoreboardCallback> scoreboard : playerBoards.entrySet()) {
|
||||
render(scoreboard.getKey(), scoreboard.getValue());
|
||||
}
|
||||
}, 10, 5);
|
||||
}
|
||||
|
||||
private static void render(Player player, ScoreboardCallback callback) {
|
||||
if (player.getScoreboard().getObjective(SIDEBAR) != null) {
|
||||
player.getScoreboard().getObjective(SIDEBAR).unregister();
|
||||
}
|
||||
|
||||
Objective objective = player.getScoreboard().registerNewObjective(SIDEBAR, "dummy", Component.text(callback.getTitle()));
|
||||
objective.setAutoUpdateDisplay(true);
|
||||
objective.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
|
||||
callback.getData().forEach((text, score) -> objective.getScore(text).setScore(score));
|
||||
}
|
||||
|
||||
public boolean createScoreboard(Player player, ScoreboardCallback callback) {
|
||||
Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
|
||||
player.setScoreboard(scoreboard);
|
||||
|
||||
render(player, callback);
|
||||
|
||||
playerBoards.put(player, callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeScoreboard(Player player) {
|
||||
player.getScoreboard().getObjective(SIDEBAR).unregister();
|
||||
playerBoards.remove(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,19 +19,55 @@
|
||||
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public interface BlockIds {
|
||||
BlockIds impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public class BlockIds {
|
||||
public static final BlockIds impl = new BlockIds();
|
||||
|
||||
Reflection.Method getCombinedId = Reflection.getTypedMethod(TechHider.block, null, int.class, TechHider.iBlockData);
|
||||
|
||||
int getCombinedId(Object iBlockData);
|
||||
int materialToId(Material material);
|
||||
Set<Integer> materialToAllIds(Material material);
|
||||
private static final Class<?> blockStateList = Reflection.getClass("net.minecraft.world.level.block.state.StateDefinition");
|
||||
private static final Class<?> fluidTypeFlowing = Reflection.getClass("net.minecraft.world.level.material.FlowingFluid");
|
||||
private static final Class<?> fluid = Reflection.getClass("net.minecraft.world.level.material.FluidState");
|
||||
|
||||
private static final Reflection.Method getBlockData = Reflection.getTypedMethod(TechHider.block, null, TechHider.iBlockData);
|
||||
public int materialToId(Material material) {
|
||||
return getCombinedId(getBlockData.invoke(getBlock(material)));
|
||||
}
|
||||
|
||||
private static final Reflection.Method getStates = Reflection.getTypedMethod(TechHider.block, null, blockStateList);
|
||||
private static final Reflection.Method getStateList = Reflection.getTypedMethod(blockStateList, null, ImmutableList.class);
|
||||
private static final Object water = Reflection.getTypedMethod(fluidTypeFlowing, null, fluid, boolean.class).invoke(Reflection.getField(Reflection.getClass("net.minecraft.world.level.material.Fluids"), fluidTypeFlowing, 1).get(null), false);
|
||||
private static final Iterable<?> registryBlockId = (Iterable<?>) Reflection.getField(TechHider.block, Reflection.getClass("net.minecraft.core.IdMapper"), 0).get(null);
|
||||
private static final Reflection.Method getFluid = Reflection.getTypedMethod(TechHider.iBlockData, null, fluid);
|
||||
public Set<Integer> materialToAllIds(Material material) {
|
||||
Set<Integer> ids = new HashSet<>();
|
||||
for(Object data : (ImmutableList<?>) getStateList.invoke(getStates.invoke(getBlock(material)))) {
|
||||
ids.add(getCombinedId(data));
|
||||
}
|
||||
|
||||
if(material == Material.WATER) {
|
||||
for(Object data : registryBlockId) {
|
||||
if(getFluid.invoke(data) == water) {
|
||||
ids.add(getCombinedId(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
private static final Reflection.Method getBlock = Reflection.getTypedMethod(TechHider.craftMagicNumbers, "getBlock", TechHider.block, Material.class);
|
||||
private Object getBlock(Material material) {
|
||||
return getBlock.invoke(null, material);
|
||||
}
|
||||
|
||||
public int getCombinedId(Object blockData) {
|
||||
return (int) getCombinedId.invoke(null, blockData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,21 +19,147 @@
|
||||
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import de.steamwar.Reflection;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.util.SimpleBitStorage;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public interface ChunkHider {
|
||||
ChunkHider impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public class ChunkHider {
|
||||
public static final ChunkHider impl = new ChunkHider();
|
||||
|
||||
Class<?> mapChunkPacket();
|
||||
BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider);
|
||||
public Class<?> mapChunkPacket() {
|
||||
return ClientboundLevelChunkWithLightPacket.class;
|
||||
}
|
||||
|
||||
private static final UnaryOperator<Object> chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class);
|
||||
private static final UnaryOperator<Object> chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class);
|
||||
|
||||
private static final Reflection.Field<Integer> chunkXField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 0);
|
||||
private static final Reflection.Field<Integer> chunkZField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 1);
|
||||
private static final Reflection.Field<ClientboundLevelChunkPacketData> chunkData = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkPacketData.class, 0);
|
||||
|
||||
private static final Reflection.Field<byte[]> dataField = Reflection.getField(ClientboundLevelChunkPacketData.class, byte[].class, 0);
|
||||
private static final Reflection.Field<List> tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0);
|
||||
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
int chunkX = chunkXField.get(packet);
|
||||
int chunkZ = chunkZField.get(packet);
|
||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = chunkPacketCloner.apply(packet);
|
||||
Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet));
|
||||
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
tileEntities.set(dataWrapper, ((List<?>)tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList()));
|
||||
|
||||
ByteBuf in = Unpooled.wrappedBuffer(dataField.get(dataWrapper));
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
for(int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset/16, chunkZ);
|
||||
section.copyBlockCount();
|
||||
|
||||
blocks(section);
|
||||
biomes(section);
|
||||
}
|
||||
|
||||
if (in.readableBytes() != 0) {
|
||||
throw new IllegalStateException("ChunkHider21: Incomplete chunk data, " + in.readableBytes() + " bytes left");
|
||||
}
|
||||
|
||||
byte[] data = new byte[out.readableBytes()];
|
||||
out.readBytes(data);
|
||||
dataField.set(dataWrapper, data);
|
||||
|
||||
chunkData.set(packet, dataWrapper);
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
public static final Class<?> tileEntity = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo");
|
||||
protected static final Reflection.Field<BlockEntityType> entityType = Reflection.getField(tileEntity, BlockEntityType.class, 0);
|
||||
private static final Class<?> builtInRegestries = Reflection.getClass("net.minecraft.core.registries.BuiltInRegistries");
|
||||
private static final Class<?> registry = Reflection.getClass("net.minecraft.core.Registry");
|
||||
private static final Reflection.Field<?> nameField = Reflection.getField(builtInRegestries, "BLOCK_ENTITY_TYPE", registry);
|
||||
private static final Class<?> resourceLocation = Reflection.getClass("net.minecraft.resources.ResourceLocation");
|
||||
private static final Reflection.Method getKey = Reflection.getTypedMethod(registry, "getKey", resourceLocation, Object.class);
|
||||
private static final Reflection.Method getName = Reflection.getTypedMethod(resourceLocation, "getPath", String.class);
|
||||
protected boolean tileEntityVisible(Set<String> hiddenBlockEntities, Object tile) {
|
||||
return !hiddenBlockEntities.contains(getName.invoke(getKey.invoke(nameField.get(null), entityType.get(tile))));
|
||||
}
|
||||
|
||||
private void blocks(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
|
||||
boolean singleValued = section.getBitsPerBlock() == 0;
|
||||
if (singleValued) {
|
||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
||||
return;
|
||||
} else if (section.getBitsPerBlock() < 9) {
|
||||
// Indirect (paletted) storage – only present when bitsPerBlock < 9 in 1.21+
|
||||
section.processPalette();
|
||||
}
|
||||
|
||||
if (section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) {
|
||||
section.skipNewDataArray(4096);
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readNewDataArray(4096));
|
||||
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int pos = (((y * 16) + z) * 16) + x;
|
||||
|
||||
TechHider.State test = section.test(x, y, z);
|
||||
|
||||
switch (test) {
|
||||
case SKIP:
|
||||
break;
|
||||
case CHECK:
|
||||
if (!section.getObfuscate().contains(values.get(pos)))
|
||||
break;
|
||||
case HIDE:
|
||||
values.set(pos, section.getTarget());
|
||||
break;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
values.set(pos, section.getAir());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.writeDataArray(values.getRaw());
|
||||
}
|
||||
|
||||
private void biomes(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
if(section.getBitsPerBlock() == 0) {
|
||||
section.copyVarInt();
|
||||
} else if(section.getBitsPerBlock() < 6) {
|
||||
section.skipPalette();
|
||||
section.skipNewDataArray(64);
|
||||
} else {
|
||||
// Direct (global) biome IDs – no palette present
|
||||
section.skipNewDataArray(64);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
class SectionHider {
|
||||
|
||||
@@ -19,19 +19,74 @@
|
||||
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public interface ProtocolWrapper {
|
||||
ProtocolWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
public class ProtocolWrapper {
|
||||
public static final ProtocolWrapper impl = new ProtocolWrapper();
|
||||
|
||||
private static final Reflection.Field<SectionPos> multiBlockChangeChunk = Reflection.getField(TechHider.multiBlockChangePacket, SectionPos.class, 0);
|
||||
private static final Reflection.Field<short[]> multiBlockChangePos = Reflection.getField(TechHider.multiBlockChangePacket, short[].class, 0);
|
||||
private static final Reflection.Field<BlockState[]> multiBlockChangeBlocks = Reflection.getField(TechHider.multiBlockChangePacket, BlockState[].class, 0);
|
||||
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
|
||||
Object chunkCoords = multiBlockChangeChunk.get(packet);
|
||||
int chunkX = TechHider.blockPositionX.get(chunkCoords);
|
||||
int chunkY = TechHider.blockPositionY.get(chunkCoords);
|
||||
int chunkZ = TechHider.blockPositionZ.get(chunkCoords);
|
||||
if(locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ))
|
||||
return packet;
|
||||
|
||||
boolean unfilteredTileEntityDataAction(Object packet);
|
||||
packet = TechHider.multiBlockChangeCloner.apply(packet);
|
||||
final short[] oldPos = multiBlockChangePos.get(packet);
|
||||
final BlockState[] oldBlocks = multiBlockChangeBlocks.get(packet);
|
||||
ArrayList<Short> poss = new ArrayList<>(oldPos.length);
|
||||
ArrayList<BlockState> blocks = new ArrayList<>(oldPos.length);
|
||||
for(int i = 0; i < oldPos.length; i++) {
|
||||
short pos = oldPos[i];
|
||||
BlockState block = oldBlocks[i];
|
||||
switch(locationEvaluator.check(p, 16*chunkX + (pos >> 8 & 0xF), 16*chunkY + (pos & 0xF), 16*chunkZ + (pos >> 4 & 0xF))) {
|
||||
case SKIP:
|
||||
poss.add(pos);
|
||||
blocks.add(block);
|
||||
break;
|
||||
case CHECK:
|
||||
poss.add(pos);
|
||||
blocks.add(techHider.iBlockDataHidden(block) ? (BlockState) techHider.getObfuscationTarget() : block);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider);
|
||||
if(blocks.isEmpty())
|
||||
return null;
|
||||
|
||||
BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider);
|
||||
short[] newPos = new short[poss.size()];
|
||||
for(int i = 0; i < newPos.length; i++)
|
||||
newPos[i] = poss.get(i);
|
||||
|
||||
multiBlockChangePos.set(packet, newPos);
|
||||
multiBlockChangeBlocks.set(packet, blocks.toArray(new BlockState[0]));
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
private static final Reflection.Field<BlockEntityType> tileEntityType = Reflection.getField(TechHider.tileEntityDataPacket, BlockEntityType.class, 0);
|
||||
private static final BlockEntityType<?> signType = Reflection.getField(BlockEntityType.class, BlockEntityType.class, 0, SignBlockEntity.class).get(null);
|
||||
public boolean unfilteredTileEntityDataAction(Object packet) {
|
||||
return tileEntityType.get(packet) != signType;
|
||||
}
|
||||
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user