forked from SteamWar/SteamWar
Cleanup SpigotCore
This commit is contained in:
@@ -1,28 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
|
||||
compileOnly(libs.nms10)
|
||||
}
|
||||
@@ -1,29 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
|
||||
compileOnly(libs.nms12)
|
||||
}
|
||||
@@ -1,34 +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 de.steamwar.sql.SteamwarUser;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerLocaleChangeEvent;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class LocaleChangeWrapper12 implements LocaleChangeWrapper {
|
||||
|
||||
@EventHandler
|
||||
private void onLocale(PlayerLocaleChangeEvent event) {
|
||||
SteamwarUser.get(event.getPlayer().getUniqueId()).setLocale(Locale.forLanguageTag(event.getLocale()), false);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_8", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_9", "default"))
|
||||
|
||||
compileOnly(libs.nms14)
|
||||
compileOnly(libs.worldedit15)
|
||||
}
|
||||
@@ -1,361 +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 de.steamwar.Reflection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
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 FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper {
|
||||
|
||||
private static final Map<String, Material> renamedLegacy = new HashMap<>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static final Reflection.Field<?> scoreboardName = Reflection.getField(FlatteningWrapper.scoreboardObjective, Reflection.getClass("net.minecraft.network.chat.Component"), 0);
|
||||
@Override
|
||||
public void setScoreboardTitle(Object packet, String title) {
|
||||
scoreboardName.set(packet, ChatWrapper.impl.stringToChatComponent(title));
|
||||
}
|
||||
|
||||
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(FlatteningWrapper.scoreboardScore, scoreActionEnum, 0) : null;
|
||||
private static final Object scoreActionChange = Core.getVersion() < 21 ? scoreActionEnum.getEnumConstants()[0] : null;
|
||||
|
||||
@Override
|
||||
public void setScoreAction(Object packet) {
|
||||
scoreAction.set(packet, scoreActionChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getMaterial(String material) {
|
||||
try{
|
||||
return Material.valueOf(material);
|
||||
}catch(IllegalArgumentException e){
|
||||
return renamedLegacy.get(material);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public ItemStack setSkullOwner(String player) {
|
||||
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
SkullMeta headmeta = (SkullMeta) head.getItemMeta();
|
||||
assert headmeta != null;
|
||||
headmeta.setOwningPlayer(Bukkit.getOfflinePlayer(player.startsWith(".") ? player.substring(1) : player));
|
||||
headmeta.setDisplayName(player);
|
||||
head.setItemMeta(headmeta);
|
||||
return head;
|
||||
}
|
||||
|
||||
protected static final Class<?> entityPose = Reflection.getClass("net.minecraft.world.entity.Pose");
|
||||
protected static final Object standing = entityPose.getEnumConstants()[0];
|
||||
protected static final Object swimming = entityPose.getEnumConstants()[3];
|
||||
protected static final Object sneaking = entityPose.getEnumConstants()[5];
|
||||
@Override
|
||||
public Object getPose(FlatteningWrapper.EntityPose pose) {
|
||||
switch (pose) {
|
||||
case SNEAKING:
|
||||
return sneaking;
|
||||
case SWIMMING:
|
||||
return swimming;
|
||||
case NORMAL:
|
||||
default:
|
||||
return standing;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNamedSpawnPacketDataWatcher(Object packet) {
|
||||
// field not present
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
@Override
|
||||
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())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
@Override
|
||||
public void syncSave(World world) {
|
||||
save.invoke(getHandle.invoke(world), null, true, false);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +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 org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerRecipeDiscoverEvent;
|
||||
|
||||
public class RecipeDiscoverWrapper14 implements RecipeDiscoverWrapper {
|
||||
@EventHandler
|
||||
public void onRecipeDiscover(PlayerRecipeDiscoverEvent e) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +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 org.bukkit.Material;
|
||||
|
||||
public class TrickyTrialsWrapper14 extends TrickyTrialsWrapper8 {
|
||||
|
||||
@Override
|
||||
public Material getTurtleScute() {
|
||||
return Material.SCUTE;
|
||||
}
|
||||
}
|
||||
@@ -1,634 +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 com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sk89q.jnbt.*;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.*;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.*;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.world.DataFixer;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||
import de.steamwar.sql.NoClipboardException;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public class WorldEditWrapper14 implements WorldEditWrapper {
|
||||
|
||||
@Override
|
||||
public InputStream getPlayerClipboard(Player player) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, (outputStream, clipboard, clipboardHolder) -> {
|
||||
ClipboardWriter writer = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(outputStream);
|
||||
writer.write(clipboard);
|
||||
writer.close();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerClipboard(Player player, Clipboard clipboard) {
|
||||
Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player);
|
||||
WorldEditWrapper.getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard(NodeData data) throws IOException {
|
||||
InputStream is = data.schemData(true);
|
||||
return readClipboard(is, data.getNodeFormat());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard(InputStream inputStream) throws IOException {
|
||||
return readClipboard(inputStream, getNativeFormat());
|
||||
}
|
||||
|
||||
private Clipboard readClipboard(InputStream is, NodeData.SchematicFormat format) throws IOException {
|
||||
switch (format) {
|
||||
case SPONGE_V2:
|
||||
case SPONGE_V3:
|
||||
return new SpongeSchematicReader(new NBTInputStream(is), this).read();
|
||||
case MCEDIT:
|
||||
return new MCEditSchematicReader(new NBTInputStream(is)).read();
|
||||
default:
|
||||
throw new IOException("This schematic format is currently not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.util.Vector getOrigin(Clipboard clipboard) {
|
||||
return new org.bukkit.util.Vector(clipboard.getOrigin().getX(), clipboard.getOrigin().getY(), clipboard.getOrigin().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getMinimum(Region region) {
|
||||
return new Vector(region.getMinimumPoint().getX(), region.getMinimumPoint().getY(), region.getMinimumPoint().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getMaximum(Region region) {
|
||||
return new Vector(region.getMaximumPoint().getX(), region.getMaximumPoint().getY(), region.getMaximumPoint().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
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.getX(), v.getY(), v.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeData.SchematicFormat getNativeFormat() {
|
||||
return NodeData.SchematicFormat.SPONGE_V2;
|
||||
}
|
||||
|
||||
public Map<String, Tag> applyDataFixer(DataFixer fixer, int dataVersion, Map<String, Tag> values) {
|
||||
return fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, new CompoundTag(values), dataVersion).getValue();
|
||||
}
|
||||
|
||||
private static class MCEditSchematicReader extends NBTSchematicReader {
|
||||
|
||||
private final NBTInputStream inputStream;
|
||||
private final DataFixer fixer;
|
||||
private boolean faweSchem = false;
|
||||
private static final ImmutableList<NBTCompatibilityHandler> COMPATIBILITY_HANDLERS
|
||||
= ImmutableList.of(
|
||||
new SignCompatibilityHandler(),
|
||||
new FlowerPotCompatibilityHandler(),
|
||||
new NoteBlockCompatibilityHandler(),
|
||||
new SkullBlockCompatibilityHandler()
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param inputStream the input stream to read from
|
||||
*/
|
||||
MCEditSchematicReader(NBTInputStream inputStream) {
|
||||
checkNotNull(inputStream);
|
||||
this.inputStream = inputStream;
|
||||
this.fixer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard read() throws IOException {
|
||||
// Schematic tag
|
||||
NamedTag rootTag = inputStream.readNamedTag();
|
||||
if (!rootTag.getName().equals("Schematic")) {
|
||||
throw new IOException("Tag 'Schematic' does not exist or is not first");
|
||||
}
|
||||
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||
|
||||
// Check
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
if (!schematic.containsKey("Blocks")) {
|
||||
throw new IOException("Schematic file is missing a 'Blocks' tag");
|
||||
}
|
||||
|
||||
// Check type of Schematic
|
||||
String materials = requireTag(schematic, "Materials", StringTag.class).getValue();
|
||||
if (!materials.equals("Alpha")) {
|
||||
throw new IOException("Schematic file is not an Alpha schematic");
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
// Metadata
|
||||
// ====================================================================
|
||||
|
||||
BlockVector3 origin;
|
||||
Region region;
|
||||
|
||||
// Get information
|
||||
short width = requireTag(schematic, "Width", ShortTag.class).getValue();
|
||||
short height = requireTag(schematic, "Height", ShortTag.class).getValue();
|
||||
short length = requireTag(schematic, "Length", ShortTag.class).getValue();
|
||||
|
||||
int originX = 0;
|
||||
int originY = 0;
|
||||
int originZ = 0;
|
||||
try {
|
||||
originX = requireTag(schematic, "WEOriginX", IntTag.class).getValue();
|
||||
originY = requireTag(schematic, "WEOriginY", IntTag.class).getValue();
|
||||
originZ = requireTag(schematic, "WEOriginZ", IntTag.class).getValue();
|
||||
BlockVector3 min = BlockVector3.at(originX, originY, originZ);
|
||||
|
||||
int offsetX = requireTag(schematic, "WEOffsetX", IntTag.class).getValue();
|
||||
int offsetY = requireTag(schematic, "WEOffsetY", IntTag.class).getValue();
|
||||
int offsetZ = requireTag(schematic, "WEOffsetZ", IntTag.class).getValue();
|
||||
BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ);
|
||||
|
||||
origin = min.subtract(offset);
|
||||
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
|
||||
} catch (IOException ignored) {
|
||||
origin = BlockVector3.ZERO;
|
||||
region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE));
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
// Blocks
|
||||
// ====================================================================
|
||||
|
||||
// Get blocks
|
||||
byte[] blockId = requireTag(schematic, "Blocks", ByteArrayTag.class).getValue();
|
||||
byte[] blockData = requireTag(schematic, "Data", ByteArrayTag.class).getValue();
|
||||
byte[] addId = new byte[0];
|
||||
short[] blocks = new short[blockId.length]; // Have to later combine IDs
|
||||
|
||||
// We support 4096 block IDs using the same method as vanilla Minecraft, where
|
||||
// the highest 4 bits are stored in a separate byte array.
|
||||
if (schematic.containsKey("AddBlocks")) {
|
||||
addId = requireTag(schematic, "AddBlocks", ByteArrayTag.class).getValue();
|
||||
}
|
||||
|
||||
// Combine the AddBlocks data with the first 8-bit block ID
|
||||
for (int index = 0; index < blockId.length; index++) {
|
||||
if ((index >> 1) >= addId.length) { // No corresponding AddBlocks index
|
||||
blocks[index] = (short) (blockId[index] & 0xFF);
|
||||
} else {
|
||||
if ((index & 1) == 0) {
|
||||
blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (blockId[index] & 0xFF));
|
||||
} else {
|
||||
blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (blockId[index] & 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need to pull out tile entities
|
||||
final ListTag tileEntityTag = getTag(schematic, "TileEntities", ListTag.class);
|
||||
List<Tag> tileEntities = tileEntityTag == null ? new ArrayList<>() : tileEntityTag.getValue();
|
||||
Map<BlockVector3, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
|
||||
Map<BlockVector3, BlockState> blockStates = new HashMap<>();
|
||||
|
||||
for (Tag tag : tileEntities) {
|
||||
if (!(tag instanceof CompoundTag)) continue;
|
||||
CompoundTag t = (CompoundTag) tag;
|
||||
int x = t.getInt("x");
|
||||
int y = t.getInt("y");
|
||||
int z = t.getInt("z");
|
||||
int index = y * width * length + z * width + x;
|
||||
if(index < 0 || index >= blocks.length)
|
||||
faweSchem = true;
|
||||
}
|
||||
|
||||
for (Tag tag : tileEntities) {
|
||||
if (!(tag instanceof CompoundTag)) continue;
|
||||
CompoundTag t = (CompoundTag) tag;
|
||||
Map<String, Tag> values = new HashMap<>(t.getValue());
|
||||
String id = t.getString("id");
|
||||
values.put("id", new StringTag(convertBlockEntityId(id)));
|
||||
int x = t.getInt("x");
|
||||
int y = t.getInt("y");
|
||||
int z = t.getInt("z");
|
||||
if(faweSchem){
|
||||
x -= originX;
|
||||
y -= originY;
|
||||
z -= originZ;
|
||||
}
|
||||
|
||||
int index = y * width * length + z * width + x;
|
||||
|
||||
try{
|
||||
BlockState block = getBlockState(blocks[index], blockData[index]);
|
||||
BlockState newBlock = block;
|
||||
if (newBlock != null) {
|
||||
for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
|
||||
if (handler.isAffectedBlock(newBlock)) {
|
||||
newBlock = handler.updateNBT(block, values);
|
||||
if (newBlock == null || values.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (values.isEmpty()) {
|
||||
t = null;
|
||||
} else {
|
||||
t = new CompoundTag(values);
|
||||
}
|
||||
|
||||
if (fixer != null && t != null) {
|
||||
t = fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, t, -1);
|
||||
}
|
||||
|
||||
BlockVector3 vec = BlockVector3.at(x, y, z);
|
||||
if (t != null) {
|
||||
tileEntitiesMap.put(vec, t.getValue());
|
||||
}
|
||||
blockStates.put(vec, newBlock);
|
||||
}catch(ArrayIndexOutOfBoundsException e){
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(origin);
|
||||
|
||||
|
||||
for (int x = 0; x < width; ++x) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int z = 0; z < length; ++z) {
|
||||
int index = y * width * length + z * width + x;
|
||||
BlockVector3 pt = BlockVector3.at(x, y, z);
|
||||
BlockState state = blockStates.computeIfAbsent(pt, p -> getBlockState(blocks[index], blockData[index]));
|
||||
|
||||
try {
|
||||
if (state != null) {
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
clipboard.setBlock(region.getMinimumPoint().add(pt), state.toBaseBlock(new CompoundTag(tileEntitiesMap.get(pt))));
|
||||
} else {
|
||||
clipboard.setBlock(region.getMinimumPoint().add(pt), state);
|
||||
}
|
||||
}
|
||||
} catch (WorldEditException ignored) { // BlockArrayClipboard won't throw this
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
private String convertBlockEntityId(String id) {
|
||||
switch (id) {
|
||||
case "Cauldron":
|
||||
return "brewing_stand";
|
||||
case "Control":
|
||||
return "command_block";
|
||||
case "DLDetector":
|
||||
return "daylight_detector";
|
||||
case "Trap":
|
||||
return "dispenser";
|
||||
case "EnchantTable":
|
||||
return "enchanting_table";
|
||||
case "EndGateway":
|
||||
return "end_gateway";
|
||||
case "AirPortal":
|
||||
return "end_portal";
|
||||
case "EnderChest":
|
||||
return "ender_chest";
|
||||
case "FlowerPot":
|
||||
return "flower_pot";
|
||||
case "RecordPlayer":
|
||||
return "jukebox";
|
||||
case "MobSpawner":
|
||||
return "mob_spawner";
|
||||
case "Music":
|
||||
case "noteblock":
|
||||
return "note_block";
|
||||
case "Structure":
|
||||
return "structure_block";
|
||||
case "Chest":
|
||||
return "chest";
|
||||
case "Sign":
|
||||
return "sign";
|
||||
case "Banner":
|
||||
return "banner";
|
||||
case "Beacon":
|
||||
return "beacon";
|
||||
case "Comparator":
|
||||
return "comparator";
|
||||
case "Dropper":
|
||||
return "dropper";
|
||||
case "Furnace":
|
||||
return "furnace";
|
||||
case "Hopper":
|
||||
return "hopper";
|
||||
case "Skull":
|
||||
return "skull";
|
||||
default:
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
private BlockState getBlockState(int id, int data) {
|
||||
return LegacyMapper.getInstance().getBlockFromLegacy(id, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
public static class SpongeSchematicReader extends NBTSchematicReader {
|
||||
|
||||
private final NBTInputStream inputStream;
|
||||
private DataFixer fixer = null;
|
||||
private int schematicVersion = -1;
|
||||
private int dataVersion = -1;
|
||||
private boolean faweSchem = false;
|
||||
private final WorldEditWrapper14 wrapper;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param inputStream the input stream to read from
|
||||
*/
|
||||
public SpongeSchematicReader(NBTInputStream inputStream, WorldEditWrapper14 wrapper) {
|
||||
checkNotNull(inputStream);
|
||||
this.inputStream = inputStream;
|
||||
this.wrapper = wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard read() throws IOException {
|
||||
CompoundTag schematicTag = getBaseTag();
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
|
||||
final Platform platform = WorldEdit.getInstance().getPlatformManager()
|
||||
.queryCapability(Capability.WORLD_EDITING);
|
||||
int liveDataVersion = platform.getDataVersion();
|
||||
|
||||
if (schematicVersion == 1) {
|
||||
dataVersion = 1631; // this is a relatively safe assumption unless someone imports a schematic from 1.12, e.g. sponge 7.1-
|
||||
fixer = platform.getDataFixer();
|
||||
return readVersion1(schematicTag);
|
||||
} else if (schematicVersion == 2 || schematicVersion == 3) {
|
||||
dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
|
||||
if (dataVersion < liveDataVersion) {
|
||||
fixer = platform.getDataFixer();
|
||||
}
|
||||
|
||||
return readVersion1(schematicTag);
|
||||
}
|
||||
throw new IOException("This schematic version is currently not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionalInt getDataVersion() {
|
||||
try {
|
||||
CompoundTag schematicTag = getBaseTag();
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
if (schematicVersion == 1) {
|
||||
return OptionalInt.of(1631);
|
||||
} else if (schematicVersion == 2) {
|
||||
return OptionalInt.of(requireTag(schematic, "DataVersion", IntTag.class).getValue());
|
||||
}
|
||||
return OptionalInt.empty();
|
||||
} catch (IOException e) {
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private CompoundTag getBaseTag() throws IOException {
|
||||
NamedTag rootTag = inputStream.readNamedTag();
|
||||
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||
|
||||
// Check
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
|
||||
if (schematic.size() == 1) {
|
||||
schematicTag = requireTag(schematic, "Schematic", CompoundTag.class);
|
||||
schematic = schematicTag.getValue();
|
||||
} else if (!rootTag.getName().equals("Schematic")) {
|
||||
throw new IOException("Tag 'Schematic' does not exist or is not first");
|
||||
}
|
||||
|
||||
schematicVersion = requireTag(schematic, "Version", IntTag.class).getValue();
|
||||
return schematicTag;
|
||||
}
|
||||
|
||||
private BlockArrayClipboard readVersion1(CompoundTag schematicTag) throws IOException {
|
||||
BlockVector3 origin;
|
||||
Region region;
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
|
||||
int width = requireTag(schematic, "Width", ShortTag.class).getValue();
|
||||
int height = requireTag(schematic, "Height", ShortTag.class).getValue();
|
||||
int length = requireTag(schematic, "Length", ShortTag.class).getValue();
|
||||
|
||||
IntArrayTag offsetTag = getTag(schematic, "Offset", IntArrayTag.class);
|
||||
int[] offsetParts;
|
||||
if (offsetTag != null) {
|
||||
offsetParts = offsetTag.getValue();
|
||||
if (offsetParts.length != 3) {
|
||||
throw new IOException("Invalid offset specified in schematic.");
|
||||
}
|
||||
} else {
|
||||
offsetParts = new int[] {0, 0, 0};
|
||||
}
|
||||
|
||||
BlockVector3 min = BlockVector3.at(offsetParts[0], offsetParts[1], offsetParts[2]);
|
||||
|
||||
CompoundTag metadataTag = getTag(schematic, "Metadata", CompoundTag.class);
|
||||
int offsetX = 0;
|
||||
int offsetY = 0;
|
||||
int offsetZ = 0;
|
||||
if (metadataTag != null && metadataTag.containsKey("WEOffsetX")) {
|
||||
// We appear to have WorldEdit Metadata
|
||||
Map<String, Tag> metadata = metadataTag.getValue();
|
||||
offsetX = requireTag(metadata, "WEOffsetX", IntTag.class).getValue();
|
||||
offsetY = requireTag(metadata, "WEOffsetY", IntTag.class).getValue();
|
||||
offsetZ = requireTag(metadata, "WEOffsetZ", IntTag.class).getValue();
|
||||
BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ);
|
||||
origin = min.subtract(offset);
|
||||
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
|
||||
} else {
|
||||
origin = min;
|
||||
region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE));
|
||||
}
|
||||
|
||||
Map<String, Tag> blockContainer = null;
|
||||
boolean v3Mode = false;
|
||||
|
||||
if (schematicVersion == 3) {
|
||||
blockContainer = requireTag(schematic, "Blocks", CompoundTag.class).getValue();
|
||||
v3Mode = true;
|
||||
}
|
||||
|
||||
Map<String, Tag> paletteObject = requireTag(v3Mode ? blockContainer: schematic, "Palette", CompoundTag.class).getValue();
|
||||
|
||||
Map<Integer, BlockState> palette = new HashMap<>();
|
||||
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setRestricted(false);
|
||||
parserContext.setTryLegacy(false);
|
||||
parserContext.setPreferringWildcard(false);
|
||||
|
||||
for (String palettePart : paletteObject.keySet()) {
|
||||
int id = requireTag(paletteObject, palettePart, IntTag.class).getValue();
|
||||
if (fixer != null) {
|
||||
palettePart = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion);
|
||||
}
|
||||
BlockState state;
|
||||
try {
|
||||
state = WorldEdit.getInstance().getBlockFactory().parseFromInput(palettePart, parserContext).toImmutableState();
|
||||
} catch (InputParseException e) {
|
||||
state = BlockTypes.AIR.getDefaultState();
|
||||
}
|
||||
palette.put(id, state);
|
||||
}
|
||||
|
||||
byte[] blocks = requireTag(v3Mode ? blockContainer: schematic, v3Mode ? "Data" : "BlockData", ByteArrayTag.class).getValue();
|
||||
|
||||
Map<BlockVector3, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
|
||||
ListTag tileEntities = getTag(v3Mode ? blockContainer: schematic, "BlockEntities", ListTag.class);
|
||||
if (tileEntities == null) {
|
||||
tileEntities = getTag(v3Mode ? blockContainer: schematic, "TileEntities", ListTag.class);
|
||||
}
|
||||
if (tileEntities != null) {
|
||||
List<Map<String, Tag>> tileEntityTags = tileEntities.getValue().stream()
|
||||
.map(tag -> (CompoundTag) tag)
|
||||
.map(CompoundTag::getValue)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (Map<String, Tag> tileEntity : tileEntityTags) {
|
||||
int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue();
|
||||
if(pos[0] < 0 || pos[0] >= width || pos[1] < 0 || pos[1] >= height || pos[2] < 0 || pos[2] >= length)
|
||||
faweSchem = true;
|
||||
}
|
||||
|
||||
for (Map<String, Tag> tileEntity : tileEntityTags) {
|
||||
int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue();
|
||||
final BlockVector3 pt = BlockVector3.at(pos[0], pos[1], pos[2]);
|
||||
Map<String, Tag> values = Maps.newHashMap(v3Mode ? requireTag(tileEntity, "Data", CompoundTag.class).getValue() : tileEntity);
|
||||
if(faweSchem){
|
||||
values.put("x", new IntTag(pt.getBlockX() - offsetX));
|
||||
values.put("y", new IntTag(pt.getBlockY() - offsetY));
|
||||
values.put("z", new IntTag(pt.getBlockZ() - offsetZ));
|
||||
}else{
|
||||
values.putIfAbsent("x", new IntTag(pt.getBlockX()));
|
||||
values.putIfAbsent("y", new IntTag(pt.getBlockY()));
|
||||
values.putIfAbsent("z", new IntTag(pt.getBlockZ()));
|
||||
}
|
||||
values.putIfAbsent("id", values.get("Id"));
|
||||
values.remove("Id");
|
||||
values.remove("Pos");
|
||||
if (fixer != null) {
|
||||
tileEntity = wrapper.applyDataFixer(fixer, dataVersion, values);
|
||||
} else {
|
||||
tileEntity = values;
|
||||
}
|
||||
tileEntitiesMap.put(pt, tileEntity);
|
||||
}
|
||||
}
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(origin);
|
||||
|
||||
int index = 0;
|
||||
int i = 0;
|
||||
int value;
|
||||
int varintLength;
|
||||
while (i < blocks.length) {
|
||||
value = 0;
|
||||
varintLength = 0;
|
||||
|
||||
while (true) {
|
||||
value |= (blocks[i] & 127) << (varintLength++ * 7);
|
||||
if (varintLength > 5) {
|
||||
throw new IOException("VarInt too big (probably corrupted data)");
|
||||
}
|
||||
if ((blocks[i] & 128) != 128) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// index = (y * length * width) + (z * width) + x
|
||||
int y = index / (width * length);
|
||||
int z = (index % (width * length)) / width;
|
||||
int x = (index % (width * length)) % width;
|
||||
BlockState state = palette.get(value);
|
||||
BlockVector3 pt = BlockVector3.at(x, y, z);
|
||||
try {
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
clipboard.setBlock(clipboard.getMinimumPoint().add(pt), state.toBaseBlock(new CompoundTag(tileEntitiesMap.get(pt))));
|
||||
} else {
|
||||
clipboard.setBlock(clipboard.getMinimumPoint().add(pt), state);
|
||||
}
|
||||
} catch (WorldEditException e) {
|
||||
throw new IOException("Failed to load a block in the schematic");
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class BlockIds14 implements BlockIds {
|
||||
|
||||
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);
|
||||
@Override
|
||||
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);
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId(Object blockData) {
|
||||
return (int) getCombinedId.invoke(null, blockData);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +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.techhider;
|
||||
|
||||
public class ChunkHider14 extends ChunkHider9 {
|
||||
|
||||
@Override
|
||||
protected void dataHider(SectionHider section) {
|
||||
section.copyBlockCount();
|
||||
section.copyBitsPerBlock();
|
||||
|
||||
boolean hasPalette = section.getBitsPerBlock() < 9;
|
||||
if(hasPalette)
|
||||
section.processPalette();
|
||||
|
||||
if(section.isSkipSection()) {
|
||||
section.skipDataArray();
|
||||
} else {
|
||||
if(hasPalette && !section.blockPrecise()) {
|
||||
section.skipDataArray();
|
||||
return;
|
||||
}
|
||||
|
||||
processDataArray(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class ProtocolWrapper14 extends ProtocolWrapper8 {
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
UnaryOperator<Object> blockBreakCloner = ProtocolUtils.shallowCloneGenerator(blockBreakPacket);
|
||||
Reflection.Field<?> blockBreakPosition = Reflection.getField(blockBreakPacket, TechHider.blockPosition, 0);
|
||||
Reflection.Field<?> blockBreakBlockData = Reflection.getField(blockBreakPacket, TechHider.iBlockData, 0);
|
||||
|
||||
return (p, packet) -> {
|
||||
switch (techHider.getLocationEvaluator().checkBlockPos(p, blockBreakPosition.get(packet))) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if(!techHider.iBlockDataHidden(blockBreakBlockData.get(packet)))
|
||||
return packet;
|
||||
case HIDE:
|
||||
packet = blockBreakCloner.apply(packet);
|
||||
blockBreakBlockData.set(packet, techHider.getObfuscationTarget());
|
||||
return packet;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
packet = blockBreakCloner.apply(packet);
|
||||
blockBreakBlockData.set(packet, TechHider.AIR);
|
||||
return packet;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,28 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
|
||||
compileOnly(libs.nms15)
|
||||
}
|
||||
@@ -1,40 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.isWarnings = false
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_14", "default"))
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
compileOnly(libs.nms18)
|
||||
compileOnly(libs.fawe18)
|
||||
|
||||
compileOnly(libs.datafixer)
|
||||
compileOnly(libs.netty)
|
||||
compileOnly(libs.authlib)
|
||||
}
|
||||
@@ -1,40 +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 de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.world.level.World;
|
||||
import net.minecraft.world.level.chunk.Chunk;
|
||||
import net.minecraft.world.level.lighting.LightEngine;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CraftbukkitWrapper18 implements CraftbukkitWrapper.ICraftbukkitWrapper {
|
||||
|
||||
private static final Reflection.Method getHandle = Reflection.getMethod("org.bukkit.craftbukkit.CraftChunk", "getHandle");
|
||||
private static final Reflection.Method getLightEngine = Reflection.getTypedMethod(World.class, null, LightEngine.class);
|
||||
|
||||
@Override
|
||||
public void sendChunk(Player p, int chunkX, int chunkZ) {
|
||||
Chunk chunk = (Chunk) getHandle.invoke(p.getWorld().getChunkAt(chunkX, chunkZ));
|
||||
TinyProtocol.instance.sendPacket(p, new ClientboundLevelChunkWithLightPacket(chunk, (LightEngine) getLightEngine.invoke(chunk.q), null, null, false, true));
|
||||
}
|
||||
}
|
||||
@@ -1,61 +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 de.steamwar.Reflection;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ProtocolWrapper18 implements ProtocolWrapper {
|
||||
|
||||
private static final Reflection.Field<List> equipmentStack = Reflection.getField(equipmentPacket, List.class, 0);
|
||||
@Override
|
||||
public void setEquipmentPacketStack(Object packet, Object slot, Object stack) {
|
||||
equipmentStack.set(packet, Collections.singletonList(new Pair<>(slot, stack)));
|
||||
}
|
||||
|
||||
private static final Class<?> playerInfoPacket = Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo");
|
||||
private static final Class<?> playerInfoActionClass = Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
|
||||
private static final Reflection.Field<?> playerInfoAction = Reflection.getField(playerInfoPacket, playerInfoActionClass, 0);
|
||||
private static final Reflection.Field<List> playerInfoData = Reflection.getField(playerInfoPacket, List.class, 0);
|
||||
private static final EnumMap<PlayerInfoAction, Object> actions = new EnumMap<>(PlayerInfoAction.class);
|
||||
static {
|
||||
Object[] nativeActions = playerInfoActionClass.getEnumConstants();
|
||||
actions.put(PlayerInfoAction.ADD, nativeActions[0]);
|
||||
actions.put(PlayerInfoAction.GAMEMODE, nativeActions[1]);
|
||||
actions.put(PlayerInfoAction.REMOVE, nativeActions[4]);
|
||||
}
|
||||
private static final Class<?> iChatBaseComponent = Reflection.getClass("net.minecraft.network.chat.Component");
|
||||
private static final Reflection.Constructor playerInfoDataConstructor = Reflection.getConstructor("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData", GameProfile.class, int.class, enumGamemode, iChatBaseComponent);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) {
|
||||
Object packet = Reflection.newInstance(playerInfoPacket);
|
||||
playerInfoAction.set(packet, actions.get(action));
|
||||
playerInfoData.set(packet, Collections.singletonList(playerInfoDataConstructor.invoke(profile, 0, ProtocolWrapper.getGameModeById.invoke(null, mode.getValue()), null)));
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +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 com.sk89q.jnbt.AdventureNBTConverter;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.DataFixer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WorldEditWrapper18 extends WorldEditWrapper14 {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
public Map<String, Tag> applyDataFixer(DataFixer fixer, int dataVersion, Map<String, Tag> values) {
|
||||
return ((CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, new CompoundTag(values).asBinaryTag(), dataVersion))).getValue();
|
||||
}
|
||||
}
|
||||
@@ -1,152 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.core.Core;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.core.IRegistry;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.resources.MinecraftKey;
|
||||
import net.minecraft.util.SimpleBitStorage;
|
||||
import net.minecraft.world.level.block.entity.TileEntityTypes;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ChunkHider18 implements ChunkHider {
|
||||
@Override
|
||||
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);
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
out.writeBytes(in); // MC appends a 0 byte at the end if there is a full chunk, idk why
|
||||
|
||||
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<TileEntityTypes> entityType = Reflection.getField(tileEntity, TileEntityTypes.class, 0);
|
||||
private static final IRegistry<?> tileEntityTypes = Reflection.getField(Core.getVersion() > 18 ? Reflection.getClass("net.minecraft.core.registries.BuiltInRegistries") : IRegistry.class, IRegistry.class, 0, TileEntityTypes.class).get(null);
|
||||
private static final Reflection.Method getKey = Reflection.getTypedMethod(IRegistry.class, null, MinecraftKey.class, Object.class);
|
||||
private static final Reflection.Method getName = Reflection.getTypedMethod(MinecraftKey.class, null, String.class);
|
||||
protected boolean tileEntityVisible(Set<String> hiddenBlockEntities, Object tile) {
|
||||
return !hiddenBlockEntities.contains((String) getName.invoke(getKey.invoke(tileEntityTypes, entityType.get(tile))));
|
||||
}
|
||||
|
||||
private void blocks(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
|
||||
boolean singletonPalette = section.getBitsPerBlock() == 0;
|
||||
if(singletonPalette) {
|
||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
||||
}else if(section.getBitsPerBlock() < 15) {
|
||||
section.processPalette();
|
||||
}
|
||||
|
||||
if(section.isSkipSection() || singletonPalette || (!section.blockPrecise() && section.isPaletted())) {
|
||||
section.skipDataArray();
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readDataArray());
|
||||
|
||||
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;
|
||||
|
||||
switch (section.test(x, y, z)) {
|
||||
case SKIP:
|
||||
break;
|
||||
case CHECK:
|
||||
if(!section.getObfuscate().contains(values.a(pos)))
|
||||
break;
|
||||
case HIDE:
|
||||
values.b(pos, section.getTarget());
|
||||
break;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
values.b(pos, section.getAir());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.writeDataArray(values.a());
|
||||
}
|
||||
|
||||
private void biomes(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
boolean singletonPalette = section.getBitsPerBlock() == 0;
|
||||
if(singletonPalette)
|
||||
section.copyVarInt();
|
||||
else if(section.getBitsPerBlock() < 6)
|
||||
section.skipPalette();
|
||||
|
||||
section.skipDataArray();
|
||||
}
|
||||
}
|
||||
@@ -1,109 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.core.SectionPosition;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak;
|
||||
import net.minecraft.world.level.block.entity.TileEntitySign;
|
||||
import net.minecraft.world.level.block.entity.TileEntityTypes;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ProtocolWrapper18 implements ProtocolWrapper {
|
||||
|
||||
private static final Reflection.Field<SectionPosition> multiBlockChangeChunk = Reflection.getField(TechHider.multiBlockChangePacket, SectionPosition.class, 0);
|
||||
private static final Reflection.Field<short[]> multiBlockChangePos = Reflection.getField(TechHider.multiBlockChangePacket, short[].class, 0);
|
||||
private static final Reflection.Field<IBlockData[]> multiBlockChangeBlocks = Reflection.getField(TechHider.multiBlockChangePacket, IBlockData[].class, 0);
|
||||
@Override
|
||||
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;
|
||||
|
||||
packet = TechHider.multiBlockChangeCloner.apply(packet);
|
||||
final short[] oldPos = multiBlockChangePos.get(packet);
|
||||
final IBlockData[] oldBlocks = multiBlockChangeBlocks.get(packet);
|
||||
ArrayList<Short> poss = new ArrayList<>(oldPos.length);
|
||||
ArrayList<IBlockData> blocks = new ArrayList<>(oldPos.length);
|
||||
for(int i = 0; i < oldPos.length; i++) {
|
||||
short pos = oldPos[i];
|
||||
IBlockData 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) ? (IBlockData) techHider.getObfuscationTarget() : block);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(blocks.isEmpty())
|
||||
return null;
|
||||
|
||||
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 IBlockData[0]));
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
private static final Reflection.Field<TileEntityTypes> tileEntityType = Reflection.getField(TechHider.tileEntityDataPacket, TileEntityTypes.class, 0);
|
||||
private static final TileEntityTypes<?> signType = Reflection.getField(TileEntityTypes.class, TileEntityTypes.class, 0, TileEntitySign.class).get(null);
|
||||
@Override
|
||||
public boolean unfilteredTileEntityDataAction(Object packet) {
|
||||
return tileEntityType.get(packet) != signType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
PacketPlayOutBlockBreak breakPacket = (PacketPlayOutBlockBreak) packet;
|
||||
switch (techHider.getLocationEvaluator().checkBlockPos(p, breakPacket.b())) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if(!techHider.iBlockDataHidden(breakPacket.c()))
|
||||
return packet;
|
||||
case HIDE:
|
||||
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) techHider.getObfuscationTarget(), breakPacket.d(), breakPacket.a());
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) TechHider.AIR, breakPacket.d(), breakPacket.a());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,37 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_14", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_18", "default"))
|
||||
|
||||
compileOnly(libs.worldedit15)
|
||||
compileOnly(libs.nms19)
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
compileOnly(libs.brigadier)
|
||||
compileOnly(libs.datafixer)
|
||||
compileOnly(libs.authlib)
|
||||
}
|
||||
@@ -1,45 +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 net.minecraft.network.chat.IChatMutableComponent;
|
||||
import net.minecraft.network.chat.contents.LiteralContents;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
|
||||
import net.minecraft.network.syncher.DataWatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ChatWrapper19 implements ChatWrapper {
|
||||
|
||||
@Override
|
||||
public Object stringToChatComponent(String text) {
|
||||
return IChatMutableComponent.a(new LiteralContents(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDataWatcherPacket(int entityId, Object... dataWatcherKeyValues) {
|
||||
ArrayList<DataWatcher.b<?>> nativeWatchers = new ArrayList<>(1);
|
||||
for(int i = 0; i < dataWatcherKeyValues.length; i+=2) {
|
||||
nativeWatchers.add(((DataWatcher.Item<?>) BountifulWrapper.impl.getDataWatcherItem(dataWatcherKeyValues[i], dataWatcherKeyValues[i+1])).e());
|
||||
}
|
||||
|
||||
return new PacketPlayOutEntityMetadata(entityId, nativeWatchers);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +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 de.steamwar.Reflection;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.SystemUtils;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.world.level.EnumGamemode;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public class ProtocolWrapper19 implements ProtocolWrapper {
|
||||
|
||||
private static final Reflection.Field<List> equipmentStack = Reflection.getField(equipmentPacket, List.class, 0);
|
||||
@Override
|
||||
public void setEquipmentPacketStack(Object packet, Object slot, Object stack) {
|
||||
equipmentStack.set(packet, Collections.singletonList(new Pair<>(slot, stack)));
|
||||
}
|
||||
|
||||
private static final Reflection.Constructor removePacketConstructor = Reflection.getConstructor(ClientboundPlayerInfoRemovePacket.class, List.class);
|
||||
private static final Reflection.Field<EnumSet> updateActions = Reflection.getField(ClientboundPlayerInfoUpdatePacket.class, EnumSet.class, 0);
|
||||
private static final Reflection.Field<List> updatePlayers = Reflection.getField(ClientboundPlayerInfoUpdatePacket.class, List.class, 0);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) {
|
||||
if(action == PlayerInfoAction.REMOVE)
|
||||
return removePacketConstructor.invoke(Collections.singletonList(profile.getId()));
|
||||
|
||||
Object packet = Reflection.newInstance(ClientboundPlayerInfoUpdatePacket.class);
|
||||
updateActions.set(packet, action == PlayerInfoAction.ADD ? EnumSet.of(ClientboundPlayerInfoUpdatePacket.a.a, ClientboundPlayerInfoUpdatePacket.a.c) : EnumSet.of(ClientboundPlayerInfoUpdatePacket.a.c));
|
||||
updatePlayers.set(packet, Collections.singletonList(new ClientboundPlayerInfoUpdatePacket.b(profile.getId(), profile, false, 0, EnumGamemode.a(mode.getValue()), null, null)));
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initTPSWarp(LongSupplier longSupplier) {
|
||||
SystemUtils.a = () -> System.nanoTime() + longSupplier.getAsLong();
|
||||
}
|
||||
}
|
||||
@@ -1,68 +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 com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutLogin;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.World;
|
||||
|
||||
public class WorldIdentifier19 implements WorldIdentifier.IWorldIdentifier {
|
||||
|
||||
private static ResourceKey<World> 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);
|
||||
|
||||
@Override
|
||||
public void setResourceKey(String name) {
|
||||
resourceKey = (ResourceKey<World>) resourceKeyConstructor.invoke(minecraftKeyConstructor.invoke("minecraft", "dimension"), minecraftKeyConstructor.invoke("steamwar", name));
|
||||
}
|
||||
|
||||
public WorldIdentifier19() {
|
||||
TinyProtocol.instance.addFilter(PacketPlayOutLogin.class, (player, o) -> {
|
||||
if (resourceKey == null) return o;
|
||||
PacketPlayOutLogin packet = (PacketPlayOutLogin) o;
|
||||
|
||||
return new PacketPlayOutLogin(
|
||||
packet.b(),
|
||||
packet.c(),
|
||||
packet.d(),
|
||||
packet.e(),
|
||||
packet.f(),
|
||||
packet.g(),
|
||||
packet.h(),
|
||||
resourceKey,
|
||||
packet.j(),
|
||||
packet.k(),
|
||||
packet.l(),
|
||||
packet.m(),
|
||||
packet.n(),
|
||||
packet.o(),
|
||||
packet.p(),
|
||||
packet.q(),
|
||||
packet.r()
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
-68
@@ -1,68 +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.authlib;
|
||||
|
||||
import com.mojang.authlib.Agent;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.GameProfileRepository;
|
||||
import com.mojang.authlib.ProfileLookupCallback;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.Services;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SteamwarGameProfileRepository19 extends 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.c();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject() {
|
||||
Services newServices = new Services(current.a(), current.b(), this, current.d(), current.paperConfigurations());
|
||||
field.set(MinecraftServer.getServer(), newServices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findProfilesByNames(String[] strings, Agent agent, 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]), agent, profileLookupCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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.techhider;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ProtocolWrapper19 extends ProtocolWrapper18 {
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
|
||||
compileOnly(libs.fawe18)
|
||||
compileOnly(libs.nms20)
|
||||
}
|
||||
@@ -1,41 +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 de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.world.level.World;
|
||||
import net.minecraft.world.level.chunk.Chunk;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CraftbukkitWrapper20 implements CraftbukkitWrapper.ICraftbukkitWrapper {
|
||||
|
||||
private static final Reflection.Method getHandle = Reflection.getMethod("org.bukkit.craftbukkit.CraftChunk", "getHandle", ChunkStatus.class);
|
||||
private static final Reflection.Method getLightEngine = Reflection.getTypedMethod(World.class, null, LevelLightEngine.class);
|
||||
|
||||
@Override
|
||||
public void sendChunk(Player p, int chunkX, int chunkZ) {
|
||||
Chunk chunk = (Chunk) getHandle.invoke(p.getWorld().getChunkAt(chunkX, chunkZ), ChunkStatus.n);
|
||||
TinyProtocol.instance.sendPacket(p, new ClientboundLevelChunkWithLightPacket(chunk, (LevelLightEngine) getLightEngine.invoke(chunk.r), null, null, true));
|
||||
}
|
||||
}
|
||||
@@ -1,117 +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 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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WorldEditRendererWrapper20 implements WorldEditRendererWrapper {
|
||||
|
||||
private static final class BoxPair {
|
||||
private CWireframe regionBox;
|
||||
private CWireframe clipboardBox;
|
||||
|
||||
public CWireframe get(boolean clipboard) {
|
||||
if (clipboard) {
|
||||
return clipboardBox;
|
||||
} else {
|
||||
return regionBox;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(boolean clipboard, CWireframe box) {
|
||||
if (clipboard) {
|
||||
this.clipboardBox = box;
|
||||
} else {
|
||||
this.regionBox = box;
|
||||
}
|
||||
}
|
||||
|
||||
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<>();
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Player player) {
|
||||
REntityServer server = servers.get(player);
|
||||
if (server != null) server.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,70 +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 com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutLogin;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.World;
|
||||
|
||||
public class WorldIdentifier20 implements WorldIdentifier.IWorldIdentifier {
|
||||
|
||||
private static ResourceKey<World> resourceKey = null;
|
||||
|
||||
private static final Reflection.Field<Integer> playerId = Reflection.getField(PacketPlayOutLogin.class, int.class, 0);
|
||||
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);
|
||||
|
||||
@Override
|
||||
public void setResourceKey(String name) {
|
||||
resourceKey = (ResourceKey<World>) resourceKeyConstructor.invoke(minecraftKeyConstructor.invoke("minecraft", "dimension"), minecraftKeyConstructor.invoke("steamwar", name));
|
||||
}
|
||||
|
||||
public WorldIdentifier20() {
|
||||
TinyProtocol.instance.addFilter(PacketPlayOutLogin.class, (player, o) -> {
|
||||
if (resourceKey == null) return o;
|
||||
PacketPlayOutLogin packet = (PacketPlayOutLogin) o;
|
||||
|
||||
return new PacketPlayOutLogin(
|
||||
playerId.get(packet),
|
||||
packet.c(),
|
||||
packet.d(),
|
||||
packet.e(),
|
||||
packet.f(),
|
||||
packet.g(),
|
||||
packet.h(),
|
||||
resourceKey,
|
||||
packet.j(),
|
||||
packet.k(),
|
||||
packet.l(),
|
||||
packet.m(),
|
||||
packet.n(),
|
||||
packet.o(),
|
||||
packet.p(),
|
||||
packet.q(),
|
||||
packet.r(),
|
||||
packet.s()
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,44 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_18", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_14", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_9", "default"))
|
||||
|
||||
compileOnly(libs.fawe21)
|
||||
|
||||
compileOnly(libs.paperapi21)
|
||||
compileOnly(libs.nms21)
|
||||
compileOnly(libs.authlib2)
|
||||
compileOnly(libs.datafixer)
|
||||
compileOnly(libs.netty)
|
||||
compileOnly(libs.authlib)
|
||||
}
|
||||
@@ -1,42 +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 de.steamwar.Reflection;
|
||||
import net.minecraft.world.entity.PositionMoveRotation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class BountifulWrapper21 extends BountifulWrapper9 {
|
||||
|
||||
@Override
|
||||
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) {
|
||||
return super.getPositionSetter(packetClass, fieldOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +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 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;
|
||||
|
||||
public class ChatWrapper21 implements ChatWrapper {
|
||||
@Override
|
||||
public Object stringToChatComponent(String text) {
|
||||
return MutableComponent.create(PlainTextContents.create(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +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 de.steamwar.Reflection;
|
||||
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 CraftbukkitWrapper21 implements CraftbukkitWrapper.ICraftbukkitWrapper {
|
||||
|
||||
private static final Reflection.Method getHandle = Reflection.getMethod("org.bukkit.craftbukkit.CraftChunk", "getHandle", ChunkStatus.class);
|
||||
|
||||
@Override
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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 com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
public class FlatteningWrapper21 extends FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper {
|
||||
|
||||
@Override
|
||||
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 Object shooting = entityPose.getEnumConstants()[16];
|
||||
@Override
|
||||
public Object getPose(FlatteningWrapper.EntityPose pose) {
|
||||
if (pose == FlatteningWrapper.EntityPose.SHOOTING) return shooting;
|
||||
return super.getPose(pose);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +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 com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
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.Collections;
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class ProtocolWrapper21 implements ProtocolWrapper {
|
||||
@Override
|
||||
public void setEquipmentPacketStack(Object packet, Object slot, Object stack) {
|
||||
ClientboundSetEquipmentPacket setEquipmentPacket = (ClientboundSetEquipmentPacket) packet;
|
||||
setEquipmentPacket.getSlots().add(Pair.of((EquipmentSlot) slot, (ItemStack) stack));
|
||||
}
|
||||
|
||||
@Override
|
||||
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)));
|
||||
}
|
||||
}
|
||||
@@ -1,29 +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 org.bukkit.Particle;
|
||||
|
||||
public class TrickyParticleWrapper21 implements TrickyParticleWrapper {
|
||||
@Override
|
||||
public Particle getVillagerHappy() {
|
||||
return Particle.HAPPY_VILLAGER;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +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 com.mojang.authlib.properties.Property;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
|
||||
public class TrickyTrialsWrapper21 implements TrickyTrialsWrapper {
|
||||
@Override
|
||||
public EntityType getTntEntityType() {
|
||||
return EntityType.TNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enchantment getUnbreakingEnchantment() {
|
||||
return Enchantment.UNBREAKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getTurtleScute() {
|
||||
return Material.TURTLE_SCUTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Property property) {
|
||||
return property.value();
|
||||
}
|
||||
}
|
||||
@@ -1,182 +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 com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
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;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.enginehub.linbus.stream.LinBinaryIO;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class WorldEditWrapper21 implements WorldEditWrapper {
|
||||
|
||||
@Override
|
||||
public InputStream getPlayerClipboard(Player player) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, (outputStream, clipboard, clipboardHolder) -> {
|
||||
ClipboardWriter writer = BuiltInClipboardFormat.FAST_V3.getWriter(outputStream);
|
||||
writer.write(clipboard);
|
||||
writer.close();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerClipboard(Player player, Clipboard clipboard) {
|
||||
Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player);
|
||||
WorldEditWrapper.getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard));
|
||||
}
|
||||
|
||||
@Override
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.util.Vector getOrigin(Clipboard clipboard) {
|
||||
return new org.bukkit.util.Vector(clipboard.getOrigin().x(), clipboard.getOrigin().y(), clipboard.getOrigin().z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getMinimum(Region region) {
|
||||
return new Vector(region.getMinimumPoint().x(), region.getMinimumPoint().y(), region.getMinimumPoint().z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector getMaximum(Region region) {
|
||||
return new Vector(region.getMaximumPoint().x(), region.getMaximumPoint().y(), region.getMaximumPoint().z());
|
||||
}
|
||||
|
||||
@Override
|
||||
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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeData.SchematicFormat getNativeFormat() {
|
||||
return NodeData.SchematicFormat.SPONGE_V3;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +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 com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
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;
|
||||
|
||||
public class WorldIdentifier21 implements WorldIdentifier.IWorldIdentifier {
|
||||
|
||||
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);
|
||||
|
||||
@Override
|
||||
public void setResourceKey(String name) {
|
||||
resourceKey = (ResourceKey<Level>) resourceKeyConstructor.invoke(minecraftKeyConstructor.invoke("minecraft", "dimension"), minecraftKeyConstructor.invoke("steamwar", name));
|
||||
}
|
||||
|
||||
public WorldIdentifier21() {
|
||||
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()
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
-73
@@ -1,73 +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.authlib;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.GameProfileRepository;
|
||||
import com.mojang.authlib.ProfileLookupCallback;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.Services;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SteamwarGameProfileRepository21 extends 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject() {
|
||||
Services newServices = new Services(current.sessionService(), current.servicesKeySet(), this, current.profileCache(), current.paperConfigurations());
|
||||
field.set(MinecraftServer.getServer(), newServices);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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.entity;
|
||||
|
||||
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;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class PacketConstructor21 implements PacketConstructor{
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +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.scoreboard;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SWScoreboard21 implements 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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createScoreboard(Player player, ScoreboardCallback callback) {
|
||||
Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
|
||||
player.setScoreboard(scoreboard);
|
||||
|
||||
render(player, callback);
|
||||
|
||||
playerBoards.put(player, callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeScoreboard(Player player) {
|
||||
player.getScoreboard().getObjective(SIDEBAR).unregister();
|
||||
playerBoards.remove(player);
|
||||
}
|
||||
}
|
||||
@@ -1,161 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
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.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ChunkHider21 implements ChunkHider {
|
||||
@Override
|
||||
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);
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
|
||||
compileOnly(libs.nms8)
|
||||
compileOnly(libs.worldedit12)
|
||||
}
|
||||
@@ -1,106 +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 de.steamwar.Reflection;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.minecraft.server.v1_8_R3.ChatComponentText;
|
||||
import net.minecraft.server.v1_8_R3.MathHelper;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutChat;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BountifulWrapper8 implements BountifulWrapper.IBountifulWrapper {
|
||||
|
||||
@Override
|
||||
public void playPling(Player player) {
|
||||
player.playSound(player.getLocation(), Sound.ORB_PICKUP, 1, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) {
|
||||
((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(BaseComponent.toLegacyText(msg)), (byte)type.ordinal()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDataWatcherObject(int index, Class<?> type) {
|
||||
return index;
|
||||
}
|
||||
|
||||
private static final Class<?> watchableObject = Reflection.getClass("net.minecraft.DataWatcher$WatchableObject");
|
||||
private static final Reflection.Constructor watchableObjectConstructor = Reflection.getConstructor(watchableObject, int.class, int.class, Object.class);
|
||||
private static final Map<Class<?>, Integer> watchableDatatypes = new HashMap<>();
|
||||
static {
|
||||
watchableDatatypes.put(byte.class, 0);
|
||||
watchableDatatypes.put(short.class, 1);
|
||||
watchableDatatypes.put(int.class, 2);
|
||||
watchableDatatypes.put(float.class, 3);
|
||||
watchableDatatypes.put(String.class, 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDataWatcherItem(Object dwo, Object value) {
|
||||
return watchableObjectConstructor.invoke(watchableDatatypes.get(value.getClass()), dwo, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BountifulWrapper.PositionSetter getPositionSetter(Class<?> packetClass, int fieldOffset) {
|
||||
Reflection.Field<Integer> posX = Reflection.getField(packetClass, int.class, fieldOffset);
|
||||
Reflection.Field<Integer> posY = Reflection.getField(packetClass, int.class, fieldOffset +1);
|
||||
Reflection.Field<Integer> posZ = Reflection.getField(packetClass, int.class, fieldOffset +2);
|
||||
Reflection.Field<Byte> lookYaw = Reflection.getField(packetClass, byte.class, 0);
|
||||
Reflection.Field<Byte> lookPitch = Reflection.getField(packetClass, byte.class, 1);
|
||||
|
||||
return (packet, x, y, z, pitch, yaw) -> {
|
||||
posX.set(packet, MathHelper.floor(x * 32));
|
||||
posY.set(packet, MathHelper.floor(y * 32));
|
||||
posZ.set(packet, MathHelper.floor(z * 32));
|
||||
lookYaw.set(packet, (byte)(yaw * 256 / 360));
|
||||
lookPitch.set(packet, (byte)(pitch * 256 / 360));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BountifulWrapper.PositionSetter getRelMoveSetter(Class<?> packetClass) {
|
||||
Reflection.Field<?> moveX = Reflection.getField(packetClass, "b", byte.class);
|
||||
Reflection.Field<?> moveY = Reflection.getField(packetClass, "c", byte.class);
|
||||
Reflection.Field<?> moveZ = Reflection.getField(packetClass, "d", byte.class);
|
||||
Reflection.Field<Byte> lookYaw = Reflection.getField(packetClass, "e", byte.class);
|
||||
Reflection.Field<Byte> lookPitch = Reflection.getField(packetClass, "f", byte.class);
|
||||
|
||||
return (packet, x, y, z, pitch, yaw) -> {
|
||||
moveX.set(packet, (byte)(x*32));
|
||||
moveY.set(packet, (byte)(y*32));
|
||||
moveZ.set(packet, (byte)(z*32));
|
||||
lookYaw.set(packet, (byte)(yaw*256/360));
|
||||
lookPitch.set(packet, (byte)(pitch*256/360));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BountifulWrapper.UUIDSetter getUUIDSetter(Class<?> packetClass) {
|
||||
return (packet, uuid) -> {};
|
||||
}
|
||||
}
|
||||
@@ -1,51 +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 de.steamwar.Reflection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChatWrapper8 implements ChatWrapper {
|
||||
|
||||
private static final Reflection.Constructor chatComponentConstructor = Reflection.getConstructor(Reflection.getClass("net.minecraft.network.chat.ChatComponentText"), String.class);
|
||||
@Override
|
||||
public Object stringToChatComponent(String text) {
|
||||
return chatComponentConstructor.invoke(text);
|
||||
}
|
||||
|
||||
private static final Class<?> metadataPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket");
|
||||
private static final Reflection.Field<Integer> metadataEntity = Reflection.getField(metadataPacket, int.class, 0);
|
||||
private static final Reflection.Field<List> metadataMetadata = Reflection.getField(metadataPacket, List.class, 0);
|
||||
@Override
|
||||
public Object getDataWatcherPacket(int entityId, Object... dataWatcherKeyValues) {
|
||||
Object packet = Reflection.newInstance(metadataPacket);
|
||||
metadataEntity.set(packet, entityId);
|
||||
|
||||
ArrayList<Object> nativeWatchers = new ArrayList<>(1);
|
||||
for(int i = 0; i < dataWatcherKeyValues.length; i+=2) {
|
||||
nativeWatchers.add(BountifulWrapper.impl.getDataWatcherItem(dataWatcherKeyValues[i], dataWatcherKeyValues[i+1]));
|
||||
}
|
||||
metadataMetadata.set(packet, nativeWatchers);
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +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 net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CraftbukkitWrapper8 implements CraftbukkitWrapper.ICraftbukkitWrapper {
|
||||
|
||||
@Override
|
||||
public void sendChunk(Player p, int chunkX, int chunkZ) {
|
||||
((CraftPlayer)p).getHandle().playerConnection.sendPacket(new PacketPlayOutMapChunk(((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(), true, 65535));
|
||||
}
|
||||
}
|
||||
@@ -1,121 +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 de.steamwar.Reflection;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
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;
|
||||
|
||||
public class FlatteningWrapper8 implements FlatteningWrapper.IFlatteningWrapper {
|
||||
|
||||
private static final Reflection.Field<String> scoreboardName = Reflection.getField(FlatteningWrapper.scoreboardObjective, String.class, 1);
|
||||
private static final Class<?> scoreActionEnum = Reflection.getClass("net.minecraft.PacketPlayOutScoreboardScore$EnumScoreboardAction");
|
||||
private static final Reflection.Field<?> scoreAction = Reflection.getField(FlatteningWrapper.scoreboardScore, scoreActionEnum, 0);
|
||||
private static final Object scoreActionChange = scoreActionEnum.getEnumConstants()[0];
|
||||
|
||||
@Override
|
||||
public void setScoreboardTitle(Object packet, String title) {
|
||||
scoreboardName.set(packet, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScoreAction(Object packet) {
|
||||
scoreAction.set(packet, scoreActionChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getMaterial(String material) {
|
||||
try{
|
||||
return Material.valueOf(material);
|
||||
}catch(IllegalArgumentException e){
|
||||
return Material.STONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getDye(int colorCode) {
|
||||
return Material.INK_SACK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack setSkullOwner(String player) {
|
||||
ItemStack head = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
|
||||
SkullMeta headmeta = (SkullMeta) head.getItemMeta();
|
||||
headmeta.setOwner(player.startsWith(".") ? player.substring(1) : player);
|
||||
headmeta.setDisplayName(player);
|
||||
head.setItemMeta(headmeta);
|
||||
return head;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPose(FlatteningWrapper.EntityPose pose) {
|
||||
return Byte.valueOf((byte)(pose == FlatteningWrapper.EntityPose.SNEAKING ? 2 : 0));
|
||||
}
|
||||
|
||||
private static final Class<?> dataWatcher = Reflection.getClass("net.minecraft.DataWatcher");
|
||||
private static final Class<?> namedSpawnPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundAddPlayerPacket");
|
||||
private static final Reflection.Field<?> namedSpawnDataWatcher = Reflection.getField(namedSpawnPacket, dataWatcher, 0);
|
||||
private static final Class<?> entity = Reflection.getClass("net.minecraft.Entity");
|
||||
private static final Reflection.Constructor dataWatcherConstructor = Reflection.getConstructor(dataWatcher, entity);
|
||||
@Override
|
||||
public void setNamedSpawnPacketDataWatcher(Object packet) {
|
||||
namedSpawnDataWatcher.set(packet, dataWatcherConstructor.invoke((Object) null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object formatDisplayName(String displayName) {
|
||||
return displayName != null ? displayName : "";
|
||||
}
|
||||
|
||||
|
||||
private static final Reflection.Field<?> spawnType = Reflection.getField(ProtocolWrapper.spawnPacket, int.class, Core.getVersion() > 8 ? 6 : 9);
|
||||
private static final Reflection.Field<Integer> spawnLivingType = Reflection.getField(ProtocolWrapper.spawnLivingPacket, int.class, 1);
|
||||
private static final Map<EntityType, Object> types = new HashMap<>();
|
||||
static {
|
||||
types.put(TrickyTrialsWrapper.impl.getTntEntityType(), 50);
|
||||
types.put(EntityType.ARMOR_STAND, 30);
|
||||
types.put(EntityType.ARROW, 60);
|
||||
types.put(EntityType.FIREBALL, 63);
|
||||
types.put(EntityType.ITEM_FRAME, 18);
|
||||
types.put(EntityType.FALLING_BLOCK, 21);
|
||||
}
|
||||
@Override
|
||||
public void setSpawnPacketType(Object packet, EntityType type) {
|
||||
(type.isAlive() ? spawnLivingType : spawnType).set(packet, types.get(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewDistance(Player player) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
private static final Reflection.Method save = Reflection.getMethod("org.bukkit.craftbukkit.CraftWorld", "save", boolean.class);
|
||||
@Override
|
||||
public void syncSave(World world) {
|
||||
save.invoke(world, true);
|
||||
}
|
||||
}
|
||||
@@ -1,113 +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 org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class IDConverter8 {
|
||||
|
||||
private final Map<String, Set<String>> availibleAttributes;
|
||||
private final Map<String, Map<Set<String>, BlockTypeID>> map;
|
||||
|
||||
public IDConverter8() {
|
||||
Map<String, Map<Set<String>, BlockTypeID>> map = new HashMap<>();
|
||||
|
||||
YamlConfiguration legacy = YamlConfiguration.loadConfiguration(new InputStreamReader(Objects.requireNonNull(IDConverter8.class.getClassLoader().getResourceAsStream("legacy.yml"))));
|
||||
for(String blockString : legacy.getKeys(false)){
|
||||
String[] legacyBlockId = legacy.getString(blockString).split(":");
|
||||
|
||||
map.computeIfAbsent(getBlockId(blockString), bId -> {
|
||||
Map<Set<String>, BlockTypeID> attributeMap = new HashMap<>();
|
||||
attributeMap.put(new HashSet<>(), new BlockTypeID(legacyBlockId[0], "0"));
|
||||
return attributeMap;
|
||||
}).put(getAttributes(blockString), new BlockTypeID(legacyBlockId[0], legacyBlockId[1]));
|
||||
}
|
||||
this.map = map;
|
||||
|
||||
Map<String, Set<String>> availableAttributes = new HashMap<>();
|
||||
for (Map.Entry<String, Map<Set<String>, BlockTypeID>> entry : map.entrySet()) {
|
||||
availableAttributes.put(entry.getKey(), entry.getValue().keySet().stream().flatMap(Collection::stream).collect(Collectors.toSet()));
|
||||
}
|
||||
this.availibleAttributes = availableAttributes;
|
||||
}
|
||||
|
||||
public BlockTypeID getId(String blockString) {
|
||||
String blockId = getBlockId(blockString);
|
||||
Map<Set<String>, IDConverter8.BlockTypeID> attributeMap = map.get(blockId);
|
||||
if(attributeMap == null) { // Block nonexistent pre-flattening
|
||||
return new BlockTypeID("0", "0");
|
||||
}
|
||||
|
||||
Set<String> attributes = getAttributes(blockString);
|
||||
Set<String> knownAttributes = this.availibleAttributes.get(blockId);
|
||||
attributes.removeIf(attribute -> !knownAttributes.contains(attribute));
|
||||
|
||||
long bestMatch = -1;
|
||||
BlockTypeID blockID = null;
|
||||
for(Map.Entry<Set<String>, BlockTypeID> entry : attributeMap.entrySet()) {
|
||||
Set<String> attrs = entry.getKey();
|
||||
if(attrs.size() <= bestMatch)
|
||||
continue;
|
||||
|
||||
long matching = attributes.stream().filter(attrs::contains).count();
|
||||
if(matching > bestMatch) {
|
||||
blockID = entry.getValue();
|
||||
bestMatch = matching;
|
||||
|
||||
if(bestMatch == attributes.size())
|
||||
break;
|
||||
}
|
||||
}
|
||||
return blockID;
|
||||
}
|
||||
|
||||
private String getBlockId(String blockString) {
|
||||
return blockString.split("\\[", 2)[0];
|
||||
}
|
||||
|
||||
private Set<String> getAttributes(String blockString) {
|
||||
Set<String> attributes = new HashSet<>();
|
||||
if(blockString.contains("["))
|
||||
Collections.addAll(attributes, blockString.split("\\[")[1].replace("]", "").split(","));
|
||||
return attributes;
|
||||
}
|
||||
|
||||
static class BlockTypeID{
|
||||
private final int blockId;
|
||||
private final byte dataId;
|
||||
|
||||
private BlockTypeID(String blockId, String dataId) {
|
||||
this.blockId = Integer.parseInt(blockId);
|
||||
this.dataId = Byte.parseByte(dataId);
|
||||
}
|
||||
|
||||
int getBlockId() {
|
||||
return blockId;
|
||||
}
|
||||
|
||||
byte getDataId() {
|
||||
return dataId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +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;
|
||||
|
||||
public class LocaleChangeWrapper8 implements LocaleChangeWrapper {
|
||||
// Event not available in 1.8-1.10
|
||||
}
|
||||
@@ -1,71 +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 de.steamwar.Reflection;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ProtocolWrapper8 implements ProtocolWrapper {
|
||||
|
||||
private static final Reflection.Field<?> equipmentSlot;
|
||||
static {
|
||||
if(Core.getVersion() == 8) {
|
||||
equipmentSlot = Reflection.getField(equipmentPacket, int.class, 1);
|
||||
} else {
|
||||
Class<?> enumItemSlot = Reflection.getClass("net.minecraft.world.entity.EnumItemSlot");
|
||||
equipmentSlot = Reflection.getField(equipmentPacket, enumItemSlot, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Reflection.Field<?> equipmentStack = Reflection.getField(equipmentPacket, itemStack, 0);
|
||||
@Override
|
||||
public void setEquipmentPacketStack(Object packet, Object slot, Object stack) {
|
||||
equipmentSlot.set(packet, slot);
|
||||
equipmentStack.set(packet, stack);
|
||||
}
|
||||
|
||||
private static final Class<?> playerInfoPacket = Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo");
|
||||
private static final Class<?> playerInfoActionClass = Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
|
||||
private static final Reflection.Field<?> playerInfoAction = Reflection.getField(playerInfoPacket, playerInfoActionClass, 0);
|
||||
private static final Reflection.Field<List> playerInfoData = Reflection.getField(playerInfoPacket, List.class, 0);
|
||||
private static final EnumMap<PlayerInfoAction, Object> actions = new EnumMap<>(PlayerInfoAction.class);
|
||||
static {
|
||||
Object[] nativeActions = playerInfoActionClass.getEnumConstants();
|
||||
actions.put(PlayerInfoAction.ADD, nativeActions[0]);
|
||||
actions.put(PlayerInfoAction.GAMEMODE, nativeActions[1]);
|
||||
actions.put(PlayerInfoAction.REMOVE, nativeActions[4]);
|
||||
}
|
||||
private static final Class<?> iChatBaseComponent = Reflection.getClass("net.minecraft.network.chat.Component");
|
||||
private static final Reflection.Constructor playerInfoDataConstructor = Reflection.getConstructor("net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo$PlayerInfoData", playerInfoPacket, GameProfile.class, int.class, enumGamemode, iChatBaseComponent);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) {
|
||||
Object packet = Reflection.newInstance(playerInfoPacket);
|
||||
playerInfoAction.set(packet, actions.get(action));
|
||||
playerInfoData.set(packet, Collections.singletonList(playerInfoDataConstructor.invoke(packet, profile, 0, ProtocolWrapper.getGameModeById.invoke(null, mode.getValue()), null)));
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +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;
|
||||
|
||||
public class RecipeDiscoverWrapper8 implements RecipeDiscoverWrapper {
|
||||
// Event not available pre flattening
|
||||
}
|
||||
@@ -1,49 +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 com.mojang.authlib.properties.Property;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
|
||||
public class TrickyTrialsWrapper8 implements TrickyTrialsWrapper {
|
||||
@Override
|
||||
public EntityType getTntEntityType() {
|
||||
return EntityType.PRIMED_TNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enchantment getUnbreakingEnchantment() {
|
||||
return Enchantment.DURABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getTurtleScute() {
|
||||
return Material.STONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Property property) {
|
||||
return property.getValue();
|
||||
}
|
||||
}
|
||||
@@ -1,42 +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 org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class WorldEditRendererWrapper8 implements WorldEditRendererWrapper {
|
||||
|
||||
@Override
|
||||
public void draw(Player player, boolean scheduled, boolean clipboard, Vector pos1, Vector pos2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(Player player, boolean clipboard, boolean hide) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Player player) {
|
||||
}
|
||||
}
|
||||
@@ -1,305 +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 com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sk89q.jnbt.*;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.SchematicReader;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WorldEditWrapper8 implements WorldEditWrapper {
|
||||
|
||||
@Override
|
||||
public InputStream getPlayerClipboard(Player player) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, (outputStream, clipboard, clipboardHolder) ->
|
||||
ClipboardFormat.SCHEMATIC.getWriter(outputStream).write(clipboard, clipboardHolder.getWorldData()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerClipboard(Player player, Clipboard clipboard) {
|
||||
WorldData world = new BukkitWorld(player.getWorld()).getWorldData();
|
||||
Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player);
|
||||
WorldEditWrapper.getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard, world));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard(NodeData data) throws IOException {
|
||||
InputStream is = data.schemData(true);
|
||||
return readClipboard(is, data.getNodeFormat());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard(InputStream inputStream) throws IOException {
|
||||
return readClipboard(inputStream, getNativeFormat());
|
||||
}
|
||||
|
||||
private Clipboard readClipboard(InputStream is, NodeData.SchematicFormat format) throws IOException {
|
||||
switch (format) {
|
||||
case MCEDIT:
|
||||
return new SchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData());
|
||||
case SPONGE_V2:
|
||||
case SPONGE_V3:
|
||||
return new SpongeSchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData());
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported schematic format");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.util.Vector getOrigin(Clipboard clipboard) {
|
||||
return new org.bukkit.util.Vector(clipboard.getOrigin().getX(), clipboard.getOrigin().getY(), clipboard.getOrigin().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.util.Vector getMinimum(Region region) {
|
||||
return new org.bukkit.util.Vector(region.getMinimumPoint().getX(), region.getMinimumPoint().getY(), region.getMinimumPoint().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.util.Vector getMaximum(Region region) {
|
||||
return new org.bukkit.util.Vector(region.getMaximumPoint().getX(), region.getMaximumPoint().getY(), region.getMaximumPoint().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.util.Vector applyTransform(org.bukkit.util.Vector vector, Transform transform) {
|
||||
Vector v = new Vector(vector.getX(), vector.getY(), vector.getZ());
|
||||
v = transform.apply(v);
|
||||
return new org.bukkit.util.Vector(v.getX(), v.getY(), v.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeData.SchematicFormat getNativeFormat() {
|
||||
return NodeData.SchematicFormat.MCEDIT;
|
||||
}
|
||||
|
||||
private static class SpongeSchematicReader implements ClipboardReader {
|
||||
|
||||
private final NBTInputStream inputStream;
|
||||
private int schematicVersion = -1;
|
||||
|
||||
SpongeSchematicReader(NBTInputStream inputStream) {
|
||||
Preconditions.checkNotNull(inputStream);
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard read(WorldData worldData) throws IOException {
|
||||
CompoundTag schematicTag = this.getBaseTag();
|
||||
if (this.schematicVersion == 1) {
|
||||
return this.readSchematic(schematicTag);
|
||||
} else if (this.schematicVersion == 2) {
|
||||
return this.readSchematic(schematicTag);
|
||||
} else {
|
||||
throw new IOException("This schematic version is currently not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private CompoundTag getBaseTag() throws IOException {
|
||||
NamedTag rootTag = this.inputStream.readNamedTag();
|
||||
if (!rootTag.getName().equals("Schematic")) {
|
||||
throw new IOException("Tag 'Schematic' does not exist or is not first");
|
||||
} else {
|
||||
CompoundTag schematicTag = (CompoundTag)rootTag.getTag();
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
this.schematicVersion = (requireTag(schematic, "Version", IntTag.class)).getValue();
|
||||
return schematicTag;
|
||||
}
|
||||
}
|
||||
|
||||
private BlockArrayClipboard readSchematic(CompoundTag schematicTag) throws IOException {
|
||||
IDConverter8 ids = new IDConverter8();
|
||||
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
boolean v3Mode = false;
|
||||
|
||||
if (schematic.size() == 1) {
|
||||
schematic = (requireTag(schematic, "Schematic", CompoundTag.class)).getValue();
|
||||
v3Mode = true;
|
||||
}
|
||||
|
||||
int width = (requireTag(schematic, "Width", ShortTag.class)).getValue();
|
||||
int height = (requireTag(schematic, "Height", ShortTag.class)).getValue();
|
||||
int length = (requireTag(schematic, "Length", ShortTag.class)).getValue();
|
||||
IntArrayTag offsetTag = getTag(schematic, "Offset", IntArrayTag.class);
|
||||
int[] offsetParts;
|
||||
if (offsetTag != null) {
|
||||
offsetParts = offsetTag.getValue();
|
||||
if (offsetParts.length != 3)
|
||||
throw new IOException("Invalid offset specified in schematic.");
|
||||
} else {
|
||||
offsetParts = new int[]{0, 0, 0};
|
||||
}
|
||||
|
||||
BlockVector min = new BlockVector(offsetParts[0], offsetParts[1], offsetParts[2]);
|
||||
CompoundTag metadataTag = getTag(schematic, "Metadata", CompoundTag.class);
|
||||
Vector origin;
|
||||
CuboidRegion region;
|
||||
if (metadataTag != null && metadataTag.containsKey("WEOffsetX")) {
|
||||
Map<String, Tag> metadata = metadataTag.getValue();
|
||||
int offsetX = (requireTag(metadata, "WEOffsetX", IntTag.class)).getValue();
|
||||
int offsetY = (requireTag(metadata, "WEOffsetY", IntTag.class)).getValue();
|
||||
int offsetZ = (requireTag(metadata, "WEOffsetZ", IntTag.class)).getValue();
|
||||
BlockVector offset = new BlockVector(offsetX, offsetY, offsetZ);
|
||||
origin = min.subtract(offset);
|
||||
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector.ONE));
|
||||
} else {
|
||||
origin = min;
|
||||
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector.ONE));
|
||||
}
|
||||
|
||||
Map<String, Tag> blockContainer = null;
|
||||
|
||||
if (v3Mode) {
|
||||
blockContainer = getTag(schematic, "Blocks", CompoundTag.class).getValue();
|
||||
}
|
||||
|
||||
Map<String, Tag> paletteObject = requireTag(v3Mode ? blockContainer : schematic, "Palette", CompoundTag.class).getValue();
|
||||
|
||||
Map<Integer, BaseBlock> palette = new HashMap<>();
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setRestricted(false);
|
||||
parserContext.setPreferringWildcard(false);
|
||||
|
||||
for(String palettePart : paletteObject.keySet()) {
|
||||
IDConverter8.BlockTypeID blockID = ids.getId(palettePart);
|
||||
palette.put(requireTag(paletteObject, palettePart, IntTag.class).getValue(), new BaseBlock(blockID.getBlockId(), blockID.getDataId()));
|
||||
}
|
||||
|
||||
byte[] blocks = requireTag(v3Mode ? blockContainer : schematic, v3Mode ? "Data" : "BlockData", ByteArrayTag.class).getValue();
|
||||
Map<BlockVector, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
|
||||
ListTag tileEntities = getTag(v3Mode ? blockContainer : schematic, "BlockEntities", ListTag.class);
|
||||
if (tileEntities == null) {
|
||||
tileEntities = getTag(v3Mode ? blockContainer : schematic, "TileEntities", ListTag.class);
|
||||
}
|
||||
|
||||
if (tileEntities != null) {
|
||||
List<Map<String, Tag>> tileEntityTags = tileEntities.getValue().stream().map((tag) ->
|
||||
(CompoundTag)tag
|
||||
).map(CompoundTag::getValue).collect(Collectors.toList());
|
||||
|
||||
BlockVector pt;
|
||||
Map<String, Tag> tileEntity;
|
||||
for(Iterator<Map<String, Tag>> var20 = tileEntityTags.iterator(); var20.hasNext(); tileEntitiesMap.put(pt, tileEntity)) {
|
||||
tileEntity = var20.next();
|
||||
int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue();
|
||||
pt = new BlockVector(pos[0], pos[1], pos[2]);
|
||||
Map<String, Tag> values = Maps.newHashMap(tileEntity);
|
||||
values.put("x", new IntTag(pt.getBlockX()));
|
||||
values.put("y", new IntTag(pt.getBlockY()));
|
||||
values.put("z", new IntTag(pt.getBlockZ()));
|
||||
values.put("id", values.get("Id"));
|
||||
values.remove("Id");
|
||||
values.remove("Pos");
|
||||
tileEntity = values;
|
||||
}
|
||||
}
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(origin);
|
||||
int index = 0;
|
||||
|
||||
for(int i = 0; i < blocks.length; ++index) {
|
||||
int value = 0;
|
||||
int varintLength = 0;
|
||||
|
||||
while(true) {
|
||||
value |= (blocks[i] & 127) << varintLength++ * 7;
|
||||
if (varintLength > 5) {
|
||||
throw new IOException("VarInt too big (probably corrupted data)");
|
||||
}
|
||||
|
||||
if ((blocks[i] & 128) != 128) {
|
||||
++i;
|
||||
int y = index / (width * length);
|
||||
int z = index % (width * length) / width;
|
||||
int x = index % (width * length) % width;
|
||||
BaseBlock block = palette.get(value);
|
||||
BlockVector pt = new BlockVector(x, y, z);
|
||||
|
||||
try {
|
||||
if (tileEntitiesMap.containsKey(pt)) {
|
||||
block.setNbtData(new CompoundTag(tileEntitiesMap.get(pt)));
|
||||
clipboard.setBlock(clipboard.getMinimumPoint().add(pt), block);
|
||||
} else {
|
||||
clipboard.setBlock(clipboard.getMinimumPoint().add(pt), block);
|
||||
}
|
||||
break;
|
||||
} catch (WorldEditException var30) {
|
||||
throw new IOException("Failed to load a block in the schematic");
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
private static <T extends Tag> T requireTag(Map<String, Tag> items, String key, Class<T> expected) throws IOException {
|
||||
if (!items.containsKey(key)) {
|
||||
throw new IOException("Schematic file is missing a \"" + key + "\" tag");
|
||||
} else {
|
||||
Tag tag = items.get(key);
|
||||
if (!expected.isInstance(tag)) {
|
||||
throw new IOException(key + " tag is not of tag type " + expected.getName());
|
||||
} else {
|
||||
return expected.cast(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Tag> T getTag(Map<String, Tag> items, String key, Class<T> expected) {
|
||||
if (!items.containsKey(key)) {
|
||||
return null;
|
||||
} else {
|
||||
Tag test = items.get(key);
|
||||
return !expected.isInstance(test) ? null : expected.cast(test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +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;
|
||||
|
||||
public class WorldIdentifier8 implements WorldIdentifier.IWorldIdentifier {
|
||||
|
||||
@Override
|
||||
public void setResourceKey(String name) {
|
||||
}
|
||||
}
|
||||
-72
@@ -1,72 +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.authlib;
|
||||
|
||||
import com.mojang.authlib.Agent;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.GameProfileRepository;
|
||||
import com.mojang.authlib.ProfileLookupCallback;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SteamwarGameProfileRepository8 extends SteamwarGameProfileRepository {
|
||||
|
||||
private static final GameProfileRepository fallback;
|
||||
|
||||
private static final Object minecraftServer;
|
||||
private static final Reflection.Field<?> gameProfile;
|
||||
|
||||
static {
|
||||
Class<?> minecraftServerClass = Reflection.getClass("net.minecraft.server.MinecraftServer");
|
||||
Class<?> gpr = Reflection.getClass("com.mojang.authlib.GameProfileRepository");
|
||||
gameProfile = Reflection.getField(minecraftServerClass, gpr, 0);
|
||||
minecraftServer = Reflection.getTypedMethod(minecraftServerClass, "getServer", minecraftServerClass).invoke(null);
|
||||
fallback = (GameProfileRepository) gameProfile.get(minecraftServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject() {
|
||||
gameProfile.set(minecraftServer, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findProfilesByNames(String[] strings, Agent agent, ProfileLookupCallback profileLookupCallback) {
|
||||
if(agent == Agent.SCROLLS) {
|
||||
fallback.findProfilesByNames(strings, agent, profileLookupCallback);
|
||||
} else {
|
||||
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]), agent, profileLookupCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +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.scoreboard;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.FlatteningWrapper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SWScoreboard8 implements SWScoreboard {
|
||||
private static final Reflection.Field<String> scoreboardName = Reflection.getField(FlatteningWrapper.scoreboardObjective, String.class, 0);
|
||||
private static final Reflection.Field<Integer> scoreboardAction = Reflection.getField(FlatteningWrapper.scoreboardObjective, int.class, Core.getVersion() > 15 ? 3 : 0);
|
||||
private static final Class<?> scoreboardDisplayEnum = Reflection.getClass("net.minecraft.world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay");
|
||||
private static final Reflection.Field<?> scoreboardDisplayType = Reflection.getField(FlatteningWrapper.scoreboardObjective, scoreboardDisplayEnum, 0);
|
||||
private static final Object displayTypeIntegers = scoreboardDisplayEnum.getEnumConstants()[0];
|
||||
|
||||
private static final Reflection.Field<String> scoreName = Reflection.getField(FlatteningWrapper.scoreboardScore, String.class, 0);
|
||||
private static final Reflection.Field<String> scoreScoreboardName = Reflection.getField(FlatteningWrapper.scoreboardScore, String.class, 1);
|
||||
private static final Reflection.Field<Integer> scoreValue = Reflection.getField(FlatteningWrapper.scoreboardScore, int.class, 0);
|
||||
|
||||
private static final HashMap<Player, ScoreboardCallback> playerBoards = new HashMap<>(); //Object -> Scoreboard | Alle Versionen in der Map!
|
||||
private static int toggle = 0; // Scoreboard 0 updates while scoreboard 1 is presenting. toggle marks the current active scoreboard
|
||||
|
||||
private static final String SIDEBAR = "Sidebar";
|
||||
private static final Object[] DELETE_SCOREBOARD = new Object[2];
|
||||
private static final Object[] DISPLAY_SIDEBAR = new Object[2];
|
||||
|
||||
static {
|
||||
Class<?> scoreboardDisplayObjective = Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective");
|
||||
Reflection.Field<String> scoreboardDisplayName = Reflection.getField(scoreboardDisplayObjective, String.class, 0);
|
||||
Reflection.Field<Integer> scoreboardDisplaySlot = Reflection.getField(scoreboardDisplayObjective, int.class, 0);
|
||||
for(int id = 0; id < 2; id++) {
|
||||
DELETE_SCOREBOARD[id] = Reflection.newInstance(FlatteningWrapper.scoreboardObjective);
|
||||
scoreboardName.set(DELETE_SCOREBOARD[id], SIDEBAR + id);
|
||||
scoreboardAction.set(DELETE_SCOREBOARD[id], 1); //1 to remove
|
||||
|
||||
DISPLAY_SIDEBAR[id] = Reflection.newInstance(scoreboardDisplayObjective);
|
||||
scoreboardDisplayName.set(DISPLAY_SIDEBAR[id], SIDEBAR + id);
|
||||
scoreboardDisplaySlot.set(DISPLAY_SIDEBAR[id], 1); // 1 = Sidebar
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
|
||||
toggle ^= 1; // Toggle between 0 and 1
|
||||
|
||||
for(Map.Entry<Player, ScoreboardCallback> scoreboard : playerBoards.entrySet()) {
|
||||
Player player = scoreboard.getKey();
|
||||
ScoreboardCallback callback = scoreboard.getValue();
|
||||
|
||||
TinyProtocol.instance.sendPacket(player, DELETE_SCOREBOARD[toggle]);
|
||||
TinyProtocol.instance.sendPacket(player, createSidebarPacket(callback.getTitle()));
|
||||
for(Map.Entry<String, Integer> score : callback.getData().entrySet()){
|
||||
TinyProtocol.instance.sendPacket(player, createScorePacket(score.getKey(), score.getValue()));
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
|
||||
if(!player.isOnline())
|
||||
return;
|
||||
TinyProtocol.instance.sendPacket(player, DISPLAY_SIDEBAR[toggle]);
|
||||
}, 2);
|
||||
}
|
||||
}, 10, 5);
|
||||
}
|
||||
|
||||
public boolean createScoreboard(Player player, ScoreboardCallback callback) {
|
||||
playerBoards.put(player, callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeScoreboard(Player player) {
|
||||
if(playerBoards.remove(player) == null || !player.isOnline())
|
||||
return;
|
||||
|
||||
TinyProtocol.instance.sendPacket(player, DELETE_SCOREBOARD[toggle]);
|
||||
}
|
||||
|
||||
private static Object createSidebarPacket(String name){
|
||||
Object packet = Reflection.newInstance(FlatteningWrapper.scoreboardObjective);
|
||||
scoreboardName.set(packet, SIDEBAR + toggle);
|
||||
scoreboardAction.set(packet, 0); //0 to create
|
||||
FlatteningWrapper.impl.setScoreboardTitle(packet, name);
|
||||
scoreboardDisplayType.set(packet, displayTypeIntegers);
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static Object createScorePacket(String name, int value){
|
||||
Object packet = Reflection.newInstance(FlatteningWrapper.scoreboardScore);
|
||||
scoreName.set(packet, name);
|
||||
scoreScoreboardName.set(packet, SIDEBAR + toggle);
|
||||
scoreValue.set(packet, value);
|
||||
FlatteningWrapper.impl.setScoreAction(packet);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +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.techhider;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class BlockIds8 implements BlockIds {
|
||||
@Override
|
||||
public int getCombinedId(Object iBlockData) {
|
||||
int id = (int) getCombinedId.invoke(null, iBlockData); // blockState << 12 | blockId
|
||||
return (id & 4095) | (id >> 12);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public int materialToId(Material material) {
|
||||
return material.getId() << 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> materialToAllIds(Material material) {
|
||||
return Collections.singleton(materialToId(material));
|
||||
}
|
||||
}
|
||||
@@ -1,39 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ChunkHider8 implements ChunkHider {
|
||||
|
||||
protected static final Class<?> mapChunkPacket = Reflection.getClass("net.minecraft.PacketPlayOutMapChunk");
|
||||
@Override
|
||||
public Class<?> mapChunkPacket() {
|
||||
return mapChunkPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (player, packet) -> packet;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ProtocolWrapper8 implements ProtocolWrapper {
|
||||
private static final Class<?> chunkCoordinateIntPair = Reflection.getClass("net.minecraft.ChunkCoordIntPair");
|
||||
private static final Reflection.Field<?> multiBlockChangeChunk = Reflection.getField(TechHider.multiBlockChangePacket, chunkCoordinateIntPair, 0);
|
||||
private static final Reflection.Field<Integer> chunkCoordinateX = Reflection.getField(chunkCoordinateIntPair, int.class, 0);
|
||||
private static final Reflection.Field<Integer> chunkCoordinateZ = Reflection.getField(chunkCoordinateIntPair, int.class, 1);
|
||||
private static final Class<?> multiBlockChangeInfo = Reflection.getClass("net.minecraft.PacketPlayOutMultiBlockChange$MultiBlockChangeInfo");
|
||||
private static final Reflection.Constructor multiBlockChangeInfoConstructor = Reflection.getConstructor(multiBlockChangeInfo, TechHider.multiBlockChangePacket, short.class, TechHider.iBlockData);
|
||||
private static final Reflection.Field<?> multiBlockChangeInfoBlock = Reflection.getField(multiBlockChangeInfo, TechHider.iBlockData, 0);
|
||||
private static final Reflection.Field<?> multiBlockChangeInfoPos = Reflection.getField(multiBlockChangeInfo, short.class, 0);
|
||||
private static final Class<?> multiBlockChangeInfoArray = Reflection.getClass("[L" + Reflection.LEGACY_NET_MINECRAFT_SERVER + ".PacketPlayOutMultiBlockChange$MultiBlockChangeInfo;");
|
||||
private static final Reflection.Field<?> multiBlockChangeInfos = Reflection.getField(TechHider.multiBlockChangePacket, multiBlockChangeInfoArray, 0);
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
|
||||
Object chunkCoords = multiBlockChangeChunk.get(packet);
|
||||
int chunkX = chunkCoordinateX.get(chunkCoords);
|
||||
int chunkZ = chunkCoordinateZ.get(chunkCoords);
|
||||
if(locationEvaluator.skipChunk(p, chunkX, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = TechHider.multiBlockChangeCloner.apply(packet);
|
||||
Object[] mbcis = (Object[]) multiBlockChangeInfos.get(packet);
|
||||
ArrayList<Object> blockChangeInfos = new ArrayList<>(mbcis.length);
|
||||
for(Object mbci : mbcis) {
|
||||
short pos = (short) multiBlockChangeInfoPos.get(mbci);
|
||||
switch(locationEvaluator.check(p, 16*chunkX + (pos >> 12 & 0xF), pos & 0xFF, 16*chunkZ + (pos >> 8 & 0xF))) {
|
||||
case SKIP:
|
||||
blockChangeInfos.add(mbci);
|
||||
break;
|
||||
case CHECK:
|
||||
blockChangeInfos.add(techHider.iBlockDataHidden(multiBlockChangeInfoBlock.get(mbci)) ? multiBlockChangeInfoConstructor.invoke(packet, pos, techHider.getObfuscationTarget()) : mbci);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(blockChangeInfos.isEmpty())
|
||||
return null;
|
||||
|
||||
multiBlockChangeInfos.set(packet, blockChangeInfos.toArray((Object[])Array.newInstance(multiBlockChangeInfo, 0)));
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
private static final Reflection.Field<Integer> tileEntityDataAction = Reflection.getField(TechHider.tileEntityDataPacket, int.class, 0);
|
||||
@Override
|
||||
public boolean unfilteredTileEntityDataAction(Object packet) {
|
||||
return tileEntityDataAction.get(packet) != 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_8", "default"))
|
||||
|
||||
compileOnly(libs.nms9)
|
||||
compileOnly(libs.worldedit12)
|
||||
}
|
||||
@@ -1,110 +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 de.steamwar.Reflection;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BountifulWrapper9 implements BountifulWrapper.IBountifulWrapper {
|
||||
|
||||
@Override
|
||||
public void playPling(Player player) {
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) {
|
||||
if(type == ChatMessageType.CHAT)
|
||||
type = ChatMessageType.SYSTEM;
|
||||
|
||||
player.spigot().sendMessage(type, msg);
|
||||
}
|
||||
|
||||
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);
|
||||
@Override
|
||||
public Object getDataWatcherObject(int index, Class<?> type) {
|
||||
return dataWatcherObjectConstructor.invoke(index, Reflection.getField(dataWatcherRegistry, dataWatcherSerializer, 0, type).get(null));
|
||||
}
|
||||
|
||||
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);
|
||||
@Override
|
||||
public Object getDataWatcherItem(Object dwo, Object value) {
|
||||
return itemConstructor.invoke(dwo, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BountifulWrapper.PositionSetter getPositionSetter(Class<?> packetClass, int fieldOffset) {
|
||||
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));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
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));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BountifulWrapper.UUIDSetter getUUIDSetter(Class<?> packetClass) {
|
||||
Reflection.Field<UUID> uuidField = Reflection.getField(packetClass, UUID.class, 0);
|
||||
|
||||
return uuidField::set;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +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 de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CraftbukkitWrapper9 implements CraftbukkitWrapper.ICraftbukkitWrapper {
|
||||
|
||||
private static final Class<?> chunk = Reflection.getClass("net.minecraft.world.level.chunk.LevelChunk");
|
||||
private static final Class<?> packetPlayOutMapChunk = Reflection.getClass("net.minecraft.network.protocol.game.PacketPlayOutMapChunk");
|
||||
private static final Reflection.Constructor newPacketPlayOutMapChunk = Reflection.getConstructor(packetPlayOutMapChunk, chunk, int.class);
|
||||
private static final Reflection.Method getHandle = Reflection.getMethod("org.bukkit.craftbukkit.CraftChunk", "getHandle");
|
||||
|
||||
@Override
|
||||
public void sendChunk(Player p, int chunkX, int chunkZ) {
|
||||
TinyProtocol.instance.sendPacket(p, newPacketPlayOutMapChunk.invoke(getHandle.invoke(p.getWorld().getChunkAt(chunkX, chunkZ)), 65535));
|
||||
}
|
||||
}
|
||||
@@ -1,29 +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 org.bukkit.Particle;
|
||||
|
||||
public class TrickyParticleWrapper9 implements TrickyParticleWrapper {
|
||||
@Override
|
||||
public Particle getVillagerHappy() {
|
||||
return Particle.VILLAGER_HAPPY;
|
||||
}
|
||||
}
|
||||
@@ -1,158 +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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ChunkHider9 extends ChunkHider8 {
|
||||
|
||||
private static final UnaryOperator<Object> mapChunkCloner = ProtocolUtils.shallowCloneGenerator(mapChunkPacket);
|
||||
|
||||
private static final Reflection.Field<Integer> mapChunkX = Reflection.getField(mapChunkPacket, int.class, 0);
|
||||
private static final Reflection.Field<Integer> mapChunkZ = Reflection.getField(mapChunkPacket, int.class, 1);
|
||||
private static final Reflection.Field<Integer> mapChunkBitMask = Reflection.getField(mapChunkPacket, int.class, 2);
|
||||
private static final Reflection.Field<List> mapChunkBlockEntities = Reflection.getField(mapChunkPacket, List.class, 0);
|
||||
private static final Reflection.Field<byte[]> mapChunkData = Reflection.getField(mapChunkPacket, byte[].class, 0);
|
||||
|
||||
private static final Class<?> nbtTagCompound = Reflection.getClass("net.minecraft.nbt.CompoundTag");
|
||||
private static final Reflection.Method nbtTagGetString = Reflection.getTypedMethod(nbtTagCompound, null, String.class, String.class);
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
int chunkX = mapChunkX.get(packet);
|
||||
int chunkZ = mapChunkZ.get(packet);
|
||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = mapChunkCloner.apply(packet);
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
mapChunkBlockEntities.set(packet, ((List<?>)mapChunkBlockEntities.get(packet)).stream().filter(
|
||||
nbttag -> !hiddenBlockEntities.contains((String) nbtTagGetString.invoke(nbttag, "id"))
|
||||
).collect(Collectors.toList()));
|
||||
|
||||
int primaryBitMask = mapChunkBitMask.get(packet);
|
||||
ByteBuf in = Unpooled.wrappedBuffer(mapChunkData.get(packet));
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
for(int chunkY = 0; chunkY < p.getWorld().getMaxHeight()/16; chunkY++) {
|
||||
if(((1 << chunkY) & primaryBitMask) == 0)
|
||||
continue;
|
||||
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, chunkY, chunkZ);
|
||||
dataHider(section);
|
||||
}
|
||||
byte[] data = new byte[out.readableBytes()];
|
||||
out.readBytes(data);
|
||||
mapChunkData.set(packet, data);
|
||||
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
protected void dataHider(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
section.processPalette();
|
||||
|
||||
if(section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) { //section.getBitsPerBlock() < 9
|
||||
section.skipDataArray();
|
||||
} else {
|
||||
processDataArray(section);
|
||||
}
|
||||
|
||||
section.getOut().writeBytes(section.getIn(), 4096); //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
|
||||
}
|
||||
|
||||
protected void processDataArray(SectionHider section) {
|
||||
VariableValueArray values = new VariableValueArray(section.getBitsPerBlock(), section.readDataArray());
|
||||
|
||||
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;
|
||||
|
||||
switch (section.test(x, y, z)) {
|
||||
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.backing);
|
||||
}
|
||||
|
||||
private static class VariableValueArray {
|
||||
private final long[] backing;
|
||||
private final int bitsPerValue;
|
||||
private final long valueMask;
|
||||
|
||||
public VariableValueArray(int bitsPerEntry, long[] dataArray) {
|
||||
this.bitsPerValue = bitsPerEntry;
|
||||
this.valueMask = (1L << this.bitsPerValue) - 1;
|
||||
this.backing = dataArray;
|
||||
}
|
||||
|
||||
public int get(int index) {
|
||||
index *= bitsPerValue;
|
||||
int i0 = index >> 6;
|
||||
int i1 = index & 0x3f;
|
||||
|
||||
long value = backing[i0] >>> i1;
|
||||
|
||||
// The value is divided over two long values
|
||||
if (i1 + bitsPerValue > 64)
|
||||
value |= backing[++i0] << 64 - i1;
|
||||
|
||||
return (int) (value & valueMask);
|
||||
}
|
||||
|
||||
public void set(int index, int value) {
|
||||
index *= bitsPerValue;
|
||||
int i0 = index >> 6;
|
||||
int i1 = index & 0x3f;
|
||||
|
||||
backing[i0] = backing[i0] & ~(valueMask << i1) | (value & valueMask) << i1;
|
||||
int i2 = i1 + bitsPerValue;
|
||||
// The value is divided over two long values
|
||||
if (i2 > 64) {
|
||||
i0++;
|
||||
backing[i0] = backing[i0] & -(1L << i2 - 64) | value >> 64 - i1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
+2
-15
@@ -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
|
||||
@@ -24,7 +24,7 @@ import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class WorldEditRendererWrapper9 implements WorldEditRendererWrapper {
|
||||
public class WorldEditRendererFallback {
|
||||
|
||||
private static final int VIEW_DISTANCE = 64;
|
||||
private static final int SQ_VIEW_DISTANCE = VIEW_DISTANCE * VIEW_DISTANCE;
|
||||
@@ -33,7 +33,6 @@ public class WorldEditRendererWrapper9 implements WorldEditRendererWrapper {
|
||||
private static final Vector ONES = new Vector(1, 1, 1);
|
||||
private static final Vector STEPS = new Vector(STEP_SIZE, STEP_SIZE, STEP_SIZE);
|
||||
|
||||
@Override
|
||||
public void draw(Player player, boolean scheduled, boolean clipboard, Vector min, Vector max) {
|
||||
if (!scheduled) return;
|
||||
|
||||
@@ -77,16 +76,4 @@ public class WorldEditRendererWrapper9 implements WorldEditRendererWrapper {
|
||||
min.add(stepSize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(Player player, boolean clipboard, boolean hide) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Player player) {
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,20 +30,4 @@ dependencies {
|
||||
api(project(":CommonCore"))
|
||||
api(project(":CommandFramework"))
|
||||
api(project(":SpigotCore:SpigotCore_Main"))
|
||||
|
||||
implementation(project(":SpigotCore:SpigotCore_8"))
|
||||
implementation(project(":SpigotCore:SpigotCore_9"))
|
||||
implementation(project(":SpigotCore:SpigotCore_10"))
|
||||
implementation(project(":SpigotCore:SpigotCore_12"))
|
||||
implementation(project(":SpigotCore:SpigotCore_14"))
|
||||
implementation(project(":SpigotCore:SpigotCore_15"))
|
||||
implementation(project(":SpigotCore:SpigotCore_18"))
|
||||
implementation(project(":SpigotCore:SpigotCore_19"))
|
||||
implementation(project(":SpigotCore:SpigotCore_20"))
|
||||
implementation(project(":SpigotCore:SpigotCore_21")) {
|
||||
attributes {
|
||||
// Very Hacky, but it works
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user