Compare commits

...

25 Commits

Author SHA1 Message Date
YoyoNow b2b803aca6 Remove unused code from Laufbau
Pull Request Build / Build (pull_request) Successful in 1m28s
2026-06-12 12:24:46 +02:00
YoyoNow 701964c2f2 Fix DevCommand.kt
Deploy / Build (push) Successful in 2m56s
Deploy / Deploy (push) Successful in 11s
2026-06-12 12:15:07 +02:00
YoyoNow 6cbfc94e6d Merge pull request 'Access widener for paper' (#420) from AccessWidener into main
Deploy / Build (push) Successful in 2m53s
Deploy / Deploy (push) Successful in 12s
Reviewed-on: #420
Reviewed-by: Chaoscaot <max@chaoscaot.de>
2026-06-12 11:16:33 +02:00
YoyoNow c0ff123279 Fix EntityDamage only applying cancel for Player
Deploy / Build (push) Successful in 2m34s
Deploy / Deploy (push) Successful in 11s
2026-06-12 11:09:13 +02:00
YoyoNow 5511a1f08e Fix steamwar.devserver.gradle
Pull Request Build / Build (pull_request) Successful in 2m1s
Backport CommonCore / Create CommonCore backport PRs (pull_request) Successful in 8s
2026-06-12 10:41:18 +02:00
YoyoNow 8c8da355bb Fix build.yml
Pull Request Build / Build (pull_request) Successful in 2m3s
2026-06-12 10:02:34 +02:00
Chaoscaot 7326ed4aa0 Merge pull request 'Remove some deprecated code in favor of newer code' (#421) from RemoveDeprecatedCode into main
Deploy / Build (push) Successful in 2m0s
Deploy / Deploy (push) Successful in 11s
Reviewed-on: #421
Reviewed-by: Chaoscaot <max@chaoscaot.de>
2026-06-12 09:58:05 +02:00
YoyoNow 2d59eb81c7 Fix ColorInit and CustomMap deprecation warnings
Pull Request Build / Build (pull_request) Successful in 2m1s
2026-06-12 09:49:32 +02:00
YoyoNow 711920464a Remove some deprecated code in favor of newer code
Pull Request Build / Build (pull_request) Successful in 1m14s
Backport CommonCore / Create CommonCore backport PRs (pull_request) Successful in 8s
2026-06-12 09:37:43 +02:00
YoyoNow 117dbd08ae Implement startup arguments into steamwar.devserver.gradle
Pull Request Build / Build (pull_request) Successful in 2m2s
2026-06-11 23:54:42 +02:00
YoyoNow b36464e69e Implement Velocity changes
Pull Request Build / Build (pull_request) Successful in 2m3s
2026-06-11 23:50:34 +02:00
YoyoNow f5ac006c0c Fix REntity.EntityDataPacketBuilder 2026-06-11 23:49:38 +02:00
YoyoNow 414bfbfe3c Fix ClassTransformer public constructor 2026-06-11 23:48:33 +02:00
YoyoNow c362a3e1f0 Remove unused code
Pull Request Build / Build (pull_request) Successful in 2m2s
2026-06-11 23:24:11 +02:00
YoyoNow 2b43af8851 Remove unneded reflection
Pull Request Build / Build (pull_request) Successful in 2m2s
2026-06-11 23:22:05 +02:00
YoyoNow 1590f8f0ee Remove Reflection
Pull Request Build / Build (pull_request) Successful in 2m4s
2026-06-11 23:18:22 +02:00
YoyoNow 932732737d Unreflect more stuff
Pull Request Build / Build (pull_request) Successful in 2m4s
2026-06-11 22:35:13 +02:00
YoyoNow 2bc164c1b0 Extract widener definition into a widener.gradle.kts plugin
Pull Request Build / Build (pull_request) Successful in 2m2s
2026-06-11 20:38:33 +02:00
YoyoNow aa66b3dc83 Optimize imports
Pull Request Build / Build (pull_request) Successful in 1m24s
2026-06-11 18:29:44 +02:00
YoyoNow f5d9c6e175 Unreflect everything
Pull Request Build / Build (pull_request) Successful in 1m23s
2026-06-11 18:26:15 +02:00
YoyoNow 36b31fac77 Remove unneeded code
Pull Request Build / Build (pull_request) Successful in 1m21s
Cleanup build.gradle.kts
2026-06-11 13:49:35 +02:00
YoyoNow 641cefad01 Add comments to bausystem.accesswidener
Pull Request Build / Build (pull_request) Successful in 1m22s
2026-06-11 13:46:55 +02:00
YoyoNow eb866125ea Remove reflection from BauSystem 2026-06-11 13:45:49 +02:00
YoyoNow 961331f029 Fix Agent and WideningTransformer and ClassPatcher 2026-06-11 13:19:04 +02:00
YoyoNow 786257ad0e Add initial AccessWidener 2026-06-11 12:22:44 +02:00
107 changed files with 1361 additions and 3103 deletions
+1
View File
@@ -51,6 +51,7 @@ jobs:
rm -rf deploy
mkdir -p deploy
cp "AccessWidener/build/libs/AccessWidener-all.jar" "deploy/AccessWidener.jar"
cp "BauSystem/build/libs/BauSystem-all.jar" "deploy/BauSystem.jar"
cp "FightSystem/build/libs/FightSystem-all.jar" "deploy/FightSystem.jar"
cp "KotlinCore/build/libs/KotlinCore-all.jar" "deploy/KotlinCore.jar"
@@ -17,18 +17,29 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
plugins {
`java-library`
alias(libs.plugins.shadow)
}
import lombok.experimental.UtilityClass;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.contents.PlainTextContents;
dependencies {
implementation("org.ow2.asm:asm:9.7")
implementation("org.ow2.asm:asm-commons:9.7")
}
import java.util.Optional;
@UtilityClass
public class FlatteningWrapper {
public Object formatDisplayName(String displayName) {
return displayName != null ? Optional.of((Object) MutableComponent.create(PlainTextContents.create(displayName))) : Optional.empty();
tasks.shadowJar {
manifest {
attributes(
"Manifest-Version" to "1.0",
"Build-Jdk-Spec" to "21",
"Main-Class" to "de.steamwar.Main",
"Premain-Class" to "de.steamwar.Agent",
"Can-Retransform-Classes" to "true",
"Can-Redefine-Classes" to "true",
)
}
}
tasks.build {
dependsOn(tasks.shadowJar)
}
@@ -0,0 +1,49 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
/**
* A single parsed line from a .accesswidener file.
* <p>
* Examples:
* accessible class net/minecraft/server/level/ServerPlayer
* accessible method net/minecraft/server/level/ServerPlayer getStats ()V
* mutable field net/minecraft/world/entity/Entity id I
* extendable class net/minecraft/world/level/chunk/LevelChunk
*/
public record AccessWidenerEntry(
/** accessible | mutable | extendable (may have "transitive-" prefix) */
String directive,
/** class | method | field */
String memberType,
/** Internal class name, e.g. net/minecraft/server/level/ServerPlayer */
String target,
/** Method/field name, null for class entries */
String name,
/** Descriptor, null for class entries */
String descriptor) {
/**
* Returns true if this entry targets the class with the given internal name.
*/
public boolean targets(String internalName) {
return target.equals(internalName);
}
}
@@ -0,0 +1,104 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* Parses Fabric-compatible .accesswidener files.
* <p>
* Supported format:
* <pre>
* accessWidener v2 named
*
* # comments are supported
* accessible class net/minecraft/Foo
* accessible method net/minecraft/Foo someMethod ()V
* accessible field net/minecraft/Foo someField I
* mutable field net/minecraft/Foo someField I
* extendable class net/minecraft/Foo
* extendable method net/minecraft/Foo someMethod ()V
*
* # transitive variants (expose widening to dependents)
* transitive-accessible class net/minecraft/Foo
* </pre>
*/
public final class AccessWidenerParser {
private AccessWidenerParser() {
}
public static List<AccessWidenerEntry> parse(InputStream in) throws IOException {
List<AccessWidenerEntry> entries = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
String line;
boolean headerSeen = false;
while ((line = reader.readLine()) != null) {
// Strip inline comments
int commentIdx = line.indexOf('#');
if (commentIdx >= 0) line = line.substring(0, commentIdx);
line = line.strip();
if (line.isEmpty()) continue;
if (!headerSeen) {
// First non-blank, non-comment line must be the header
if (!line.startsWith("accessWidener")) {
throw new IOException("Missing accessWidener header, got: " + line);
}
headerSeen = true;
continue;
}
AccessWidenerEntry entry = parseLine(line);
if (entry != null) entries.add(entry);
}
}
return entries;
}
private static AccessWidenerEntry parseLine(String line) {
String[] parts = line.split("\\s+");
if (parts.length < 3) return null;
String directive = parts[0]; // accessible / mutable / extendable / transitive-*
String memberType = parts[1]; // class / method / field
String target = parts[2]; // internal class name
return switch (memberType) {
case "class" -> new AccessWidenerEntry(directive, "class", target, null, null);
case "method", "field" -> {
if (parts.length < 5) yield null;
yield new AccessWidenerEntry(directive, memberType, target, parts[3], parts[4]);
}
default -> null;
};
}
}
@@ -0,0 +1,75 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
import java.io.File;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* Java agent entry point.
* <p>
* At JVM startup: java -javaagent:paper-access-widener-agent.jar -jar server.jar
* <p>
* On attach the agent:
* <ol>
* <li>Find all .jar files inside the plugins folder</li>
* <li>Scan all found jars for *.accesswidener resources</li>
* <li>Transform any class during loading</li>
* </ol>
*/
public class Agent {
private Agent() {
throw new IllegalStateException("Utility class");
}
private static final Logger LOG = Logger.getLogger("AccessWidenerAgent");
// -javaagent: startup
public static void premain(String args, Instrumentation inst) {
init(inst);
}
private static void init(Instrumentation inst) {
LOG.info("[AccessWidener] Agent initialising.");
List<AccessWidenerEntry> entries = new ArrayList<>();
File file = new File(new File(".").getAbsoluteFile(), "plugins/");
File[] files = file.listFiles();
if (files == null) files = new File[0];
for (File jarFile : files) {
if (!jarFile.isFile()) continue;
if (!jarFile.getName().endsWith(".jar")) continue;
try {
entries.addAll(Utils.findAndParseAccessWideners(jarFile.toPath()));
} catch (IOException e) {
LOG.warning("Failed to parse access wideners from " + jarFile.getAbsolutePath());
}
}
LOG.info("[AccessWidener] Loaded " + entries.size() + " access wideners.");
inst.addTransformer(new WideningTransformer(entries), false);
LOG.info("[AccessWidener] Agent ready.");
}
}
@@ -0,0 +1,83 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Uses ASM to patch class bytecode according to a list of access widener entries.
*
* Returns {@code null} if the class is not targeted by any entry (no-op signal
* to the caller so it can skip the write).
*/
public class ClassPatcher {
private static final Logger LOG = Logger.getLogger("ClassPatcher");
private final List<AccessWidenerEntry> entries;
/** Pre-computed set of targeted internal names for fast filtering. */
private final Set<String> targets;
private final Set<String> targetsPublicConstructor;
public ClassPatcher(List<AccessWidenerEntry> entries) {
this.entries = entries;
this.targets = entries.stream()
.map(AccessWidenerEntry::target)
.flatMap(s -> {
if (!s.contains("$")) return Stream.of(s);
int index = s.lastIndexOf('$');
return Stream.of(s, s.substring(0, index));
})
.collect(Collectors.toSet());
this.targetsPublicConstructor = entries.stream()
.filter(entry -> entry.directive().equals("transitive-extendable"))
.map(AccessWidenerEntry::target)
.collect(Collectors.toSet());
}
/**
* Patches {@code classBytes} if {@code className} is targeted.
*
* @return patched bytes, or {@code null} if no changes were needed
*/
public byte[] patch(String className, byte[] classBytes) {
if (!targets.contains(className)) return null;
try {
ClassReader cr = new ClassReader(classBytes);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new ClassTransformer(cw, className, entries, targetsPublicConstructor.contains(className)), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return cw.toByteArray();
} catch (Exception e) {
LOG.warning("[AccessWidener] Failed to transform " + className + ": " + e.getMessage());
return null;
}
}
}
@@ -0,0 +1,125 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.List;
public class ClassTransformer extends ClassVisitor {
private final String internalName;
private final List<AccessWidenerEntry> entries;
private final boolean appendPublicConstructor;
public ClassTransformer(ClassVisitor cv, String internalName, List<AccessWidenerEntry> entries, boolean appendPublicConstructor) {
super(Opcodes.ASM9, cv);
this.internalName = internalName;
this.entries = entries;
this.appendPublicConstructor = appendPublicConstructor;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
int newAccess = access;
for (AccessWidenerEntry e : entries) {
if (!e.targets(internalName) || !"class".equals(e.memberType())) continue;
newAccess = applyDirective(e.directive(), newAccess, false);
}
if (appendPublicConstructor) {
MethodVisitor methodVisitor = visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitMethodInsn(
Opcodes.INVOKESPECIAL,
"java/lang/Object",
"<init>",
"()V",
false
);
methodVisitor.visitInsn(Opcodes.RETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
}
super.visit(version, newAccess, name, signature, superName, interfaces);
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
int newAccess = access;
for (AccessWidenerEntry e : entries) {
if (!e.target().equals(name) || !"class".equals(e.memberType())) continue;
newAccess = applyDirective(e.directive(), newAccess, false);
}
super.visitInnerClass(name, outerName, innerName, newAccess);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
int newAccess = access;
for (AccessWidenerEntry e : entries) {
if (!e.targets(internalName) || !"method".equals(e.memberType())) continue;
if (!name.equals(e.name()) || !descriptor.equals(e.descriptor())) continue;
newAccess = applyDirective(e.directive(), newAccess, false);
}
return super.visitMethod(newAccess, name, descriptor, signature, exceptions);
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
int newAccess = access;
for (AccessWidenerEntry e : entries) {
if (!e.targets(internalName) || !"field".equals(e.memberType())) continue;
if (!name.equals(e.name())) continue;
newAccess = applyDirective(e.directive(), newAccess, true);
}
return super.visitField(newAccess, name, descriptor, signature, value);
}
/**
* Apply a directive to an access bitmask.
*
* @param directive accessible / mutable / extendable (with optional "transitive-" prefix)
* @param access current access flags
* @param isField true when processing a field (mutable removes final)
*/
private static int applyDirective(String directive, int access, boolean isField) {
// Strip transitive- prefix — the widening itself is the same
String effective = directive.startsWith("transitive-") ? directive.substring("transitive-".length()) : directive;
return switch (effective) {
case "accessible" -> makePublic(access);
case "extendable" -> makePublic(removeFinal(access));
case "mutable" -> isField ? removeFinal(access) : access;
default -> access;
};
}
private static int makePublic(int access) {
return (access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) | Opcodes.ACC_PUBLIC;
}
private static int removeFinal(int access) {
return access & ~Opcodes.ACC_FINAL;
}
}
@@ -0,0 +1,125 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
/**
* Command-line tool that produces a widened copy of a JAR for use as a
* compile-time stub in IntelliJ / Gradle.
*
* Usage:
* java -jar jar-widener.jar <input.jar> <output.jar> [file.accesswidener ...]
*
* The output JAR is identical to the input JAR except that every class
* targeted by the access widener entries has its access flags patched:
* accessible → public
* extendable → public + non-final
* mutable → non-final field
*
* Intended for use as a Gradle task so IntelliJ sees the already-widened
* class when you Ctrl+click NMS code, and javac compiles without complaints.
*/
public class Main {
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.err.println("Usage: jar-widener <input.jar> <output.jar> [*.accesswidener ...]");
System.exit(1);
}
Path inputJar = Path.of(args[0]);
Path outputJar = Path.of(args[1]);
if (!Files.exists(inputJar)) {
System.err.println("Input JAR not found: " + inputJar);
System.exit(1);
}
// --- Collect all access widener entries ---
List<AccessWidenerEntry> entries = new ArrayList<>();
if (args.length > 2) {
for (int i = 2; i < args.length; i++) {
Path awFile = Path.of(args[i]);
if (!Files.exists(awFile)) {
System.err.println("Warning: access widener file not found, skipping: " + awFile);
continue;
}
try (InputStream in = Files.newInputStream(awFile)) {
List<AccessWidenerEntry> parsed = AccessWidenerParser.parse(in);
System.out.println("Loaded " + parsed.size() + " entries from " + awFile.getFileName());
entries.addAll(parsed);
}
}
}
if (entries.isEmpty()) {
System.out.println("No access widener entries found — copying JAR unchanged.");
Files.createDirectories(outputJar.getParent());
Files.copy(inputJar, outputJar, StandardCopyOption.REPLACE_EXISTING);
return;
}
System.out.println("Widening " + inputJar.getFileName()
+ " with " + entries.size() + " total entr"
+ (entries.size() == 1 ? "y" : "ies") + "...");
// --- Copy input → output, transforming .class files in place ---
Files.createDirectories(outputJar.getParent());
Files.copy(inputJar, outputJar, StandardCopyOption.REPLACE_EXISTING);
ClassPatcher patcher = new ClassPatcher(entries);
try (FileSystem fs = FileSystems.newFileSystem(outputJar)) {
// Walk every .class entry in the JAR
try (var stream = Files.walk(fs.getPath("/"))) {
stream.filter(p -> p.toString().endsWith(".class"))
.forEach(classPath -> patchClass(fs, classPath, patcher));
}
}
System.out.println("Done. Widened JAR written to " + outputJar);
}
private static void patchClass(FileSystem fs, Path classPath, ClassPatcher patcher) {
// Derive internal class name from path e.g. /net/minecraft/Foo.class → net/minecraft/Foo
String internalName = classPath.toString()
.replaceFirst("^/", "")
.replace(".class", "");
try {
byte[] original = Files.readAllBytes(classPath);
byte[] patched = patcher.patch(internalName, original);
if (patched != null) {
Files.write(classPath, patched);
System.out.println(" Widened: " + internalName);
}
} catch (IOException e) {
System.err.println(" Warning: failed to patch " + internalName + ": " + e.getMessage());
}
}
}
@@ -0,0 +1,60 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class Utils {
private static final Logger LOG = Logger.getLogger("AccessWidenerAgent");
private Utils() {
throw new IllegalStateException("Utility class");
}
public static List<AccessWidenerEntry> findAndParseAccessWideners(Path jarPath) throws IOException {
List<AccessWidenerEntry> results = new ArrayList<>();
try (ZipFile zip = new ZipFile(jarPath.toFile())) {
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (entry.isDirectory() || !entry.getName().endsWith(".accesswidener")) continue;
try (InputStream in = zip.getInputStream(entry)) {
results.addAll(AccessWidenerParser.parse(in));
} catch (IOException e) {
LOG.warning("[AccessWidener] Failed to parse " + entry.getName()
+ " in " + jarPath.getFileName() + ": " + e.getMessage());
}
}
}
return results;
}
}
@@ -0,0 +1,44 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar;
import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;
import java.util.List;
/**
* Transforms class bytecode to apply access widening rules.
* <p>
* Also monitors for new plugin ClassLoaders appearing (when plugins load after
* the agent attaches) and automatically picks up their .accesswidener files.
*/
public class WideningTransformer implements ClassFileTransformer {
private final ClassPatcher patcher;
public WideningTransformer(List<AccessWidenerEntry> entries) {
patcher = new ClassPatcher(entries);
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
return patcher.patch(className, classfileBuffer);
}
}
@@ -19,6 +19,7 @@
plugins {
steamwar.java
widener
}
tasks.compileJava {
@@ -47,3 +48,7 @@ dependencies {
implementation(libs.luaj)
implementation(files("$projectDir/../libs/YAPION-SNAPSHOT.jar"))
}
widener {
fromCatalog(libs.nms)
}
@@ -0,0 +1,13 @@
accessWidener v2 named
# For NoClipCommand
accessible field net/minecraft/server/level/ServerPlayerGameMode gameModeForPlayer Lnet/minecraft/world/level/GameType;
# For PlaceItemUtils
accessible field org/bukkit/craftbukkit/block/CraftBlockState position Lnet/minecraft/core/BlockPos;
mutable field org/bukkit/craftbukkit/block/CraftBlockState position Lnet/minecraft/core/BlockPos;
accessible field org/bukkit/craftbukkit/block/CraftBlockState world Lorg/bukkit/craftbukkit/CraftWorld;
mutable field org/bukkit/craftbukkit/block/CraftBlockState world Lorg/bukkit/craftbukkit/CraftWorld;
# For TickManager
accessible field net/minecraft/server/ServerTickRateManager remainingSprintTicks J
@@ -25,7 +25,6 @@ import de.steamwar.bausystem.configplayer.ConfigConverter;
import de.steamwar.bausystem.features.gui.BauGUI;
import de.steamwar.bausystem.features.script.lua.SteamWarLuaPlugin;
import de.steamwar.bausystem.features.script.lua.libs.LuaLib;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.panzern.Panzern;
import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm;
import de.steamwar.bausystem.features.tracer.TraceManager;
@@ -112,9 +111,6 @@ public class BauSystem extends JavaPlugin implements Listener {
if (any instanceof ConfigConverter) {
Config.addConfigConverter((ConfigConverter) any);
}
if (any instanceof BoundingBoxLoader) {
((BoundingBoxLoader) any).load();
}
}
};
try {
@@ -55,19 +55,11 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -32,7 +32,6 @@ import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
@Linked
@@ -19,28 +19,17 @@
package de.steamwar.bausystem.features.slaves.laufbau;
import com.sk89q.worldedit.blocks.SkullBlock;
import com.sk89q.worldedit.world.block.BaseBlock;
import de.steamwar.inventory.SWItem;
import lombok.Getter;
import lombok.ToString;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@ToString
@Getter
public class BlockBoundingBox {
@@ -92,197 +81,4 @@ public class BlockBoundingBox {
public double volume() {
return volume;
}
static {
addPixel(Material.AIR.createBlockData(), 0, 0, 0, 0, 0, 0, null);
// addPixel(Material.COBWEB.createBlockData(), 0, 0, 0, 0, 0, 0, createItem("LAUFBAU_BLOCK_COBWEB", Material.COBWEB));
addPixel(Material.END_STONE.createBlockData(), 0, 0, 0, 16, 16, 16, null);
addPixel(Material.DIRT_PATH.createBlockData(), 0, 0, 0, 16, 15, 16, createItem("LAUFBAU_BLOCK_GRASS_PATH", Material.DIRT_PATH));
addPixel(Material.MUD.createBlockData(), 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SOUL_SAND", Material.SOUL_SAND));
Cocoa cocoaNorth = (Cocoa) Material.COCOA.createBlockData();
cocoaNorth.setAge(2);
cocoaNorth.setFacing(BlockFace.NORTH);
addPixel(cocoaNorth, 4, 3, 1, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_NORTH"));
Cocoa cocoaSouth = (Cocoa) Material.COCOA.createBlockData();
cocoaSouth.setAge(2);
cocoaSouth.setFacing(BlockFace.SOUTH);
addPixel(cocoaSouth, 4, 3, 7, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_SOUTH"));
Cocoa cocoaWest = (Cocoa) Material.COCOA.createBlockData();
cocoaWest.setAge(2);
cocoaWest.setFacing(BlockFace.WEST);
addPixel(cocoaWest, 1, 3, 4, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_WEST"));
Cocoa cocoaEast = (Cocoa) Material.COCOA.createBlockData();
cocoaEast.setAge(2);
cocoaEast.setFacing(BlockFace.EAST);
addPixel(cocoaEast, 7, 3, 4, 8, 9, 8, createItem("LAUFBAU_BLOCK_COCOA", Material.COCOA_BEANS, "LAUFBAU_FACING_EAST"));
TurtleEgg singleTurtleEgg = (TurtleEgg) Material.TURTLE_EGG.createBlockData();
singleTurtleEgg.setEggs(1);
singleTurtleEgg.setHatch(0);
addPixel(singleTurtleEgg, 4, 0, 3, 9, 7, 9, createItem("LAUFBAU_BLOCK_TURTLE_EGG", Material.TURTLE_EGG, "LAUFBAU_COUNT_1"));
TurtleEgg doubleTurtleEgg = (TurtleEgg) Material.TURTLE_EGG.createBlockData();
doubleTurtleEgg.setEggs(2);
doubleTurtleEgg.setHatch(0);
addPixel(doubleTurtleEgg, 1, 0, 1, 14, 7, 14, createItem("LAUFBAU_BLOCK_TURTLE_EGG", Material.TURTLE_EGG, "LAUFBAU_COUNT_2"));
addPixel(Material.CHEST.createBlockData(), 1, 0, 1, 14, 14, 14, createItem("LAUFBAU_BLOCK_CHEST", Material.CHEST));
Snow snowLayers8 = (Snow) Material.SNOW.createBlockData();
snowLayers8.setLayers(8);
addPixel(snowLayers8, 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_8"));
Directional headNorth = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headNorth.setFacing(BlockFace.NORTH);
addPixel(headNorth, 4, 4, 8, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_NORTH"), BlockBoundingBox::randomPlayerHead);
Directional headSouth = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headSouth.setFacing(BlockFace.SOUTH);
addPixel(headSouth, 4, 4, 0, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_SOUTH"), BlockBoundingBox::randomPlayerHead);
Directional headWest = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headWest.setFacing(BlockFace.WEST);
addPixel(headWest, 8, 4, 4, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_WEST"), BlockBoundingBox::randomPlayerHead);
Directional headEast = (Directional) Material.PLAYER_WALL_HEAD.createBlockData();
headEast.setFacing(BlockFace.EAST);
addPixel(headEast, 0, 4, 4, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_WALL_HEAD", Material.PLAYER_HEAD, "LAUFBAU_FACING_EAST"), BlockBoundingBox::randomPlayerHead);
Snow snowLayers7 = (Snow) Material.SNOW.createBlockData();
snowLayers7.setLayers(7);
addPixel(snowLayers7, 0, 0, 0, 16, 12, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_7"));
Snow snowLayers6 = (Snow) Material.SNOW.createBlockData();
snowLayers6.setLayers(6);
addPixel(snowLayers6, 0, 0, 0, 16, 10, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_6"));
addPixel(Material.STONECUTTER.createBlockData(), 0, 0, 0, 16, 9, 16, createItem("LAUFBAU_BLOCK_STONECUTTER", Material.STONECUTTER));
addPixel(Material.PLAYER_HEAD.createBlockData(), 4, 0, 4, 8, 8, 8, createItem("LAUFBAU_BLOCK_PLAYER_HEAD", Material.PLAYER_HEAD), BlockBoundingBox::randomPlayerHead);
addPixel(Material.CAKE.createBlockData(), 1, 0, 1, 14, 8, 14, createItem("LAUFBAU_BLOCK_CAKE", Material.CAKE));
Slab bottomSlab = (Slab) Material.END_STONE_BRICK_SLAB.createBlockData();
bottomSlab.setType(Slab.Type.BOTTOM);
addPixel(bottomSlab, 0, 0, 0, 16, 8, 16, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_SLAB", Material.END_STONE_BRICK_SLAB, "LAUFBAU_TYPE_BOTTOM"));
Slab topSlab = (Slab) Material.END_STONE_BRICK_SLAB.createBlockData();
topSlab.setType(Slab.Type.TOP);
addPixel(topSlab, 0, 8, 0, 16, 8, 16, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_SLAB", Material.END_STONE_BRICK_SLAB, "LAUFBAU_TYPE_TOP"));
SeaPickle quadSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
quadSeaPickle.setWaterlogged(false);
quadSeaPickle.setPickles(4);
addPixel(quadSeaPickle, 2, 0, 2, 12, 7, 12, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_4"));
Campfire campfire = (Campfire) Material.CAMPFIRE.createBlockData();
campfire.setSignalFire(false);
campfire.setLit(false);
addPixel(campfire, 0, 0, 0, 16, 7, 16, createItem("LAUFBAU_BLOCK_CAMPFIRE", Material.CAMPFIRE));
SeaPickle trippleSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
trippleSeaPickle.setWaterlogged(false);
trippleSeaPickle.setPickles(3);
addPixel(trippleSeaPickle, 2, 0, 2, 12, 6, 12, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_3"));
SeaPickle doubleSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
doubleSeaPickle.setWaterlogged(false);
doubleSeaPickle.setPickles(2);
addPixel(doubleSeaPickle, 3, 0, 3, 10, 6, 10, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_2"));
SeaPickle singleSeaPickle = (SeaPickle) Material.SEA_PICKLE.createBlockData();
singleSeaPickle.setWaterlogged(false);
singleSeaPickle.setPickles(1);
addPixel(singleSeaPickle, 6, 0, 6, 4, 6, 4, createItem("LAUFBAU_BLOCK_SEA_PICKLE", Material.SEA_PICKLE, "LAUFBAU_COUNT_1"));
addPixel(Material.FLOWER_POT.createBlockData(), 5, 0, 5, 6, 6, 6, createItem("LAUFBAU_BLOCK_FLOWER_POT", Material.FLOWER_POT));
Snow snowLayers3 = (Snow) Material.SNOW.createBlockData();
snowLayers3.setLayers(3);
addPixel(snowLayers3, 0, 0, 0, 16, 4, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_3"));
TrapDoor bottomTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
bottomTrapDoor.setHalf(Bisected.Half.BOTTOM);
addPixel(bottomTrapDoor, 0, 0, 0, 16, 3, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_HALF_BOTTOM"));
TrapDoor topTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
topTrapDoor.setHalf(Bisected.Half.TOP);
addPixel(topTrapDoor, 0, 13, 0, 16, 3, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_HALF_TOP"));
Snow snowLayers2 = (Snow) Material.SNOW.createBlockData();
snowLayers2.setLayers(2);
addPixel(snowLayers2, 0, 0, 0, 16, 2, 16, createItem("LAUFBAU_BLOCK_SNOW", Material.SNOW, "LAUFBAU_LAYERS_2"));
addPixel(Material.LILY_PAD.createBlockData(), 1, 0, 1, 14, 1.5, 14, createItem("LAUFBAU_BLOCK_LILY_PAD", Material.LILY_PAD));
addPixel(Material.WHITE_CARPET.createBlockData(), 0, 0, 0, 16, 1, 16, createItem("LAUFBAU_BLOCK_WHITE_CARPET", Material.WHITE_CARPET));
Directional endRodBottomTop = (Directional) Material.END_ROD.createBlockData();
endRodBottomTop.setFacing(BlockFace.UP);
addPixel(endRodBottomTop, 6, 0, 6, 4, 16, 4, createItem("LAUFBAU_BLOCK_END_ROD", Material.END_ROD, "LAUFBAU_FACING_UP", "LAUFBAU_FACING_DOWN"));
Directional endRodNorthSouth = (Directional) Material.END_ROD.createBlockData();
endRodNorthSouth.setFacing(BlockFace.NORTH);
addPixel(endRodNorthSouth, 6, 6, 0, 4, 4, 16, createItem("LAUFBAU_BLOCK_END_ROD", Material.END_ROD, "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
Directional endRodEastWest = (Directional) Material.END_ROD.createBlockData();
endRodEastWest.setFacing(BlockFace.EAST);
addPixel(endRodEastWest, 0, 6, 6, 16, 4, 4, createItem("LAUFBAU_BLOCK_END_ROD", Material.END_ROD, "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
Directional lightningRodBottomTop = (Directional) Material.LIGHTNING_ROD.createBlockData();
lightningRodBottomTop.setFacing(BlockFace.UP);
addPixel(lightningRodBottomTop, 6, 0, 6, 4, 16, 4, createItem("LAUFBAU_BLOCK_LIGHTNING_ROD", Material.LIGHTNING_ROD, "LAUFBAU_FACING_UP", "LAUFBAU_FACING_DOWN"));
Directional lightningRodNorthSouth = (Directional) Material.LIGHTNING_ROD.createBlockData();
lightningRodNorthSouth.setFacing(BlockFace.NORTH);
addPixel(lightningRodNorthSouth, 6, 6, 0, 4, 4, 16, createItem("LAUFBAU_BLOCK_LIGHTNING_ROD", Material.LIGHTNING_ROD, "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
Directional lightningRodEastWest = (Directional) Material.LIGHTNING_ROD.createBlockData();
lightningRodEastWest.setFacing(BlockFace.EAST);
addPixel(lightningRodEastWest, 0, 6, 6, 16, 4, 4, createItem("LAUFBAU_BLOCK_LIGHTNING_ROD", Material.LIGHTNING_ROD, "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
Waterlogged conduit = (Waterlogged) Material.CONDUIT.createBlockData();
conduit.setWaterlogged(false);
addPixel(conduit, 5, 5, 5, 6, 6, 6, createItem("LAUFBAU_BLOCK_CONDUIT", Material.CONDUIT));
TrapDoor northTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
northTrapDoor.setFacing(BlockFace.NORTH);
northTrapDoor.setOpen(true);
addPixel(northTrapDoor, 0, 0, 13, 16, 16, 3, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_NORTH", "LAUFBAU_OPEN"));
TrapDoor southTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
southTrapDoor.setFacing(BlockFace.SOUTH);
southTrapDoor.setOpen(true);
addPixel(southTrapDoor, 0, 0, 0, 16, 16, 3, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_SOUTH", "LAUFBAU_OPEN"));
TrapDoor westTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
westTrapDoor.setFacing(BlockFace.WEST);
westTrapDoor.setOpen(true);
addPixel(westTrapDoor, 13, 0, 0, 3, 16, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_WEST", "LAUFBAU_OPEN"));
TrapDoor eastTrapDoor = (TrapDoor) Material.IRON_TRAPDOOR.createBlockData();
eastTrapDoor.setFacing(BlockFace.EAST);
eastTrapDoor.setOpen(true);
addPixel(eastTrapDoor, 0, 0, 0, 3, 16, 16, createItem("LAUFBAU_BLOCK_IRON_TRAPDOOR", Material.IRON_TRAPDOOR, "LAUFBAU_FACING_EAST", "LAUFBAU_OPEN"));
}
private static void addPixel(BlockData blockData, double xPixel, double yPixel, double zPixel, double dxPixel, double dyPixel, double dzPixel, SWItem swItem) {
new BlockBoundingBox(blockData, Arrays.asList(pixelCuboid(xPixel, yPixel, zPixel, dxPixel, dyPixel, dzPixel)), swItem);
}
private static void addPixel(BlockData blockData, double xPixel, double yPixel, double zPixel, double dxPixel, double dyPixel, double dzPixel, SWItem swItem, Consumer<BaseBlock> blockConsumer) {
new BlockBoundingBox(blockData, Arrays.asList(pixelCuboid(xPixel, yPixel, zPixel, dxPixel, dyPixel, dzPixel)), swItem, blockConsumer);
}
@SuppressWarnings("deprecation")
private static void randomPlayerHead(BaseBlock block) {
if (block instanceof SkullBlock) {
SkullBlock skullBlock = (SkullBlock) block;
skullBlock.setOwner(randomPlayerHead.get(random.nextInt(randomPlayerHead.size())).toString());
}
}
}
@@ -1,25 +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.bausystem.features.slaves.laufbau;
public interface BoundingBoxLoader {
void load();
}
@@ -22,6 +22,7 @@ package de.steamwar.bausystem.features.slaves.laufbau;
import de.steamwar.bausystem.region.Point;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.bukkit.util.BoundingBox;
@Data
@AllArgsConstructor
@@ -33,6 +34,15 @@ public class Cuboid {
private double dy;
private double dz;
public Cuboid(BoundingBox boundingBox) {
this.x = boundingBox.getMinX();
this.y = boundingBox.getMinY();
this.z = boundingBox.getMinZ();
this.dx = boundingBox.getWidthX();
this.dy = boundingBox.getHeight();
this.dz = boundingBox.getWidthZ();
}
public boolean intersects(Cuboid cuboid) {
double minx = x - cuboid.dx;
double miny = y - cuboid.dy;
@@ -24,15 +24,52 @@ import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.shared.Pair;
import de.steamwar.bausystem.utils.WorldEditUtils;
import de.steamwar.command.SWCommand;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.shapes.CollisionContext;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.block.CraftBlockType;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.util.CraftVoxelShape;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.VoxelShape;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@Linked
public class LaufbauCommand extends SWCommand {
static {
AtomicLong counter = new AtomicLong();
AtomicReference<VoxelShape> shape = new AtomicReference<>();
long time = System.currentTimeMillis();
Registry.BLOCK.forEach(blockType -> {
Block block = CraftBlockType.bukkitToMinecraftNew(blockType);
block.getStateDefinition().getPossibleStates().forEach(blockState -> {
VoxelShape voxelShape = new CraftVoxelShape(blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()));
shape.set(voxelShape);
Material material = blockType.asMaterial();
if (!material.isItem()) return;
new BlockBoundingBox(
CraftBlockData.createData(blockState),
voxelShape.getBoundingBoxes().stream().map(Cuboid::new).collect(Collectors.toList()),
new SWItem(material, "Item")
);
counter.incrementAndGet();
});
});
System.out.println(System.currentTimeMillis() - time + "ms " + shape.get() + " " + counter.get());
}
public LaufbauCommand() {
super("laufbau", "laufsklave");
}
@@ -1,261 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.AmethystCluster;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class AmethystBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
floorSmallAmethystBud();
ceilingSmallAmethystBud();
northSmallAmethystBud();
southSmallAmethystBud();
eastSmallAmethystBud();
westSmallAmethystBud();
floorMediumAmethystBud();
ceilingMediumAmethystBud();
northMediumAmethystBud();
southMediumAmethystBud();
eastMediumAmethystBud();
westMediumAmethystBud();
floorLargeAmethystBud();
ceilingLargeAmethystBud();
northLargeAmethystBud();
southLargeAmethystBud();
eastLargeAmethystBud();
westLargeAmethystBud();
floorAmethystCluster();
ceilingAmethystCluster();
northAmethystCluster();
southAmethystCluster();
eastAmethystCluster();
westAmethystCluster();
}
private void floorSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 4, 8, 3, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_UP"));
}
private void ceilingSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 13, 4, 8, 3, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_DOWN"));
}
private void northSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 13, 8, 8, 3));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_NORTH"));
}
private void southSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 0, 8, 8, 3));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_SOUTH"));
}
private void eastSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 4, 4, 3, 8, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_EAST"));
}
private void westSmallAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.SMALL_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(13, 4, 4, 3, 8, 8));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_SMALL_AMETHYST_BUD", Material.SMALL_AMETHYST_BUD, "LAUFBAU_FACING_WEST"));
}
private void floorMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 0, 3, 10, 4, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_UP"));
}
private void ceilingMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 12, 3, 10, 4, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_DOWN"));
}
private void northMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 12, 10, 10, 4));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_NORTH"));
}
private void southMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 4));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_SOUTH"));
}
private void eastMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 3, 3, 4, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_EAST"));
}
private void westMediumAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.MEDIUM_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(12, 3, 3, 4, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_MEDIUM_AMETHYST_BUD", Material.MEDIUM_AMETHYST_BUD, "LAUFBAU_FACING_WEST"));
}
private void floorLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 0, 3, 10, 5, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_UP"));
}
private void ceilingLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 11, 3, 10, 5, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_DOWN"));
}
private void northLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 11, 10, 10, 5));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_NORTH"));
}
private void southLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 5));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_SOUTH"));
}
private void eastLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 3, 3, 5, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_EAST"));
}
private void westLargeAmethystBud() {
AmethystCluster cluster = (AmethystCluster) Material.LARGE_AMETHYST_BUD.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(11, 3, 3, 5, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_LARGE_AMETHYST_BUD", Material.LARGE_AMETHYST_BUD, "LAUFBAU_FACING_WEST"));
}
private void floorAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.UP);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 0, 3, 10, 7, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_UP"));
}
private void ceilingAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 9, 3, 10, 7, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_DOWN"));
}
private void northAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 9, 10, 10, 7));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_NORTH"));
}
private void southAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 7));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_SOUTH"));
}
private void eastAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 3, 3, 7, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_EAST"));
}
private void westAmethystCluster() {
AmethystCluster cluster = (AmethystCluster) Material.AMETHYST_CLUSTER.createBlockData();
cluster.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(9, 3, 3, 7, 10, 10));
new BlockBoundingBox(cluster, cuboidList, createItem("LAUFBAU_BLOCK_AMETHYST_CLUSTER", Material.AMETHYST_CLUSTER, "LAUFBAU_FACING_WEST"));
}
}
@@ -1,46 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class AzaleaBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BlockData blockData = Material.FLOWERING_AZALEA.createBlockData();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(6, 0, 6, 4, 8, 4));
new BlockBoundingBox(blockData, cuboidList, createItem("LAUFBAU_BLOCK_AZALEA", Material.FLOWERING_AZALEA));
}
}
@@ -1,149 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Bell;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class BellBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
ceilingBell();
floorNorthBell();
floorEastBell();
doubleWallNorthBell();
doubleWallEastBell();
singleWallNorthBell();
singleWallSouthBell();
singleWallEastBell();
singleWallWestBell();
}
public void ceilingBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.CEILING);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 7, 2, 3, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_CEILING"));
}
public void floorNorthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.FLOOR);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 4, 16, 16, 8));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
public void floorEastBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.FLOOR);
bell.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 0, 8, 16, 16));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
public void doubleWallNorthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.DOUBLE_WALL);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 0, 2, 2, 16));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_DOUBLE_WALL", "LAUFBAU_FACING_NORTH"));
}
public void doubleWallEastBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.DOUBLE_WALL);
bell.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(0, 13, 7, 16, 2, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_DOUBLE_WALL", "LAUFBAU_FACING_EAST"));
}
public void singleWallNorthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 0, 2, 2, 13));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_NORTH"));
}
public void singleWallSouthBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(7, 13, 3, 2, 2, 13));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_SOUTH"));
}
public void singleWallEastBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(3, 13, 7, 13, 2, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_EAST"));
}
public void singleWallWestBell() {
Bell bell = (Bell) Material.BELL.createBlockData();
bell.setAttachment(Bell.Attachment.SINGLE_WALL);
bell.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 4, 8, 2, 8));
cuboidList.add(pixelCuboid(5, 6, 5, 6, 8, 6));
cuboidList.add(pixelCuboid(0, 13, 7, 13, 2, 2));
new BlockBoundingBox(bell, cuboidList, createItem("LAUFBAU_BLOCK_BELL", Material.BELL, "LAUFBAU_ATTACHMENT_SINGLE_WALL", "LAUFBAU_FACING_WEST"));
}
}
@@ -1,46 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.type.BrewingStand;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class BrewingStandBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BrewingStand brewingStand = (BrewingStand) Material.BREWING_STAND.createBlockData();
List<Cuboid> cuboids = new ArrayList<>();
cuboids.add(pixelCuboid(1, 0, 1, 14, 2, 14));
cuboids.add(pixelCuboid(7, 2, 7, 2, 12, 2));
new BlockBoundingBox(brewingStand, cuboids, createItem("LAUFBAU_BLOCK_BREWING_STAND", Material.BREWING_STAND));
}
}
@@ -1,62 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.Lightable;
import org.bukkit.block.data.type.Candle;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class CandleBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
caked();
single();
}
private void caked() {
Lightable candleCake = (Lightable) Material.CYAN_CANDLE_CAKE.createBlockData();
candleCake.setLit(true);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(7, 8, 7, 2, 6, 2));
new BlockBoundingBox(candleCake, cuboidList, createItem("LAUFBAU_BLOCK_CANDLE_CAKE", Material.CAKE));
}
private void single() {
Candle candle = (Candle) Material.CYAN_CANDLE.createBlockData();
candle.setCandles(1);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(7, 0, 7, 2, 6, 2));
new BlockBoundingBox(candle, cuboidList, createItem("LAUFBAU_BLOCK_CANDLE", Material.CYAN_CANDLE, "LAUFBAU_COUNT_1"));
}
}
@@ -1,69 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Axis;
import org.bukkit.Material;
import org.bukkit.block.data.Orientable;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class ChainBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
bottomTopChain();
northSouthChain();
eastWestChain();
}
private void bottomTopChain() {
Orientable chainBottomTop = (Orientable) Material.CHAIN.createBlockData();
chainBottomTop.setAxis(Axis.Y);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(6.5, 0, 6.5, 3, 16, 3));
new BlockBoundingBox(chainBottomTop, cuboidList, createItem("LAUFBAU_BLOCK_CHAIN", Material.CHAIN, "LAUFBAU_FACING_UP", "LAUFBAU_FACING_DOWN"));
}
private void northSouthChain() {
Orientable chainBottomTop = (Orientable) Material.CHAIN.createBlockData();
chainBottomTop.setAxis(Axis.Z);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(6.5, 6.5, 0, 3, 3, 16));
new BlockBoundingBox(chainBottomTop, cuboidList, createItem("LAUFBAU_BLOCK_CHAIN", Material.CHAIN, "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
private void eastWestChain() {
Orientable chainBottomTop = (Orientable) Material.CHAIN.createBlockData();
chainBottomTop.setAxis(Axis.X);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 6.5, 6.5, 16, 3, 3));
new BlockBoundingBox(chainBottomTop, cuboidList, createItem("LAUFBAU_BLOCK_CHAIN", Material.CHAIN, "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
}
@@ -1,89 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.MultipleFacing;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class ChorusPlantBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
for (int nx = 0; nx < 2; nx++) {
for (int ny = 0; ny < 2; ny++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int py = 0; py < 2; py++) {
for (int pz = 0; pz < 2; pz++) {
MultipleFacing chorusPlant = (MultipleFacing) Material.CHORUS_PLANT.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(3, 3, 3, 10, 10, 10));
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
chorusPlant.setFace(BlockFace.WEST, true);
cuboidList.add(pixelCuboid(0, 3, 3, 3, 10, 10));
}
if (ny == 1) {
lore.add("LAUFBAU_CONNECTION_DOWN");
chorusPlant.setFace(BlockFace.DOWN, true);
cuboidList.add(pixelCuboid(3, 0, 3, 10, 3, 10));
}
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
chorusPlant.setFace(BlockFace.NORTH, true);
cuboidList.add(pixelCuboid(3, 3, 0, 10, 10, 3));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
chorusPlant.setFace(BlockFace.EAST, true);
cuboidList.add(pixelCuboid(13, 3, 3, 3, 10, 10));
}
if (py == 1) {
lore.add("LAUFBAU_CONNECTION_UP");
chorusPlant.setFace(BlockFace.UP, true);
cuboidList.add(pixelCuboid(3, 13, 3, 10, 3, 10));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
chorusPlant.setFace(BlockFace.SOUTH, true);
cuboidList.add(pixelCuboid(3, 3, 13, 10, 10, 3));
}
new BlockBoundingBox(chorusPlant, cuboidList, createItem("LAUFBAU_BLOCK_CHORUS_PLANT", Material.CHORUS_PLANT, lore.toArray(new String[0])));
}
}
}
}
}
}
}
}
@@ -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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class DragonEggBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BlockData blockData = Material.DRAGON_EGG.createBlockData();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(1, 0, 1, 14, 16, 14));
new BlockBoundingBox(blockData, cuboidList, createItem("LAUFBAU_BLOCK_DRAGON_EGG", Material.DRAGON_EGG));
}
}
@@ -1,59 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.type.BigDripleaf;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class DripLeafBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
tiltNone();
tiltPartial();
}
private void tiltNone() {
BigDripleaf bigDripleaf = (BigDripleaf) Material.BIG_DRIPLEAF.createBlockData();
bigDripleaf.setTilt(BigDripleaf.Tilt.NONE);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 11, 0, 16, 4, 16));
new BlockBoundingBox(bigDripleaf, cuboidList, createItem("LAUFBAU_BLOCK_BIG_DRIP_LEAF", Material.BIG_DRIPLEAF, "LAUFBAU_TILT_NONE"));
}
private void tiltPartial() {
BigDripleaf bigDripleaf = (BigDripleaf) Material.BIG_DRIPLEAF.createBlockData();
bigDripleaf.setTilt(BigDripleaf.Tilt.PARTIAL);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 11, 0, 16, 2, 16));
new BlockBoundingBox(bigDripleaf, cuboidList, createItem("LAUFBAU_BLOCK_BIG_DRIP_LEAF", Material.BIG_DRIPLEAF, "LAUFBAU_TILT_PARTIAL"));
}
}
@@ -1,75 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Fence;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class FencesBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
for (int nx = 0; nx < 2; nx++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int pz = 0; pz < 2; pz++) {
Fence fence = (Fence) Material.NETHER_BRICK_FENCE.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(6, 0, 6, 4, 24, 4));
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
fence.setFace(BlockFace.NORTH, true);
cuboidList.add(pixelCuboid(6, 0, 0, 4, 24, 6));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
fence.setFace(BlockFace.SOUTH, true);
cuboidList.add(pixelCuboid(6, 0, 10, 4, 24, 6));
}
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
fence.setFace(BlockFace.WEST, true);
cuboidList.add(pixelCuboid(0, 0, 6, 6, 24, 4));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
fence.setFace(BlockFace.EAST, true);
cuboidList.add(pixelCuboid(10, 0, 6, 6, 24, 4));
}
new BlockBoundingBox(fence, cuboidList, createItem("LAUFBAU_BLOCK_NETHER_BRICK_FENCE", Material.NETHER_BRICK_FENCE, lore.toArray(new String[0])));
}
}
}
}
}
}
@@ -1,157 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.FaceAttachable;
import org.bukkit.block.data.type.Grindstone;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class GrindstoneBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
floorNorthGrindstone();
floorEastGrindstone();
ceilingNorthGrindstone();
ceilingEastGrindstone();
wallNorthGrindstone();
wallSouthGrindstone();
wallEastGrindstone();
wallWestGrindstone();
}
public void floorNorthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.FLOOR);
grindstone.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 4, 2, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 0, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(12, 0, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(2, 7, 5, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 7, 5, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
public void floorEastGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.FLOOR);
grindstone.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(2, 4, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(6, 0, 2, 4, 7, 2));
cuboidList.add(pixelCuboid(6, 0, 12, 4, 7, 2));
cuboidList.add(pixelCuboid(5, 7, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(5, 7, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_FLOOR", "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
public void ceilingNorthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.CEILING);
grindstone.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 2, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 9, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(12, 9, 6, 2, 7, 4));
cuboidList.add(pixelCuboid(2, 3, 5, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 3, 5, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_CEILING", "LAUFBAU_FACING_NORTH", "LAUFBAU_FACING_SOUTH"));
}
public void ceilingEastGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.CEILING);
grindstone.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(2, 0, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(6, 9, 2, 4, 7, 2));
cuboidList.add(pixelCuboid(6, 9, 12, 4, 7, 2));
cuboidList.add(pixelCuboid(5, 3, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(5, 3, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_CEILING", "LAUFBAU_FACING_EAST", "LAUFBAU_FACING_WEST"));
}
public void wallNorthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 2, 0, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 6, 9, 2, 4, 7));
cuboidList.add(pixelCuboid(12, 6, 9, 2, 4, 7));
cuboidList.add(pixelCuboid(2, 5, 3, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 5, 3, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_NORTH"));
}
public void wallSouthGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 2, 4, 8, 12, 12));
cuboidList.add(pixelCuboid(2, 6, 0, 2, 4, 7));
cuboidList.add(pixelCuboid(12, 6, 0, 2, 4, 7));
cuboidList.add(pixelCuboid(2, 5, 7, 2, 6, 6));
cuboidList.add(pixelCuboid(12, 5, 7, 2, 6, 6));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_SOUTH"));
}
public void wallEastGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 2, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(0, 6, 2, 7, 4, 2));
cuboidList.add(pixelCuboid(0, 6, 12, 7, 4, 2));
cuboidList.add(pixelCuboid(7, 5, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(7, 5, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_EAST"));
}
public void wallWestGrindstone() {
Grindstone grindstone = (Grindstone) Material.GRINDSTONE.createBlockData();
grindstone.setAttachedFace(FaceAttachable.AttachedFace.WALL);
grindstone.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 2, 4, 12, 12, 8));
cuboidList.add(pixelCuboid(9, 6, 2, 7, 4, 2));
cuboidList.add(pixelCuboid(9, 6, 12, 7, 4, 2));
cuboidList.add(pixelCuboid(3, 5, 2, 6, 6, 2));
cuboidList.add(pixelCuboid(3, 5, 12, 6, 6, 2));
new BlockBoundingBox(grindstone, cuboidList, createItem("LAUFBAU_BLOCK_GRINDSTONE", Material.GRINDSTONE, "LAUFBAU_ATTACHMENT_WALL", "LAUFBAU_FACING_WEST"));
}
}
@@ -1,97 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Hopper;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class HopperBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
downHopper();
northHopper();
southHopper();
eastHopper();
westHopper();
}
public void downHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.DOWN);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(6, 0, 6, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_FLOOR"));
}
public void northHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(6, 4, 0, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_NORTH"));
}
public void southHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(6, 4, 12, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_SOUTH"));
}
public void eastHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(12, 4, 6, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_EAST"));
}
public void westHopper() {
Hopper hopper = (Hopper) Material.HOPPER.createBlockData();
hopper.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 10, 0, 16, 6, 16));
cuboidList.add(pixelCuboid(4, 4, 4, 8, 6, 8));
cuboidList.add(pixelCuboid(0, 4, 6, 4, 4, 4));
new BlockBoundingBox(hopper, cuboidList, createItem("LAUFBAU_BLOCK_HOPPER", Material.HOPPER, "LAUFBAU_CONNECTION_WEST"));
}
}
@@ -1,75 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Fence;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class IronBarBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
for (int nx = 0; nx < 2; nx++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int pz = 0; pz < 2; pz++) {
Fence fence = (Fence) Material.IRON_BARS.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(7, 0, 7, 2, 16, 2));
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
fence.setFace(BlockFace.NORTH, true);
cuboidList.add(pixelCuboid(7, 0, 0, 2, 16, 7));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
fence.setFace(BlockFace.SOUTH, true);
cuboidList.add(pixelCuboid(7, 0, 9, 2, 16, 7));
}
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
fence.setFace(BlockFace.WEST, true);
cuboidList.add(pixelCuboid(0, 0, 7, 7, 16, 2));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
fence.setFace(BlockFace.EAST, true);
cuboidList.add(pixelCuboid(9, 0, 7, 7, 16, 2));
}
new BlockBoundingBox(fence, cuboidList, createItem("LAUFBAU_BLOCK_IRON_BARS", Material.IRON_BARS, lore.toArray(new String[0])));
}
}
}
}
}
}
@@ -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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.type.Lantern;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class LanternBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
lantern();
hangingLantern();
}
public void lantern() {
Lantern lantern = (Lantern) Material.LANTERN.createBlockData();
lantern.setHanging(false);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(5, 0, 5, 6, 7, 6));
cuboidList.add(pixelCuboid(6, 7, 6, 4, 2, 4));
new BlockBoundingBox(lantern, cuboidList, createItem("LAUFBAU_BLOCK_LANTERN", Material.LANTERN));
}
public void hangingLantern() {
Lantern lantern = (Lantern) Material.LANTERN.createBlockData();
lantern.setHanging(true);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(5, 1, 5, 6, 7, 6));
cuboidList.add(pixelCuboid(6, 8, 6, 4, 2, 4));
new BlockBoundingBox(lantern, cuboidList, createItem("LAUFBAU_BLOCK_LANTERN", Material.LANTERN, "LAUFBAU_HANGING"));
}
}
@@ -1,46 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class LecternBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
BlockData blockData = Material.LECTERN.createBlockData();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 2, 16));
cuboidList.add(pixelCuboid(4, 2, 4, 8, 12, 8));
new BlockBoundingBox(blockData, cuboidList, createItem("LAUFBAU_BLOCK_LECTERN", Material.LECTERN));
}
}
@@ -1,343 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Stairs;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class StairBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
straightBottomNorthStair();
straightBottomSouthStair();
straightBottomEastStair();
straightBottomWestStair();
straightTopNorthStair();
straightTopSouthStair();
straightTopEastStair();
straightTopWestStair();
outerLeftBottomNorthStair();
outerLeftBottomSouthStair();
outerLeftBottomEastStair();
outerLeftBottomWestStair();
outerLeftTopNorthStair();
outerLeftTopSouthStair();
outerLeftTopEastStair();
outerLeftTopWestStair();
innerLeftBottomNorthStair();
innerLeftBottomSouthStair();
innerLeftBottomEastStair();
innerLeftBottomWestStair();
innerLeftTopNorthStair();
innerLeftTopSouthStair();
innerLeftTopEastStair();
innerLeftTopWestStair();
}
public void straightBottomNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_NORTH"));
}
public void straightBottomSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_SOUTH"));
}
public void straightBottomEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 8, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_EAST"));
}
public void straightBottomWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_WEST"));
}
public void straightTopNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_NORTH"));
}
public void straightTopSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 16, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_SOUTH"));
}
public void straightTopEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 0, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_EAST"));
}
public void straightTopWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.STRAIGHT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 8, 8, 16));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_STRAIGHT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_WEST"));
}
public void outerLeftBottomNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_NORTH"));
}
public void outerLeftBottomSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_SOUTH"));
}
public void outerLeftBottomEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_EAST"));
}
public void outerLeftBottomWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_WEST"));
}
public void outerLeftTopNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_NORTH"));
}
public void outerLeftTopSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_SOUTH"));
}
public void outerLeftTopEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(8, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_EAST"));
}
public void outerLeftTopWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.OUTER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_OUTER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_WEST"));
}
public void innerLeftBottomNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_NORTH"));
}
public void innerLeftBottomSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_SOUTH"));
}
public void innerLeftBottomEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 8, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_EAST"));
}
public void innerLeftBottomWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.BOTTOM);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 8, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 8, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_BOTTOM", "LAUFBAU_FACING_WEST"));
}
public void innerLeftTopNorthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.NORTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_NORTH"));
}
public void innerLeftTopSouthStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.SOUTH);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_SOUTH"));
}
public void innerLeftTopEastStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.EAST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 0, 16, 8, 8));
cuboidList.add(pixelCuboid(8, 0, 8, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_EAST"));
}
public void innerLeftTopWestStair() {
Stairs stairs = (Stairs) Material.END_STONE_BRICK_STAIRS.createBlockData();
stairs.setShape(Stairs.Shape.INNER_LEFT);
stairs.setHalf(Stairs.Half.TOP);
stairs.setFacing(BlockFace.WEST);
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(0, 8, 0, 16, 8, 16));
cuboidList.add(pixelCuboid(0, 0, 8, 16, 8, 8));
cuboidList.add(pixelCuboid(0, 0, 0, 8, 8, 8));
new BlockBoundingBox(stairs, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS", Material.END_STONE_BRICK_STAIRS, "LAUFBAU_SHAPE_INNER_LEFT", "LAUFBAU_HALF_TOP", "LAUFBAU_FACING_WEST"));
}
}
@@ -1,79 +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.bausystem.features.slaves.laufbau.boundingboxes;
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
import de.steamwar.bausystem.features.slaves.laufbau.BoundingBoxLoader;
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Wall;
import java.util.ArrayList;
import java.util.List;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.createItem;
import static de.steamwar.bausystem.features.slaves.laufbau.LaufbauUtils.pixelCuboid;
@Linked
public class WallBoundingBox implements BoundingBoxLoader {
@Override
public void load() {
v18();
}
private void v18() {
for (int nx = 0; nx < 2; nx++) {
for (int nz = 0; nz < 2; nz++) {
for (int px = 0; px < 2; px++) {
for (int pz = 0; pz < 2; pz++) {
Wall fence = (Wall) Material.END_STONE_BRICK_WALL.createBlockData();
List<String> lore = new ArrayList<>();
List<Cuboid> cuboidList = new ArrayList<>();
cuboidList.add(pixelCuboid(4, 0, 4, 8, 24, 8));
if (nz == 1) {
lore.add("LAUFBAU_CONNECTION_NORTH");
fence.setHeight(BlockFace.NORTH, Wall.Height.LOW);
cuboidList.add(pixelCuboid(5, 0, 0, 6, 24, 4));
}
if (pz == 1) {
lore.add("LAUFBAU_CONNECTION_SOUTH");
fence.setHeight(BlockFace.SOUTH, Wall.Height.LOW);
cuboidList.add(pixelCuboid(5, 0, 12, 6, 24, 4));
}
if (nx == 1) {
lore.add("LAUFBAU_CONNECTION_WEST");
fence.setHeight(BlockFace.WEST, Wall.Height.LOW);
cuboidList.add(pixelCuboid(0, 0, 5, 4, 24, 6));
}
if (px == 1) {
lore.add("LAUFBAU_CONNECTION_EAST");
fence.setHeight(BlockFace.EAST, Wall.Height.LOW);
cuboidList.add(pixelCuboid(12, 0, 5, 4, 24, 6));
}
new BlockBoundingBox(fence, cuboidList, createItem("LAUFBAU_BLOCK_END_STONE_BRICK_WALL", Material.END_STONE_BRICK_WALL, lore.toArray(new String[0])));
}
}
}
}
}
}
@@ -31,6 +31,7 @@ import de.steamwar.command.TypeMapper;
import de.steamwar.core.CraftbukkitWrapper;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import de.steamwar.techhider.legacy.TechHider;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -38,7 +39,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import de.steamwar.techhider.legacy.TechHider;
import java.util.*;
import java.util.stream.Collectors;
@@ -25,7 +25,6 @@ import de.steamwar.bausystem.features.tracer.rendering.TraceEntity;
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
import de.steamwar.bausystem.region.Region;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityAction;
import de.steamwar.entity.REntityServer;
import lombok.Getter;
import lombok.Setter;
@@ -38,6 +38,7 @@ import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -47,7 +48,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -73,19 +73,7 @@ public class BindCommand extends SWCommand implements Listener {
}
}
private static final CommandMap commandMap;
static {
Field knownCommandsField;
try {
knownCommandsField = Bukkit.getServer().getClass().getDeclaredField("commandMap");
knownCommandsField.setAccessible(true);
commandMap = (CommandMap) knownCommandsField.get(Bukkit.getServer());
} catch (IllegalAccessException | NoSuchFieldException var2) {
Bukkit.shutdown();
throw new SecurityException("Oh shit. Commands cannot be registered.", var2);
}
}
private static final CommandMap commandMap = ((CraftServer) Bukkit.getServer()).getCommandMap();
private static final NamespacedKey KEY = SWUtils.getNamespaceKey("command");
@@ -21,7 +21,6 @@ package de.steamwar.bausystem.features.util;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.mojang.authlib.GameProfile;
import de.steamwar.Reflection;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
@@ -30,7 +29,6 @@ import de.steamwar.core.ProtocolWrapper;
import de.steamwar.core.SWPlayer;
import de.steamwar.linkage.Linked;
import net.minecraft.network.protocol.game.*;
import net.minecraft.server.level.ServerPlayerGameMode;
import net.minecraft.world.entity.player.Abilities;
import net.minecraft.world.level.GameType;
import org.bukkit.Bukkit;
@@ -103,10 +101,8 @@ public class NoClipCommand extends SWCommand implements Listener {
TinyProtocol.instance.addFilter(ServerboundSetCreativeModeSlotPacket.class, third);
}
private static final Reflection.Field<GameType> playerGameMode = Reflection.getField(ServerPlayerGameMode.class, GameType.class, 0);
private void setInternalGameMode(Player player, GameMode gameMode) {
playerGameMode.set(((CraftPlayer) player).getHandle().gameMode, GameType.byId(gameMode.getValue()));
((CraftPlayer) player).getHandle().gameMode.gameModeForPlayer = GameType.byId(gameMode.getValue());
}
@Register(help = true)
@@ -36,8 +36,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
@@ -25,6 +25,7 @@ import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.linkage.Linked;
import de.steamwar.sql.BauweltMember;
import de.steamwar.techhider.legacy.TechHider;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -39,7 +40,6 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.player.*;
import org.bukkit.util.Vector;
import de.steamwar.techhider.legacy.TechHider;
import java.util.HashSet;
import java.util.Set;
@@ -28,6 +28,7 @@ import de.steamwar.command.SWCommand;
import de.steamwar.core.CraftbukkitWrapper;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import de.steamwar.techhider.legacy.TechHider;
import net.md_5.bungee.api.ChatMessageType;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.server.level.ServerPlayer;
@@ -40,7 +41,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import de.steamwar.techhider.legacy.TechHider;
import java.util.*;
import java.util.function.BiFunction;
@@ -19,7 +19,6 @@
package de.steamwar.bausystem.utils;
import de.steamwar.Reflection;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.experimental.UtilityClass;
@@ -86,9 +85,6 @@ public class PlaceItemUtils {
.collect(Collectors.toSet());
}
private static final Reflection.Field<?> positionAccessor = Reflection.getField(CraftBlockState.class, BlockPos.class, 0);
private static final Reflection.Field<?> worldAccessor = Reflection.getField(CraftBlockState.class, CraftWorld.class, 0);
/**
* Attempt to place an {@link ItemStack} the {@link Player} is holding against a {@link Block} inside the World.
* This can be easily used inside the {@link org.bukkit.event.player.PlayerInteractEvent} to mimik placing a
@@ -288,8 +284,9 @@ public class PlaceItemUtils {
} else {
// If a BlockState is present set the Position and World to the Block you want to place
Location blockLocation = block.getLocation();
positionAccessor.set(blockState, new BlockPos(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ()));
worldAccessor.set(blockState, blockLocation.getWorld());
CraftBlockState craftBlockState = (CraftBlockState) blockState;
craftBlockState.position = new BlockPos(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ());
craftBlockState.world = (CraftWorld) blockLocation.getWorld();
}
if (blockData.getMaterial().isSolid()) {
@@ -20,7 +20,6 @@
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.bausystem.BauSystem;
import net.minecraft.network.protocol.game.ClientboundTickingStatePacket;
import net.minecraft.server.MinecraftServer;
@@ -33,7 +32,6 @@ public class TickManager implements Listener {
public static final TickManager impl = new TickManager();
private static final ServerTickRateManager manager = MinecraftServer.getServer().tickRateManager();
private static final Reflection.Field<Long> remainingSprintTicks = Reflection.getField(ServerTickRateManager.class, long.class, 0);
private boolean blockTpsPacket = true;
private int totalSteps;
@@ -121,7 +119,7 @@ public class TickManager implements Listener {
public long getRemainingTicks() {
if (isSprinting()) {
return remainingSprintTicks.get(manager);
return manager.remainingSprintTicks;
} else {
return manager.frozenTicksToRun();
}
@@ -19,6 +19,7 @@
package de.steamwar.bausystem.utils;
import com.fastasyncworldedit.core.regions.selector.PolyhedralRegionSelector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
@@ -32,16 +33,19 @@ import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.*;
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
import de.steamwar.Reflection;
import com.sk89q.worldedit.world.World;
import de.steamwar.bausystem.shared.Pair;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@UtilityClass
@@ -91,17 +95,36 @@ public class WorldEditUtils {
.getRegionSelector(BukkitAdapter.adapt(player.getWorld()));
return new Pair<>(regionSelector.getClass(), regionSelector.getVertices()
.stream()
.map(blockVector3 -> blockVector3 == null ? null : adapt(player.getWorld(), blockVector3))
.map(blockVector3 -> {
if (blockVector3 == null) {
return null;
} else {
return BukkitAdapter.adapt(player.getWorld(), blockVector3);
}
})
.collect(Collectors.toList()));
}
private static final Map<Class<? extends RegionSelector>, Function<World, RegionSelector>> constructors = new HashMap<>();
static {
constructors.put(CuboidRegionSelector.class, CuboidRegionSelector::new);
constructors.put(ExtendingCuboidRegionSelector.class, ExtendingCuboidRegionSelector::new);
constructors.put(Polygonal2DRegionSelector.class, Polygonal2DRegionSelector::new);
constructors.put(EllipsoidRegionSelector.class, EllipsoidRegionSelector::new);
constructors.put(SphereRegionSelector.class, SphereRegionSelector::new);
constructors.put(CylinderRegionSelector.class, CylinderRegionSelector::new);
constructors.put(ConvexPolyhedralRegionSelector.class, ConvexPolyhedralRegionSelector::new);
constructors.put(PolyhedralRegionSelector.class, PolyhedralRegionSelector::new);
}
public void setVertices(Player player, Class<? extends RegionSelector> clazz, List<Location> vertices) {
LocalSession localSession = WorldEdit.getInstance()
.getSessionManager()
.get(BukkitAdapter.adapt(player));
Reflection.Constructor constructorInvoker = Reflection.getConstructor(clazz, com.sk89q.worldedit.world.World.class);
RegionSelector regionSelector = (RegionSelector) constructorInvoker.invoke(BukkitAdapter.adapt(player.getWorld()));
Function<World, RegionSelector> constructor = constructors.get(clazz);
if (constructor == null) return;
RegionSelector regionSelector = constructor.apply(BukkitAdapter.adapt(player.getWorld()));
localSession.setRegionSelector(BukkitAdapter.adapt(player.getWorld()), regionSelector);
if (vertices.isEmpty()) return;
@@ -127,13 +150,9 @@ public class WorldEditUtils {
try {
BlockVector3 min = regionSelector.getRegion().getMinimumPoint();
BlockVector3 max = regionSelector.getRegion().getMaximumPoint();
return new Pair<>(adapt(player.getWorld(), min), adapt(player.getWorld(), max));
return new Pair<>(BukkitAdapter.adapt(player.getWorld(), min), BukkitAdapter.adapt(player.getWorld(), max));
} catch (IncompleteRegionException e) {
return null;
}
}
private Location adapt(World world, BlockVector3 blockVector3) {
return new Location(world, blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ());
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ version: "2.0"
depend: [ WorldEdit, SpigotCore ]
load: POSTWORLD
main: de.steamwar.bausystem.BauSystem
api-version: "1.13"
api-version: "1.21"
website: "https://steamwar.de"
description: "So unseriös wie wir sind: BauSystem nur besser."
+1
View File
@@ -37,5 +37,6 @@ tasks.register<DevServer>("DevBau21") {
dependsOn(":SpigotCore:shadowJar")
dependsOn(":BauSystem:shadowJar")
dependsOn(":SchematicSystem:shadowJar")
dependsOn(":KotlinCore:shadowJar")
template = "Bau21"
}
+1 -2
View File
@@ -152,8 +152,7 @@ class DevCommand : CliktCommand("dev") {
)
val additionalVersions = mapOf(
"Tutorial" to 15,
"Lobby" to 20
"Lobby" to 21
)
fun findVersion(server: String): Int? =
@@ -32,7 +32,10 @@ import de.steamwar.fightsystem.record.GlobalRecorder;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.utils.*;
import de.steamwar.fightsystem.utils.FightUI;
import de.steamwar.fightsystem.utils.HullHider;
import de.steamwar.fightsystem.utils.SWSound;
import de.steamwar.fightsystem.utils.TechHiderWrapper;
import de.steamwar.linkage.AbstractLinker;
import de.steamwar.linkage.SpigotLinker;
import de.steamwar.message.Message;
@@ -27,12 +27,9 @@ import de.steamwar.fightsystem.fight.FightPlayer;
import de.steamwar.fightsystem.utils.Message;
import de.steamwar.fightsystem.utils.Region;
import de.steamwar.fightsystem.utils.SWSound;
import de.steamwar.techhider.ProtocolUtils;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import java.util.List;
public class EnternCountdown extends Countdown {
private static int calcTime(FightPlayer fp, Countdown countdown) {
@@ -47,7 +44,6 @@ public class EnternCountdown extends Countdown {
}
private final FightPlayer fightPlayer;
private List<ProtocolUtils.ChunkPos> chunkPos;
public EnternCountdown(FightPlayer fp, Countdown countdown) {
super(calcTime(fp, countdown), new Message("ENTERN_COUNTDOWN"), SWSound.BLOCK_NOTE_PLING, false);
@@ -24,6 +24,7 @@ import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.record.GlobalRecorder;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Registry;
import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity;
@@ -88,7 +89,7 @@ public class Fight {
}
public static void playSound(Sound sound, float volume, float pitch) {
GlobalRecorder.getInstance().soundAtPlayer(sound.name(), volume, pitch);
GlobalRecorder.getInstance().soundAtPlayer(Registry.SOUNDS.getKey(sound).getKey(), volume, pitch);
//volume: max. 100, pitch: max. 2
Bukkit.getServer().getOnlinePlayers().forEach(player -> player.playSound(player, sound, volume, pitch));
}
@@ -35,7 +35,9 @@ import de.steamwar.fightsystem.listener.TeamArea;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.fightsystem.utils.*;
import de.steamwar.fightsystem.utils.FightUI;
import de.steamwar.fightsystem.utils.ItemBuilder;
import de.steamwar.fightsystem.utils.Region;
import de.steamwar.fightsystem.winconditions.Wincondition;
import de.steamwar.fightsystem.winconditions.Winconditions;
import de.steamwar.inventory.SWItem;
@@ -24,6 +24,7 @@ import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@@ -38,11 +39,13 @@ public class EntityDamage implements Listener {
@EventHandler
public void handleEntityDamage(EntityDamageEvent event) {
if (!(event.getEntity() instanceof Player)) return;
if (Config.ArenaRegion.in2dRegion(event.getEntity().getLocation())) event.setCancelled(true);
}
@EventHandler
public void handleEntityDamageByEntity(EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof Player)) return;
if (Config.ArenaRegion.in2dRegion(event.getEntity().getLocation())) event.setCancelled(true);
}
}
@@ -25,7 +25,6 @@ import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
@@ -20,7 +20,6 @@
package de.steamwar.fightsystem.listener;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem;
@@ -37,7 +36,6 @@ import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.fightsystem.utils.SWSound;
import de.steamwar.linkage.Linked;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.network.protocol.game.ServerboundUseItemPacket;
import net.minecraft.world.InteractionHand;
@@ -115,18 +113,18 @@ public class Recording implements Listener {
}.register();
new StateDependent(ArenaMode.AntiReplay, FightState.Ingame) {
private final BiFunction<Player, ServerboundUseItemPacket, Object> place = Recording.this::blockPlace;
private final BiFunction<Player, Object, Object> dig = Recording.this::blockDig;
private final BiFunction<Player, ServerboundPlayerActionPacket, Object> dig = Recording.this::blockDig;
@Override
public void enable() {
TinyProtocol.instance.addFilter(ServerboundUseItemPacket.class, place);
TinyProtocol.instance.addFilter(blockDigPacket, dig);
TinyProtocol.instance.addFilter(ServerboundPlayerActionPacket.class, dig);
}
@Override
public void disable() {
TinyProtocol.instance.removeFilter(ServerboundUseItemPacket.class, place);
TinyProtocol.instance.removeFilter(blockDigPacket, dig);
TinyProtocol.instance.removeFilter(ServerboundPlayerActionPacket.class, dig);
}
}.register();
new StateDependentTask(ArenaMode.AntiReplay, FightState.All, () -> {
@@ -143,13 +141,8 @@ public class Recording implements Listener {
GlobalRecorder.getInstance().entitySpeed(entity);
}
private static final Class<? extends Packet<?>> blockDigPacket = ServerboundPlayerActionPacket.class;
private static final Class<?> playerDigType = blockDigPacket.getDeclaredClasses()[0];
private static final Reflection.Field<?> blockDigType = Reflection.getField(blockDigPacket, playerDigType, 0);
private static final Object releaseUseItem = playerDigType.getEnumConstants()[5];
private Object blockDig(Player p, Object packet) {
if (!isNotSent(p) && blockDigType.get(packet) == releaseUseItem) {
private Object blockDig(Player p, ServerboundPlayerActionPacket packet) {
if (!isNotSent(p) && packet.getAction() == ServerboundPlayerActionPacket.Action.RELEASE_USE_ITEM) {
GlobalRecorder.getInstance().bowSpan(p, false, false);
}
return packet;
@@ -34,7 +34,9 @@ import de.steamwar.fightsystem.fight.FightWorld;
import de.steamwar.fightsystem.fight.FreezeWorld;
import de.steamwar.fightsystem.listener.FightScoreboard;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.utils.*;
import de.steamwar.fightsystem.utils.FightUI;
import de.steamwar.fightsystem.utils.Message;
import de.steamwar.fightsystem.utils.TechHiderWrapper;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
@@ -510,11 +512,13 @@ public class PacketProcessor implements Listener {
float volume = source.readFloat();
float pitch = source.readFloat();
Sound sound = Sound.valueOf(soundName);
Sound sound = Registry.SOUNDS.get(NamespacedKey.minecraft(soundName));
if (sound == null) sound = Sound.valueOf(soundName); // TODO: Remove in 26.x because of no longer needed backwards compatibility
Sound finalSound = sound;
execSync(() -> {
Location location = new Location(Config.world, x, y, z);
location.getWorld().playSound(location, sound, SoundCategory.valueOf(soundCategory), volume, pitch);
location.getWorld().playSound(location, finalSound, SoundCategory.valueOf(soundCategory), volume, pitch);
});
}
@@ -524,9 +528,11 @@ public class PacketProcessor implements Listener {
float volume = source.readFloat();
float pitch = source.readFloat();
Sound sound = Sound.valueOf(soundName);
Sound sound = Registry.SOUNDS.get(NamespacedKey.minecraft(soundName));
if (sound == null) sound = Sound.valueOf(soundName); // TODO: Remove in 26.x because of no longer needed backwards compatibility
Sound finalSound = sound;
execSync(() -> Fight.playSound(sound, volume, pitch));
execSync(() -> Fight.playSound(finalSound, volume, pitch));
}
private void pasteSchem(FightTeam team) throws IOException {
@@ -33,6 +33,7 @@ import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Registry;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.entity.Entity;
@@ -238,7 +239,7 @@ public interface Recorder {
}
default void sound(int x, int y, int z, SWSound soundType, String soundCategory, float volume, float pitch) {
write(0x32, x, y, z, soundType.getSound().name(), soundCategory, volume, pitch);
write(0x32, x, y, z, Registry.SOUNDS.getKey(soundType.getSound()).getKey(), soundCategory, volume, pitch);
}
default void soundAtPlayer(String soundType, float volume, float pitch) {
@@ -19,7 +19,6 @@
package de.steamwar.fightsystem.utils;
import de.steamwar.Reflection;
import de.steamwar.core.CraftbukkitWrapper;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.events.BoardingEvent;
@@ -51,7 +50,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Collection;
import java.util.Optional;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@@ -82,18 +81,13 @@ public class TechHiderWrapper extends StateDependent implements Listener {
.map(CraftMagicNumbers::getBlock)
.collect(Collectors.toUnmodifiableSet());
Object blockEntityType;
try {
blockEntityType = BuiltInRegistries.class.getDeclaredField("BLOCK_ENTITY_TYPE").get(null);
} catch (Exception e) {
throw new IllegalStateException(e);
}
Reflection.Method method = Reflection.getTypedMethod(Reflection.getClass("net.minecraft.core.Registry"), "get", Optional.class, ResourceLocation.class);
Set<BlockEntityType<?>> blockEntityTypeToObfuscate = Config.GameModeConfig.Techhider.HiddenBlockEntities.stream()
.map((id) -> {
.map(id -> {
ResourceLocation loc = ResourceLocation.parse(id);
return ((Optional<Holder.Reference<BlockEntityType<?>>>) method.invoke(blockEntityType, loc)).get().value();
return BuiltInRegistries.BLOCK_ENTITY_TYPE.get(loc).orElse(null);
})
.filter(Objects::nonNull)
.map(Holder.Reference::value)
.collect(Collectors.toUnmodifiableSet());
new TechHider(CraftMagicNumbers.getBlock(Config.GameModeConfig.Techhider.ObfuscateWith), new AccessPrivilegeProvider() {
-30
View File
@@ -30,16 +30,6 @@ dependencies {
implementation(project(":FightSystem:FightSystem_Core"))
}
tasks.register<FightServer>("WarGear20") {
group = "run"
description = "Run a WarGear 1.20 Fight Server"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":FightSystem:shadowJar")
template = "WarGear20"
worldName = "arenas/Pentraki"
config = "WarGear20.yml"
}
tasks.register<FightServer>("HalloweenWS") {
group = "run"
description = "Run a Halloween 1.21 Fight Replay Server"
@@ -63,23 +53,3 @@ tasks.register<FightServer>("WarGear21") {
config = "WarGear21.yml"
jar = "/jars/paper-1.21.6.jar"
}
tasks.register<FightServer>("SpaceCraftDev20") {
group = "run"
description = "Run a SpaceCraftDev 1.20 Fight Server"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":FightSystem:shadowJar")
template = "SpaceCraft20"
worldName = "arenas/AS_Horizon"
config = "SpaceCraftDev20.yml"
}
tasks.register<FightServer>("QuickGear20") {
group = "run"
description = "Run a QuickGear 1.20 Fight Server"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":FightSystem:shadowJar")
template = "QuickGear20"
worldName = "arenas/WarGearPark"
config = "QuickGear20.yml"
}
+6
View File
@@ -19,6 +19,7 @@
plugins {
steamwar.java
widener
}
dependencies {
@@ -32,6 +33,11 @@ dependencies {
compileOnly(libs.fawe)
}
widener {
fromCatalog(libs.nms)
fromCatalog(libs.paperapi)
}
tasks.register<DevServer>("DevLobby20") {
group = "run"
description = "Run a 1.20 Dev Lobby"
@@ -42,7 +42,7 @@ public class ColorInit {
if (inputStream == null) {
colors = new byte[256 * 256 * 256];
for (int i = 0; i < colors.length; i++) {
colors[i] = MapPalette.matchColor(new Color(i));
colors[i] = matchColor(new Color(i));
}
} else {
try {
@@ -57,4 +57,26 @@ public class ColorInit {
}
System.out.println("[ColorInit] Initialization took " + (System.currentTimeMillis() - time) + "ms");
}
public static byte matchColor(Color color) {
if (color.getAlpha() < 128) return 0;
if (MapPalette.mapColorCache != null && MapPalette.mapColorCache.isCached()) {
return MapPalette.mapColorCache.matchColor(color);
}
int index = 0;
double best = -1;
for (int i = 4; i < MapPalette.colors.length; i++) {
double distance = MapPalette.getDistance(color, MapPalette.colors[i]);
if (distance < best || best == -1) {
best = distance;
index = i;
}
}
// Minecraft has 248 colors, some of which have negative byte representations
return (byte) (index < 128 ? index : -129 + (index - 127));
}
}
@@ -254,7 +254,8 @@ public class CustomMap implements Listener {
int green = pixels[i2];
int i3 = (y * width + x) * numBands + 2;
int blue = pixels[i3];
Color nearest = MapPalette.getColor(ColorInit.getColorByte(red, green, blue));
int colorIndex = ColorInit.getColorByte(red, green, blue);
Color nearest = MapPalette.colors[colorIndex >= 0 ? colorIndex : colorIndex + 256];
pixels[(y * width + x) * numBands] = nearest.getRed();
pixels[i2] = nearest.getGreen();
+6
View File
@@ -0,0 +1,6 @@
accessWidener v2 named
# For CustomMap and ColorInit
accessible field org/bukkit/map/MapPalette colors [Ljava/awt/Color;
accessible method org/bukkit/map/MapPalette getDistance (Ljava/awt/Color;Ljava/awt/Color;)D
accessible field org/bukkit/map/MapPalette mapColorCache Lorg/bukkit/map/MapPalette$MapColorCache;
@@ -20,9 +20,12 @@
package de.steamwar.misslewars.slowmo;
import de.steamwar.misslewars.MissileWars;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.TickRateManager;
import org.bukkit.Bukkit;
public class SlowMoRunner {
private static TickRateManager tickRateManager = MinecraftServer.getServer().tickRateManager();
private static long currentTime = 0;
private static long current = 0;
@@ -40,14 +43,14 @@ public class SlowMoRunner {
if (currentTime > 0) {
current += 1;
if (current % 5 == 0) {
SlowMoUtils.unfreeze();
tickRateManager.setFrozen(false);
current = 0;
} else {
SlowMoUtils.freeze();
tickRateManager.setFrozen(true);
}
currentTime--;
} else {
SlowMoUtils.unfreeze();
tickRateManager.setFrozen(false);
}
}, 0, 1);
}
@@ -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.misslewars.slowmo;
import net.minecraft.server.level.ServerLevel;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
import java.lang.reflect.Field;
public class SlowMoUtils {
private static final Field field;
public static final boolean freezeEnabled;
private static boolean frozen = false;
private static final World world;
static {
Field temp;
try {
temp = ServerLevel.class.getField("freezed");
} catch (NoSuchFieldException e) {
temp = null;
}
field = temp;
if (field != null) field.setAccessible(true);
freezeEnabled = field != null;
world = Bukkit.getWorlds().get(0);
}
public static void freeze() {
setFreeze(world, true);
}
public static void unfreeze() {
setFreeze(world, false);
}
public static boolean frozen() {
return freezeEnabled && frozen;
}
private static void setFreeze(World world, boolean state) {
if (freezeEnabled) {
if (frozen == state) return;
try {
field.set(((CraftWorld) world).getHandle(), state);
frozen = state;
} catch (IllegalAccessException e) {
// Ignored;
}
}
}
}
@@ -37,8 +37,8 @@ public class AutoChecker {
public static final AutoChecker impl = new AutoChecker();
public AutoCheckerResult check(Clipboard clipboard, GameModeConfig<Material, String> type) {
return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX())
.depth(clipboard.getDimensions().getBlockZ()).blockScanResult(scan(clipboard, type))
return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().x()).width(clipboard.getDimensions().x())
.depth(clipboard.getDimensions().z()).blockScanResult(scan(clipboard, type))
.entities(clipboard.getEntities().stream().map(Entity::getLocation)
.map(blockVector3 -> new BlockPos(blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ()))
.collect(Collectors.toList()))
@@ -46,19 +46,19 @@ public class AutoChecker {
}
public AutoCheckerResult sizeCheck(Clipboard clipboard, GameModeConfig<Material, String> type) {
return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX())
.depth(clipboard.getDimensions().getBlockZ()).build();
return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().y()).width(clipboard.getDimensions().x())
.depth(clipboard.getDimensions().z()).build();
}
public AutoChecker.BlockScanResult scan(Clipboard clipboard, GameModeConfig<Material, String> type) {
AutoChecker.BlockScanResult result = new AutoChecker.BlockScanResult();
BlockVector3 min = clipboard.getMinimumPoint();
BlockVector3 max = clipboard.getMaximumPoint();
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
for (int x = min.x(); x <= max.x(); x++) {
for (int y = min.y(); y <= max.y(); y++) {
for (int z = min.z(); z <= max.z(); z++) {
final BaseBlock block = clipboard.getFullBlock(BlockVector3.at(x, y, z));
final Material material = Material.matchMaterial(block.getBlockType().getId());
final Material material = Material.matchMaterial(block.getBlockType().id());
if (material == null) {
continue;
}
@@ -69,7 +69,7 @@ public class AutoChecker {
checkInventory(result, block, material, new BlockPos(x, y, z), type);
}
if (x == min.getBlockX() || x == max.getBlockX() || y == max.getBlockY() || z == min.getBlockZ() || z == max.getBlockZ()) {
if (x == min.x() || x == max.x() || y == max.y() || z == min.z() || z == max.z()) {
result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(new BlockPos(x, y, z));
}
}
@@ -245,12 +245,12 @@ public class SchematicCommand extends SWCommand {
BlockState replaceType = Objects.requireNonNull(toReplace.contains(Material.END_STONE) ? BlockTypes.IRON_BLOCK : BlockTypes.END_STONE).getDefaultState();
BlockVector3 min = clipboard.getMinimumPoint();
BlockVector3 max = clipboard.getMaximumPoint();
for (int i = min.getBlockX(); i <= max.getBlockX(); i++) {
for (int j = min.getBlockY(); j <= max.getBlockY(); j++) {
for (int k = min.getBlockZ(); k <= max.getBlockZ(); k++) {
for (int i = min.x(); i <= max.x(); i++) {
for (int j = min.y(); j <= max.y(); j++) {
for (int k = min.z(); k <= max.z(); k++) {
BlockVector3 vector = BlockVector3.at(i, j, k);
BaseBlock block = clipboard.getFullBlock(vector);
if (toReplace.contains(Material.matchMaterial(block.getBlockType().getId()))) {
if (toReplace.contains(Material.matchMaterial(block.getBlockType().id()))) {
clipboard.setBlock(vector, replaceType.toBaseBlock());
}
}
@@ -19,6 +19,7 @@
plugins {
steamwar.java
widener
}
tasks.compileJava {
@@ -61,3 +62,7 @@ dependencies {
implementation(libs.anvilgui)
}
widener {
fromCatalog(libs.nms)
}
@@ -1,7 +1,6 @@
package com.comphenix.tinyprotocol;
import com.google.common.collect.MapMaker;
import de.steamwar.Reflection;
import de.steamwar.core.CRIUWakeupEvent;
import de.steamwar.core.Core;
import io.netty.channel.*;
@@ -180,22 +179,12 @@ public class TinyProtocol {
networkManagers = serverConnection.getConnections();
// We need to synchronize against this list
createServerChannelHandler();
for (ChannelFuture item : serverConnection.channels) {
// Channel future that contains the server connection
Channel serverChannel = item.channel();
// Find the correct list, or implicitly throw an exception
boolean looking = true;
for (int i = 0; looking; i++) {
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
for (Object item : list) {
if (!(item instanceof ChannelFuture)) break;
// Channel future that contains the server connection
Channel serverChannel = ((ChannelFuture) item).channel();
serverChannels.add(serverChannel);
serverChannel.pipeline().addFirst(serverChannelHandler);
looking = false;
}
serverChannels.add(serverChannel);
serverChannel.pipeline().addFirst(serverChannelHandler);
}
}
@@ -1,315 +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;
import de.steamwar.core.Core;
import jdk.internal.misc.Unsafe;
import lombok.AllArgsConstructor;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@UtilityClass
public final class Reflection {
public static final int MAJOR_VERSION;
public static final int MINOR_VERSION;
static {
String[] version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.");
MAJOR_VERSION = Integer.parseInt(version[1]);
MINOR_VERSION = version.length > 2 ? Integer.parseInt(version[2]) : 0;
}
private static final String ORG_BUKKIT_CRAFTBUKKIT = Bukkit.getServer().getClass().getPackage().getName();
public static final String LEGACY_NET_MINECRAFT_SERVER = ORG_BUKKIT_CRAFTBUKKIT.replace("org.bukkit.craftbukkit", "net.minecraft.server");
private static final Map<String, String> spigotClassnames = new HashMap<>();
static {
// See https://mappings.dev for complete mappings
spigotClassnames.put("net.minecraft.Util", "net.minecraft.SystemUtils");
spigotClassnames.put("net.minecraft.core.BlockPos", "net.minecraft.core.BlockPosition");
spigotClassnames.put("net.minecraft.core.DefaultedRegistry", "net.minecraft.core.RegistryBlocks");
spigotClassnames.put("net.minecraft.core.IdMapper", "net.minecraft.core.RegistryBlockID");
spigotClassnames.put("net.minecraft.core.Vec3i", "net.minecraft.core.BaseBlockPosition");
spigotClassnames.put("net.minecraft.nbt.CompoundTag", "net.minecraft.nbt.NBTTagCompound");
spigotClassnames.put("net.minecraft.network.Connection", "net.minecraft.network.NetworkManager");
spigotClassnames.put("net.minecraft.network.chat.Component", "net.minecraft.network.chat.IChatBaseComponent");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAddEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAddPlayerPacket", "net.minecraft.network.protocol.game.PacketPlayOutNamedEntitySpawn");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundAnimatePacket", "net.minecraft.network.protocol.game.PacketPlayOutAnimation");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockDestructionPacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockBreak");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket", "net.minecraft.network.protocol.game.PacketPlayOutTileEntityData");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockAction");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayOutBlockChange");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundContainerClosePacket", "net.minecraft.network.protocol.game.PacketPlayOutCloseWindow");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundEntityEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityStatus");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundExplodePacket", "net.minecraft.network.protocol.game.PacketPlayOutExplosion");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundGameEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutGameStateChange");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo", "net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$a");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelEventPacket", "net.minecraft.network.protocol.game.PacketPlayOutWorldEvent");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket", "net.minecraft.network.protocol.game.PacketPlayOutWorldParticles");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntity");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Pos", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutRelEntityMove");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$PosRot", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutRelEntityMoveLook");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundMoveEntityPacket$Rot", "net.minecraft.network.protocol.game.PacketPlayOutEntity$PacketPlayOutEntityLook");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket", "net.minecraft.network.protocol.game.PacketPlayOutOpenSignEditor");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundRotateHeadPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityHeadRotation");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetObjectivePacket", "net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSetScorePacket", "net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundSoundPacket", "net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect");
spigotClassnames.put("net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket", "net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundContainerClickPacket", "net.minecraft.network.protocol.game.PacketPlayInWindowClick");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket", "net.minecraft.network.protocol.game.PacketPlayInUseEntity");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket$Action", "net.minecraft.network.protocol.game.PacketPlayInUseEntity$EnumEntityUseAction");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundInteractPacket$ActionType", "net.minecraft.network.protocol.game.PacketPlayInUseEntity$b");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInPosition");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInPositionLook");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot", "net.minecraft.network.protocol.game.PacketPlayInFlying$PacketPlayInLook");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundPlayerActionPacket", "net.minecraft.network.protocol.game.PacketPlayInBlockDig");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket", "net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundSignUpdatePacket", "net.minecraft.network.protocol.game.PacketPlayInUpdateSign");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundUseItemPacket", "net.minecraft.network.protocol.game.PacketPlayInBlockPlace");
spigotClassnames.put("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket", "net.minecraft.network.protocol.game.PacketPlayInUseItem");
spigotClassnames.put("net.minecraft.network.syncher.EntityDataAccessor", "net.minecraft.network.syncher.DataWatcherObject");
spigotClassnames.put("net.minecraft.network.syncher.EntityDataSerializer", "net.minecraft.network.syncher.DataWatcherSerializer");
spigotClassnames.put("net.minecraft.network.syncher.EntityDataSerializers", "net.minecraft.network.syncher.DataWatcherRegistry");
spigotClassnames.put("net.minecraft.network.syncher.SynchedEntityData$DataItem", "net.minecraft.network.syncher.DataWatcher$Item");
spigotClassnames.put("net.minecraft.server.ServerScoreboard$Method", "net.minecraft.server.ScoreboardServer$Action");
spigotClassnames.put("net.minecraft.server.level.ChunkMap", "net.minecraft.server.level.PlayerChunkMap");
spigotClassnames.put("net.minecraft.server.level.ChunkMap$TrackedEntity", "net.minecraft.server.level.PlayerChunkMap$EntityTracker");
spigotClassnames.put("net.minecraft.server.level.ServerChunkCache", "net.minecraft.server.level.ChunkProviderServer");
spigotClassnames.put("net.minecraft.server.level.ServerLevel", "net.minecraft.server.level.WorldServer");
spigotClassnames.put("net.minecraft.server.level.ServerPlayer", "net.minecraft.server.level.EntityPlayer");
spigotClassnames.put("net.minecraft.server.network.ServerConnectionListener", "net.minecraft.server.network.ServerConnection");
spigotClassnames.put("net.minecraft.world.InteractionHand", "net.minecraft.world.EnumHand");
spigotClassnames.put("net.minecraft.world.entity.EntityType", "net.minecraft.world.entity.EntityTypes");
spigotClassnames.put("net.minecraft.world.entity.Pose", "net.minecraft.world.entity.EntityPose");
spigotClassnames.put("net.minecraft.world.entity.item.PrimedTnt", "net.minecraft.world.entity.item.EntityTNTPrimed");
spigotClassnames.put("net.minecraft.world.entity.projectile.AbstractArrow", "net.minecraft.world.entity.projectile.EntityArrow");
spigotClassnames.put("net.minecraft.world.level.GameType", "net.minecraft.world.level.EnumGamemode");
spigotClassnames.put("net.minecraft.world.level.LevelAccessor", "net.minecraft.world.level.GeneratorAccess");
spigotClassnames.put("net.minecraft.world.level.block.state.BlockState", "net.minecraft.world.level.block.state.IBlockData");
spigotClassnames.put("net.minecraft.world.level.block.state.StateDefinition", "net.minecraft.world.level.block.state.BlockStateList");
spigotClassnames.put("net.minecraft.world.level.chunk.LevelChunk", "net.minecraft.world.level.chunk.Chunk");
spigotClassnames.put("net.minecraft.world.level.material.FlowingFluid", "net.minecraft.world.level.material.FluidTypeFlowing");
spigotClassnames.put("net.minecraft.world.level.material.Fluids", "net.minecraft.world.level.material.FluidTypes");
spigotClassnames.put("net.minecraft.world.level.material.FluidState", "net.minecraft.world.level.material.Fluid");
spigotClassnames.put("net.minecraft.world.phys.BlockHitResult", "net.minecraft.world.phys.MovingObjectPositionBlock");
spigotClassnames.put("net.minecraft.world.phys.Vec3", "net.minecraft.world.phys.Vec3D");
spigotClassnames.put("net.minecraft.resources.ResourceLocation", "net.minecraft.resources.MinecraftKey");
spigotClassnames.put("net.minecraft.util.ProgressListener", "net.minecraft.util.IProgressUpdate");
}
public static Class<?> getClass(String name) {
try {
if (name.startsWith("org.bukkit.craftbukkit")) {
return Class.forName(ORG_BUKKIT_CRAFTBUKKIT + name.substring(22));
} else if (MAJOR_VERSION < 17 && name.startsWith("net.minecraft")) {
return Class.forName(LEGACY_NET_MINECRAFT_SERVER + "." + spigotClassnames.getOrDefault(name, name).split("[.](?=[^.]*$)")[1]);
} else if (MAJOR_VERSION < 21 || MINOR_VERSION < 4) {
return Class.forName(spigotClassnames.getOrDefault(name, name));
} else {
Class<?> clazz = null;
try {
clazz = Class.forName(name);
} catch (ClassNotFoundException e) {
}
if (clazz != null && clazz.getName().equals(name)) {
return clazz;
}
try {
return Core.class.getClassLoader().getParent().loadClass(name);
} catch (ClassNotFoundException e) {
if (clazz == null) {
throw e;
}
return clazz;
}
}
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Cannot find " + name, e);
}
}
@AllArgsConstructor
public static class Field<T> {
private final java.lang.reflect.Field f;
@SuppressWarnings("unchecked")
public T get(Object target) {
try {
return (T) f.get(target);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Cannot read field", e);
}
}
public void set(Object target, Object value) {
try {
f.set(target, value);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Cannot write field", e);
}
}
}
public static <T> Field<T> getField(Class<?> target, String name, Class<T> fieldType) {
return getField(target, name, fieldType, 0);
}
public static <T> Field<T> getField(Class<?> target, Class<T> fieldType, int index) {
return getField(target, null, fieldType, index);
}
public static <T> Field<T> getField(Class<?> target, Class<T> fieldType, int index, Class<?>... parameters) {
return getField(target, null, fieldType, index, parameters);
}
private static <T> Field<T> getField(Class<?> target, String name, Class<T> fieldType, int index, Class<?>... parameters) {
for (final java.lang.reflect.Field field : target.getDeclaredFields()) {
if (matching(field, name, fieldType, parameters) && index-- <= 0) {
field.setAccessible(true);
return new Field<>(field);
}
}
// Search in parent classes
if (target.getSuperclass() != null) {
return getField(target.getSuperclass(), name, fieldType, index);
}
throw new IllegalArgumentException("Cannot find field with type " + fieldType);
}
private static <T> boolean matching(java.lang.reflect.Field field, String name, Class<T> fieldType, Class<?>... parameters) {
if (name != null && !field.getName().equals(name)) return false;
if (!fieldType.isAssignableFrom(field.getType())) return false;
if (parameters.length > 0) {
Type[] arguments = ((ParameterizedType) field.getGenericType()).getActualTypeArguments();
for (int i = 0; i < parameters.length; i++) {
if (arguments[i] instanceof ParameterizedType ? ((ParameterizedType) arguments[i]).getRawType() != parameters[i] : arguments[i] != parameters[i]) {
return false;
}
}
}
return true;
}
@AllArgsConstructor
public static class Method {
private final java.lang.reflect.Method m;
public Object invoke(Object target, Object... arguments) {
try {
return m.invoke(target, arguments);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot invoke method " + m, e);
}
}
}
public static Method getTypedMethod(Class<?> clazz, String methodName, Class<?> returnType, Class<?>... params) {
for (final java.lang.reflect.Method method : clazz.getDeclaredMethods()) {
if ((methodName == null || method.getName().equals(methodName))
&& (returnType == null || method.getReturnType().equals(returnType))
&& Arrays.equals(method.getParameterTypes(), params)) {
method.setAccessible(true);
return new Method(method);
}
}
// Search in every superclass
if (clazz.getSuperclass() != null) {
return getTypedMethod(clazz.getSuperclass(), methodName, returnType, params);
}
throw new IllegalArgumentException(String.format("Cannot find method %s (%s).", methodName, Arrays.asList(params)));
}
@AllArgsConstructor
public static class Constructor {
private final java.lang.reflect.Constructor<?> c;
public Object invoke(Object... arguments) {
try {
return c.newInstance(arguments);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot invoke constructor " + c, e);
}
}
}
public static Constructor getConstructor(Class<?> clazz, Class<?>... params) {
for (final java.lang.reflect.Constructor<?> constructor : clazz.getDeclaredConstructors()) {
if (Arrays.equals(constructor.getParameterTypes(), params)) {
constructor.setAccessible(true);
return new Constructor(constructor);
}
}
throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params)));
}
public static Object newInstance(Class<?> clazz) {
try {
return Unsafe.getUnsafe().allocateInstance(clazz);
} catch (InstantiationException e) {
throw new SecurityException("Could not create object", e);
}
}
}
@@ -22,35 +22,20 @@ package de.steamwar.command;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.craftbukkit.CraftServer;
import java.lang.reflect.Field;
import java.util.Map;
@UtilityClass
class CommandRegistering {
private static final CommandMap commandMap;
private static final SimpleCommandMap commandMap;
private static final Map<String, Command> knownCommandMap;
static {
try {
final Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap");
commandMapField.setAccessible(true);
commandMap = (CommandMap) commandMapField.get(Bukkit.getServer());
} catch (NoSuchFieldException | IllegalAccessException exception) {
Bukkit.shutdown();
throw new SecurityException("Oh shit. Commands cannot be registered.", exception);
}
try {
final Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands");
knownCommandsField.setAccessible(true);
knownCommandMap = (Map<String, Command>) knownCommandsField.get(commandMap);
} catch (NoSuchFieldException | IllegalAccessException exception) {
Bukkit.shutdown();
throw new SecurityException("Oh shit. Commands cannot be registered.", exception);
}
commandMap = ((CraftServer) Bukkit.getServer()).getCommandMap();
knownCommandMap = commandMap.getKnownCommands();
}
static void unregister(Command command) {
@@ -19,20 +19,11 @@
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.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializer;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
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 {
public static final BountifulWrapper impl = new BountifulWrapper();
@@ -44,60 +35,4 @@ public class BountifulWrapper {
if (type == ChatMessageType.CHAT) type = ChatMessageType.SYSTEM;
player.spigot().sendMessage(type, msg);
}
private static final Class<?> dataWatcherRegistry = EntityDataSerializers.class;
private static final Class<?> dataWatcherSerializer = EntityDataSerializer.class;
public Object getDataWatcherObject(int index, Class<?> type) {
return new EntityDataAccessor<>(index, (EntityDataSerializer<Object>) Reflection.getField(dataWatcherRegistry, dataWatcherSerializer, 0, type).get(null));
}
public Object getDataWatcherItem(Object dwo, Object value) {
return new SynchedEntityData.DataItem<>((EntityDataAccessor<Object>) 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) -> {
field.set(packet, new PositionMoveRotation(new Vec3(x, y, z), field.get(packet).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.UUIDSetter getUUIDSetter(Class<?> packetClass) {
Reflection.Field<UUID> uuidField = Reflection.getField(packetClass, UUID.class, 0);
return uuidField::set;
}
public interface PositionSetter {
void set(Object packet, double x, double y, double z, float pitch, float yaw);
}
public interface UUIDSetter {
void set(Object packet, UUID uuid);
}
}
@@ -20,7 +20,6 @@
package de.steamwar.core;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.sql.internal.Statement;
import io.netty.channel.ChannelFuture;
import net.minecraft.server.MinecraftServer;
@@ -96,9 +95,6 @@ class CheckpointUtilsJ9 {
}
}
private static final Reflection.Field<List> channelFutures = Reflection.getField(ServerConnectionListener.class, List.class, 0, ChannelFuture.class);
private static void freezeInternal(Path path) throws Exception {
Bukkit.getPluginManager().callEvent(new CRIUSleepEvent());
@@ -109,9 +105,9 @@ class CheckpointUtilsJ9 {
// Close socket
ServerConnectionListener serverConnection = MinecraftServer.getServer().getConnection();
List<?> channels = channelFutures.get(serverConnection);
for (Object future : channels) {
((ChannelFuture) future).channel().close().syncUninterruptibly();
List<ChannelFuture> channels = serverConnection.channels;
for (ChannelFuture future : channels) {
future.channel().close().syncUninterruptibly();
}
channels.clear();
@@ -145,8 +141,8 @@ class CheckpointUtilsJ9 {
// Reopen socket
serverConnection.startTcpServerListener(InetAddress.getLoopbackAddress(), port);
for (Object future : channels) {
((ChannelFuture) future).channel().config().setAutoRead(true);
for (ChannelFuture future : channels) {
future.channel().config().setAutoRead(true);
}
Bukkit.getPluginManager().callEvent(new CRIUWakeupEvent());
@@ -5,8 +5,8 @@
*
* 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.
* the Free Software Foundation, either versionStrings 3 of the License, or
* (at your option) any later versionStrings.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,7 +20,6 @@
package de.steamwar.core;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.command.SWCommandUtils;
import de.steamwar.command.SWTypeMapperCreator;
import de.steamwar.command.TabCompletionCache;
@@ -49,9 +48,13 @@ public class Core extends JavaPlugin {
public static final Message MESSAGE = new Message("SpigotCore", Core.class.getClassLoader());
@Getter
@Deprecated
public static int getVersion() {
return Reflection.MAJOR_VERSION;
private static final int version;
static {
String[] versionStrings = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.");
version = Integer.parseInt(versionStrings[1]);
}
@Getter
@@ -19,7 +19,6 @@
package de.steamwar.core;
import de.steamwar.Reflection;
import de.steamwar.sql.SWException;
import org.spigotmc.WatchdogThread;
@@ -39,9 +38,7 @@ public class ErrorHandler extends Handler {
public ErrorHandler() {
Logger.getLogger("").addHandler(this);
Reflection.Field<WatchdogThread> getInstance = Reflection.getField(WatchdogThread.class, WatchdogThread.class, 0);
watchdogThreadId = getInstance.get(null).getId();
watchdogThreadId = WatchdogThread.instance.threadId();
}
void unregister() {
@@ -20,7 +20,6 @@
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;
@@ -33,13 +32,8 @@ public class WorldIdentifier {
private static ResourceKey<Level> resourceKey = null;
private static final Class<?> resourceKeyClass = ResourceKey.class;
private static final Class<?> minecraftKeyClass = ResourceLocation.class;
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) {
resourceKey = (ResourceKey<Level>) resourceKeyConstructor.invoke(minecraftKeyConstructor.invoke("minecraft", "dimension"), minecraftKeyConstructor.invoke("steamwar", name));
resourceKey = new ResourceKey<>(new ResourceLocation("minecraft", "dimension"), new ResourceLocation("steamwar", name));
}
public WorldIdentifier() {
@@ -22,7 +22,6 @@ 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;
@@ -35,13 +34,10 @@ 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());
current = MinecraftServer.getServer().services;
fallback = current.profileRepository();
}
@@ -68,7 +64,6 @@ public class SteamwarGameProfileRepository implements GameProfileRepository {
}
public void inject() {
Services newServices = new Services(current.sessionService(), current.servicesKeySet(), this, current.profileCache(), current.paperConfigurations());
field.set(MinecraftServer.getServer(), newServices);
MinecraftServer.getServer().services = new Services(current.sessionService(), current.servicesKeySet(), this, current.profileCache(), current.paperConfigurations());
}
}
@@ -20,16 +20,13 @@
package de.steamwar.core.events;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.core.Core;
import de.steamwar.linkage.Linked;
import de.steamwar.sql.SWException;
import de.steamwar.techhider.ProtocolUtils;
import de.steamwar.techhider.TechHider;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket;
import net.minecraft.world.phys.BlockHitResult;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -38,7 +35,6 @@ import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
@Linked
public class AntiNocom implements Listener {
@@ -13,7 +13,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import java.util.*;
import java.util.Optional;
@Linked
@@ -49,7 +49,7 @@ public class RArmorStand extends REntity implements RInteractableEntity<RArmorSt
super.spawn(packetSink);
if (size != null && size != Size.NORMAL) {
packetSink.accept(getDataWatcherPacket(sizeWatcher, size.value));
entityDataPacket().add(sizeWatcher, size.value).send(packetSink);
}
}
@@ -61,9 +61,9 @@ public class RBlockDisplay extends RDisplay {
private static final EntityDataAccessor<BlockState> blockWatcher = new EntityDataAccessor<>(23, EntityDataSerializers.BLOCK_STATE);
private void getBlock(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getBlock(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || !block.getAsString(true).equals(DEFAULT_BLOCK.getAsString(true))) {
packetSink.accept(blockWatcher, ((CraftBlockData) block).getState());
packetSink.add(blockWatcher, ((CraftBlockData) block).getState());
}
}
}
@@ -89,18 +89,13 @@ public abstract class RDisplay extends REntity {
}
@SafeVarargs
protected final void sendPacket(Consumer<Object> packetSink, BiConsumer<Boolean, BiConsumer<Object, Object>>... dataSinkSinks) {
List<Object> keyValueData = new ArrayList<>();
protected final void sendPacket(Consumer<Object> packetSink, BiConsumer<Boolean, EntityDataPacketBuilder>... dataSinkSinks) {
EntityDataPacketBuilder builder = entityDataPacket();
boolean ignoreDefault = packetSink == updatePacketSink;
for (BiConsumer<Boolean, BiConsumer<Object, Object>> dataSinkSink : dataSinkSinks) {
dataSinkSink.accept(ignoreDefault, (dataWatcher, value) -> {
keyValueData.add(dataWatcher);
keyValueData.add(value);
});
}
if (!keyValueData.isEmpty()) {
packetSink.accept(getDataWatcherPacket(keyValueData.toArray()));
for (BiConsumer<Boolean, EntityDataPacketBuilder> dataSinkSink : dataSinkSinks) {
dataSinkSink.accept(ignoreDefault, builder);
}
if (!builder.isEmpty()) builder.send(packetSink);
}
public void setTransform(@NonNull Transformation transform) {
@@ -113,12 +108,12 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Vector3f> scaleWatcher = new EntityDataAccessor<>(12, EntityDataSerializers.VECTOR3);
private static final EntityDataAccessor<Quaternionf> rightRotationWatcher = new EntityDataAccessor<>(14, EntityDataSerializers.QUATERNION);
private void getTransformData(boolean ignoreDefault, BiConsumer<Object, Object> dataSink) {
private void getTransformData(boolean ignoreDefault, EntityDataPacketBuilder dataSink) {
if (ignoreDefault || !transform.equals(DEFAULT_TRANSFORM)) {
dataSink.accept(translationWatcher, transform.getTranslation());
dataSink.accept(leftRotationWatcher, transform.getLeftRotation());
dataSink.accept(scaleWatcher, transform.getScale());
dataSink.accept(rightRotationWatcher, transform.getRightRotation());
dataSink.add(translationWatcher, transform.getTranslation());
dataSink.add(leftRotationWatcher, transform.getLeftRotation());
dataSink.add(scaleWatcher, transform.getScale());
dataSink.add(rightRotationWatcher, transform.getRightRotation());
}
}
@@ -130,10 +125,10 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Integer> transformationInterpolationDurationWatcher = new EntityDataAccessor<>(9, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> positionOrRotationInterpolationDurationWatcher = new EntityDataAccessor<>(10, EntityDataSerializers.INT);
private void getInterpolationDuration(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getInterpolationDuration(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || interpolationDelay != 0) {
packetSink.accept(transformationInterpolationDurationWatcher, interpolationDuration);
packetSink.accept(positionOrRotationInterpolationDurationWatcher, interpolationDuration);
packetSink.add(transformationInterpolationDurationWatcher, interpolationDuration);
packetSink.add(positionOrRotationInterpolationDurationWatcher, interpolationDuration);
}
}
@@ -144,9 +139,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Float> viewRangeWatcher = new EntityDataAccessor<>(17, EntityDataSerializers.FLOAT);
private void getViewRange(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getViewRange(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || viewRange != 1.0F) {
packetSink.accept(viewRangeWatcher, viewRange);
packetSink.add(viewRangeWatcher, viewRange);
}
}
@@ -157,9 +152,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Float> shadowRadiusWatcher = new EntityDataAccessor<>(18, EntityDataSerializers.FLOAT);
private void getShadowRadius(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getShadowRadius(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || shadowRadius != 0.0F) {
packetSink.accept(shadowRadiusWatcher, shadowRadius);
packetSink.add(shadowRadiusWatcher, shadowRadius);
}
}
@@ -170,9 +165,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Float> shadowStrengthWatcher = new EntityDataAccessor<>(19, EntityDataSerializers.FLOAT);
private void getShadowStrength(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getShadowStrength(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || shadowStrength != 1.0F) {
packetSink.accept(shadowStrengthWatcher, shadowStrength);
packetSink.add(shadowStrengthWatcher, shadowStrength);
}
}
@@ -183,9 +178,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Float> displayWidthWatcher = new EntityDataAccessor<>(20, EntityDataSerializers.FLOAT);
private void getDisplayWidth(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getDisplayWidth(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || displayWidth != 0.0F) {
packetSink.accept(displayWidthWatcher, displayWidth);
packetSink.add(displayWidthWatcher, displayWidth);
}
}
@@ -196,9 +191,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Float> displayHeightWatcher = new EntityDataAccessor<>(21, EntityDataSerializers.FLOAT);
private void getDisplayHeight(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getDisplayHeight(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || displayHeight != 0.0F) {
packetSink.accept(displayHeightWatcher, displayHeight);
packetSink.add(displayHeightWatcher, displayHeight);
}
}
@@ -209,9 +204,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Integer> interpolationDelayWatcher = new EntityDataAccessor<>(8, EntityDataSerializers.INT);
private void getInterpolationDelay(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getInterpolationDelay(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || interpolationDelay != 0) {
packetSink.accept(interpolationDelayWatcher, interpolationDelay);
packetSink.add(interpolationDelayWatcher, interpolationDelay);
}
}
@@ -222,9 +217,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Byte> billboardWatcher = new EntityDataAccessor<>(15, EntityDataSerializers.BYTE);
private void getBillboard(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getBillboard(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || billboard != Display.Billboard.FIXED) {
packetSink.accept(billboardWatcher, (byte) billboard.ordinal());
packetSink.add(billboardWatcher, (byte) billboard.ordinal());
}
}
@@ -235,9 +230,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Integer> glowColorOverrideWatcher = new EntityDataAccessor<>(22, EntityDataSerializers.INT);
private void getGlowColorOverride(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getGlowColorOverride(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || glowColorOverride != null) {
packetSink.accept(glowColorOverrideWatcher, glowColorOverride == null ? -1 : glowColorOverride.asARGB());
packetSink.add(glowColorOverrideWatcher, glowColorOverride == null ? -1 : glowColorOverride.asARGB());
}
}
@@ -248,9 +243,9 @@ public abstract class RDisplay extends REntity {
private static final EntityDataAccessor<Integer> brightnessWatcher = new EntityDataAccessor<>(16, EntityDataSerializers.INT);
private void getBrightness(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getBrightness(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || brightness != null) {
packetSink.accept(brightnessWatcher, brightness == null ? -1 : brightness.getBlockLight() << 4 | brightness.getSkyLight() << 20);
packetSink.add(brightnessWatcher, brightness == null ? -1 : brightness.getBlockLight() << 4 | brightness.getSkyLight() << 20);
}
}
}
@@ -20,13 +20,12 @@
package de.steamwar.entity;
import com.mojang.datafixers.util.Pair;
import de.steamwar.Reflection;
import de.steamwar.core.BountifulWrapper;
import de.steamwar.core.FlatteningWrapper;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import lombok.Getter;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.contents.PlainTextContents;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
@@ -44,7 +43,6 @@ import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
public class REntity {
@@ -174,14 +172,10 @@ public class REntity {
server.postEntityMove(this, fromX, fromZ);
}
private static final Class<?> animationPacket = ClientboundAnimatePacket.class;
private static final Reflection.Field<Integer> animationEntity = Reflection.getField(animationPacket, int.class, 5);
private static final Reflection.Field<Integer> animationAnimation = Reflection.getField(animationPacket, int.class, 6);
public void showAnimation(byte animation) {
Object packet = Reflection.newInstance(animationPacket);
animationEntity.set(packet, entityId);
animationAnimation.set(packet, (int) animation);
ClientboundAnimatePacket packet = new ClientboundAnimatePacket();
packet.id = entityId;
packet.action = animation;
server.updateEntity(this, packet);
}
@@ -189,25 +183,21 @@ public class REntity {
server.updateEntity(this, new ClientboundSetEntityMotionPacket(entityId, new Vec3(calcVelocity(dX), calcVelocity(dY), calcVelocity(dZ))));
}
private static final Class<?> statusPacket = ClientboundEntityEventPacket.class;
private static final Reflection.Field<Integer> statusEntity = Reflection.getField(statusPacket, int.class, 0);
private static final Reflection.Field<Byte> statusStatus = Reflection.getField(statusPacket, byte.class, 0);
public void showDamage() {
Object packet = Reflection.newInstance(statusPacket);
statusEntity.set(packet, entityId);
statusStatus.set(packet, (byte) 2);
ClientboundEntityEventPacket packet = new ClientboundEntityEventPacket();
packet.entityId = entityId;
packet.eventId = (byte) 2;
server.updateEntity(this, packet);
}
public void setPose(Pose pose) {
this.pose = pose;
server.updateEntity(this, getDataWatcherPacket(poseDataWatcher, pose));
server.updateEntity(this, entityDataPacket().add(poseDataWatcher, pose).build());
}
public void setOnFire(boolean perma) {
fireTick = perma ? -1 : 21;
server.updateEntity(this, getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
server.updateEntity(this, entityDataPacket().add(entityStatusWatcher, getEntityStatus()).build());
}
public boolean isOnFire() {
@@ -216,20 +206,18 @@ public class REntity {
public void setInvisible(boolean invisible) {
this.invisible = invisible;
server.updateEntity(this, getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
server.updateEntity(this, entityDataPacket().add(entityStatusWatcher, getEntityStatus()).build());
}
public void setBowDrawn(boolean drawn, boolean offHand) {
bowDrawn = drawn;
server.updateEntity(this, getDataWatcherPacket(poseDataWatcher, Pose.SHOOTING));
server.updateEntity(this, entityDataPacket().add(poseDataWatcher, Pose.SHOOTING).build());
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
server.updateEntity(this, getDataWatcherPacket(
nameWatcher, FlatteningWrapper.formatDisplayName(displayName),
nameVisibleWatcher, displayName != null
));
server.updateEntity(this, entityDataPacket().add(nameWatcher, formatDisplayName(displayName))
.add(nameVisibleWatcher, displayName != null).build());
}
public void setItem(Object slot, ItemStack stack) {
@@ -243,22 +231,18 @@ public class REntity {
public void setNoGravity(boolean noGravity) {
this.noGravity = noGravity;
server.updateEntity(this, getDataWatcherPacket(noGravityDataWatcher, noGravity));
server.updateEntity(this, entityDataPacket().add(noGravityDataWatcher, noGravity).build());
}
public void setGlowing(boolean glowing) {
this.isGlowing = glowing;
server.updateEntity(this, getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
server.updateEntity(this, entityDataPacket().add(entityStatusWatcher, getEntityStatus()).build());
}
private static final Function<REntity, Object> spawnPacketGenerator = entitySpawnPacketGenerator(ClientboundAddEntityPacket.class, 2);
private static final Reflection.Field<Integer> additionalData = Reflection.getField(ClientboundAddEntityPacket.class, int.class, 4);
private Object spawnPacketGenerator() {
Object packet = spawnPacketGenerator.apply(this);
additionalData.set(packet, objectData);
return packet;
private ClientboundAddEntityPacket spawnPacketGenerator() {
ResourceLocation key = CraftNamespacedKey.toMinecraft(entityType.getKey());
net.minecraft.world.entity.EntityType<?> entityType = BuiltInRegistries.ENTITY_TYPE.get(key).get().value();
return new ClientboundAddEntityPacket(entityId, uuid, x, y, z, pitch, yaw, entityType, objectData, Vec3.ZERO, 0);
}
void list(Consumer<Object> packetSink) {
@@ -276,20 +260,22 @@ public class REntity {
}
if (pose != Pose.STANDING) {
packetSink.accept(getDataWatcherPacket(poseDataWatcher, pose));
entityDataPacket().add(poseDataWatcher, pose).send(packetSink);
}
byte status = getEntityStatus();
if (status != 0) {
packetSink.accept(getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
entityDataPacket().add(entityStatusWatcher, getEntityStatus()).send(packetSink);
}
if (displayName != null) {
packetSink.accept(getDataWatcherPacket(nameWatcher, FlatteningWrapper.formatDisplayName(displayName), nameVisibleWatcher, true));
entityDataPacket().add(nameWatcher, formatDisplayName(displayName))
.add(nameVisibleWatcher, true)
.send(packetSink);
}
if (noGravity) {
packetSink.accept(getDataWatcherPacket(noGravityDataWatcher, true));
entityDataPacket().add(noGravityDataWatcher, true).send(packetSink);
}
}
@@ -297,7 +283,7 @@ public class REntity {
if (fireTick > 0) {
fireTick--;
if (fireTick == 0) {
server.updateEntity(this, getDataWatcherPacket(entityStatusWatcher, getEntityStatus()));
server.updateEntity(this, entityDataPacket().add(entityStatusWatcher, getEntityStatus()).build());
}
}
}
@@ -328,13 +314,29 @@ public class REntity {
return status;
}
protected Object getDataWatcherPacket(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());
protected EntityDataPacketBuilder entityDataPacket() {
return new EntityDataPacketBuilder();
}
public class EntityDataPacketBuilder {
private List<SynchedEntityData.DataValue<?>> values = new ArrayList<>();
public <T> EntityDataPacketBuilder add(EntityDataAccessor<T> accessor, T value) {
values.add(new SynchedEntityData.DataItem<>(accessor, value).value());
return this;
}
return new ClientboundSetEntityDataPacket(entityId, nativeWatchers);
public boolean isEmpty() {
return values.isEmpty();
}
public ClientboundSetEntityDataPacket build() {
return new ClientboundSetEntityDataPacket(entityId, values);
}
public void send(Consumer<Object> packetSink) {
packetSink.accept(build());
}
}
private Object getTeleportPacket() {
@@ -359,14 +361,10 @@ public class REntity {
}
}
private static final Class<?> headRotationPacket = ClientboundRotateHeadPacket.class;
private static final Reflection.Field<Integer> headRotationEntity = Reflection.getField(headRotationPacket, int.class, 0);
private static final Reflection.Field<Byte> headRotationYaw = Reflection.getField(headRotationPacket, byte.class, 0);
private Object getHeadRotationPacket() {
Object packet = Reflection.newInstance(headRotationPacket);
headRotationEntity.set(packet, entityId);
headRotationYaw.set(packet, headYaw);
ClientboundRotateHeadPacket packet = new ClientboundRotateHeadPacket();
packet.entityId = entityId;
packet.yHeadRot = headYaw;
return packet;
}
@@ -374,33 +372,6 @@ public class REntity {
return new ClientboundSetEquipmentPacket(entityId, Collections.singletonList(Pair.of((EquipmentSlot) slot, CraftItemStack.asNMSCopy(stack))));
}
private static final Reflection.Field<net.minecraft.world.entity.EntityType> spawnType = Reflection.getField(ClientboundAddEntityPacket.class, net.minecraft.world.entity.EntityType.class, 0);
private static Function<REntity, Object> entitySpawnPacketGenerator(Class<?> spawnPacket, int posOffset) {
BountifulWrapper.UUIDSetter uuid = BountifulWrapper.impl.getUUIDSetter(spawnPacket);
Function<REntity, Object> packetGenerator = spawnPacketGenerator(spawnPacket, posOffset);
return entity -> {
Object packet = packetGenerator.apply(entity);
uuid.set(packet, entity.uuid);
ResourceLocation key = CraftNamespacedKey.toMinecraft(entity.entityType.getKey());
spawnType.set(packet, BuiltInRegistries.ENTITY_TYPE.get(key).get().value());
return packet;
};
}
protected static Function<REntity, Object> spawnPacketGenerator(Class<?> spawnPacket, int posOffset) {
Reflection.Field<Integer> entityId = Reflection.getField(spawnPacket, int.class, 0);
BountifulWrapper.PositionSetter position = BountifulWrapper.impl.getPositionSetter(spawnPacket, posOffset);
return entity -> {
Object packet = Reflection.newInstance(spawnPacket);
entityId.set(packet, entity.entityId);
position.set(packet, entity.x, entity.y, entity.z, entity.pitch, entity.yaw);
return packet;
};
}
private byte rotToByte(float rot) {
return (byte) ((int) (rot * 256.0F / 360.0F));
}
@@ -408,4 +379,8 @@ public class REntity {
private int calcVelocity(double value) {
return (int) (Math.max(-3.9, Math.min(value, 3.9)) * 8000);
}
private static Optional<Component> formatDisplayName(String displayName) {
return displayName != null ? Optional.of(MutableComponent.create(PlainTextContents.create(displayName))) : Optional.empty();
}
}
@@ -20,7 +20,6 @@
package de.steamwar.entity;
import de.steamwar.techhider.BlockIds;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Location;
@@ -19,14 +19,13 @@
package de.steamwar.entity;
import de.steamwar.core.BountifulWrapper;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -61,18 +60,13 @@ public class RInteraction extends REntity implements RInteractableEntity<RIntera
}
@SafeVarargs
protected final void sendPacket(Consumer<Object> packetSink, BiConsumer<Boolean, BiConsumer<Object, Object>>... dataSinkSinks) {
List<Object> keyValueData = new ArrayList<>();
protected final void sendPacket(Consumer<Object> packetSink, BiConsumer<Boolean, EntityDataPacketBuilder>... dataSinkSinks) {
EntityDataPacketBuilder builder = entityDataPacket();
boolean ignoreDefault = packetSink == updatePacketSink;
for (BiConsumer<Boolean, BiConsumer<Object, Object>> dataSinkSink : dataSinkSinks) {
dataSinkSink.accept(ignoreDefault, (dataWatcher, value) -> {
keyValueData.add(dataWatcher);
keyValueData.add(value);
});
}
if (!keyValueData.isEmpty()) {
packetSink.accept(getDataWatcherPacket(keyValueData.toArray()));
for (BiConsumer<Boolean, EntityDataPacketBuilder> dataSinkSink : dataSinkSinks) {
dataSinkSink.accept(ignoreDefault, builder);
}
if (!builder.isEmpty()) builder.send(packetSink);
}
public void setInteractionWidth(float interactionWidth) {
@@ -80,11 +74,11 @@ public class RInteraction extends REntity implements RInteractableEntity<RIntera
sendPacket(updatePacketSink, this::getInteractionWidthData);
}
private static final Object interactionWidthWatcher = BountifulWrapper.impl.getDataWatcherObject(8, Float.class);
private static final EntityDataAccessor<Float> interactionWidthWatcher = new EntityDataAccessor<>(8, EntityDataSerializers.FLOAT);
private void getInteractionWidthData(boolean ignoreDefault, BiConsumer<Object, Object> dataSink) {
private void getInteractionWidthData(boolean ignoreDefault, EntityDataPacketBuilder dataSink) {
if (ignoreDefault || interactionWidth != 1.0) {
dataSink.accept(interactionWidthWatcher, interactionWidth);
dataSink.add(interactionWidthWatcher, interactionWidth);
}
}
@@ -93,11 +87,11 @@ public class RInteraction extends REntity implements RInteractableEntity<RIntera
sendPacket(updatePacketSink, this::getInteractionHeightData);
}
private static final Object interactionHeightWatcher = BountifulWrapper.impl.getDataWatcherObject(9, Float.class);
private static final EntityDataAccessor<Float> interactionHeightWatcher = new EntityDataAccessor<>(9, EntityDataSerializers.FLOAT);
private void getInteractionHeightData(boolean ignoreDefault, BiConsumer<Object, Object> dataSink) {
private void getInteractionHeightData(boolean ignoreDefault, EntityDataPacketBuilder dataSink) {
if (ignoreDefault || interactionHeight != 1.0) {
dataSink.accept(interactionHeightWatcher, interactionHeight);
dataSink.add(interactionHeightWatcher, interactionHeight);
}
}
@@ -106,11 +100,11 @@ public class RInteraction extends REntity implements RInteractableEntity<RIntera
sendPacket(updatePacketSink, this::getResponsiveData);
}
private static final Object responsiveWatcher = BountifulWrapper.impl.getDataWatcherObject(10, Boolean.class);
private static final EntityDataAccessor<Boolean> responsiveWatcher = new EntityDataAccessor<>(10, EntityDataSerializers.BOOLEAN);
private void getResponsiveData(boolean ignoreDefault, BiConsumer<Object, Object> dataSink) {
private void getResponsiveData(boolean ignoreDefault, EntityDataPacketBuilder dataSink) {
if (ignoreDefault || !responsive) {
dataSink.accept(responsiveWatcher, responsive);
dataSink.add(responsiveWatcher, responsive);
}
}
}
@@ -63,9 +63,9 @@ public class RItemDisplay extends RDisplay {
private static final EntityDataAccessor<net.minecraft.world.item.ItemStack> itemStackWatcher = new EntityDataAccessor<>(23, EntityDataSerializers.ITEM_STACK);
private void getItemStack(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getItemStack(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || !itemStack.equals(DEFAULT_ITEM_STACK)) {
packetSink.accept(itemStackWatcher, CraftItemStack.asNMSCopy(itemStack));
packetSink.add(itemStackWatcher, CraftItemStack.asNMSCopy(itemStack));
}
}
@@ -76,9 +76,9 @@ public class RItemDisplay extends RDisplay {
sendPacket(updatePacketSink, this::getItemDisplayTransform);
}
private void getItemDisplayTransform(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getItemDisplayTransform(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || itemDisplayTransform != ItemDisplay.ItemDisplayTransform.NONE) {
packetSink.accept(itemDisplayTransformWatcher, (byte) itemDisplayTransform.ordinal());
packetSink.add(itemDisplayTransformWatcher, (byte) itemDisplayTransform.ordinal());
}
}
}
@@ -21,7 +21,6 @@ package de.steamwar.entity;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import de.steamwar.core.BountifulWrapper;
import de.steamwar.core.ProtocolWrapper;
import de.steamwar.network.CoreNetworkHandler;
import de.steamwar.network.NetworkSender;
@@ -29,6 +28,8 @@ import de.steamwar.network.packets.common.PlayerSkinRequestPacket;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.world.phys.Vec3;
import org.bukkit.GameMode;
import org.bukkit.Location;
@@ -42,7 +43,7 @@ import java.util.function.Consumer;
public class RPlayer extends REntity implements RInteractableEntity<RPlayer> {
private static final Object skinPartsDataWatcher = BountifulWrapper.impl.getDataWatcherObject(17, Byte.class);
private static final EntityDataAccessor<Byte> skinPartsDataWatcher = new EntityDataAccessor<>(17, EntityDataSerializers.BYTE);
@Getter
private final UUID actualUUID;
@@ -85,7 +86,7 @@ public class RPlayer extends REntity implements RInteractableEntity<RPlayer> {
@Override
void spawn(Consumer<Object> packetSink) {
packetSink.accept(getNamedSpawnPacket());
packetSink.accept(getDataWatcherPacket(skinPartsDataWatcher, (byte) 0x7F));
entityDataPacket().add(skinPartsDataWatcher, (byte) 0x7F).send(packetSink);
for (Map.Entry<Object, ItemStack> entry : itemSlots.entrySet()) {
packetSink.accept(getEquipmentPacket(entry.getKey(), entry.getValue()));
@@ -77,9 +77,9 @@ public class RTextDisplay extends RDisplay {
private static final EntityDataAccessor<Component> textWatcher = new EntityDataAccessor<>(23, EntityDataSerializers.COMPONENT);
private void getText(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getText(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || !text.isEmpty()) {
packetSink.accept(textWatcher, MutableComponent.create(PlainTextContents.create(text)));
packetSink.add(textWatcher, MutableComponent.create(PlainTextContents.create(text)));
}
}
@@ -90,9 +90,9 @@ public class RTextDisplay extends RDisplay {
private static final EntityDataAccessor<Integer> lineWidthWatcher = new EntityDataAccessor<>(24, EntityDataSerializers.INT);
private void getLineWidth(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getLineWidth(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || lineWidth != 200) {
packetSink.accept(lineWidthWatcher, lineWidth);
packetSink.add(lineWidthWatcher, lineWidth);
}
}
@@ -103,9 +103,9 @@ public class RTextDisplay extends RDisplay {
private static final EntityDataAccessor<Byte> textOpacityWatcher = new EntityDataAccessor<>(26, EntityDataSerializers.BYTE);
private void getTextOpacity(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getTextOpacity(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || textOpacity != (byte) -1) {
packetSink.accept(textOpacityWatcher, textOpacity);
packetSink.add(textOpacityWatcher, textOpacity);
}
}
@@ -126,9 +126,9 @@ public class RTextDisplay extends RDisplay {
private static final EntityDataAccessor<Integer> backgroundColorWatcher = new EntityDataAccessor<>(25, EntityDataSerializers.INT);
private void getBackgroundColor(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getBackgroundColor(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
if (ignoreDefault || backgroundColor != null) {
packetSink.accept(backgroundColorWatcher, backgroundColor);
packetSink.add(backgroundColorWatcher, backgroundColor);
}
}
@@ -146,7 +146,7 @@ public class RTextDisplay extends RDisplay {
private static final EntityDataAccessor<Byte> textStatusWatcher = new EntityDataAccessor<>(27, EntityDataSerializers.BYTE);
private void getTextStatus(boolean ignoreDefault, BiConsumer<Object, Object> packetSink) {
private void getTextStatus(boolean ignoreDefault, EntityDataPacketBuilder packetSink) {
byte status = 0;
if (shadowed) {
@@ -167,7 +167,7 @@ public class RTextDisplay extends RDisplay {
}
if (ignoreDefault || status != 0) {
packetSink.accept(textStatusWatcher, status);
packetSink.add(textStatusWatcher, status);
}
}
}
@@ -19,10 +19,8 @@
package de.steamwar.techhider;
import de.steamwar.Reflection;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.core.SectionPos;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.util.SimpleBitStorage;
@@ -35,13 +33,8 @@ import java.util.List;
import java.util.function.UnaryOperator;
public class ChunkHider {
private static final UnaryOperator<Object> chunkPacketShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class);
private static final UnaryOperator<Object> chunkDataShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class);
private static final Reflection.Field<ClientboundLevelChunkPacketData> levelChunkPacketDataField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkPacketData.class, 0);
private static final Reflection.Field<byte[]> chunkBlockDataField = Reflection.getField(ClientboundLevelChunkPacketData.class, byte[].class, 0);
private static final Reflection.Field<List> chunkBlockEntitiesDataField = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0);
private static final UnaryOperator<ClientboundLevelChunkWithLightPacket> chunkPacketShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new);
private static final UnaryOperator<ClientboundLevelChunkPacketData> chunkDataShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class, ClientboundLevelChunkPacketData::new);
private final int SECTION_SPAN_SIZE = 16;
private final byte BIT_PER_BLOCK_INDIRECTION_LIMIT = 8;
@@ -178,8 +171,8 @@ public class ChunkHider {
byte[] data = new byte[out.readableBytes()];
out.readBytes(data);
List<Object> blockEntities = chunkBlockEntitiesDataField.get(chunkData);
List<Object> filteredBlockEntities = filterBlockEntities(player, blockEntities, chunkX, chunkZ);
List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntities = chunkData.blockEntitiesData;
List<ClientboundLevelChunkPacketData.BlockEntityInfo> filteredBlockEntities = filterBlockEntities(player, blockEntities, chunkX, chunkZ);
return buildNewChunkPacket(packet, data, filteredBlockEntities);
@@ -237,33 +230,24 @@ public class ChunkHider {
return reEncodedData.getRaw();
}
private ClientboundLevelChunkWithLightPacket buildNewChunkPacket(ClientboundLevelChunkWithLightPacket originalPacket, byte[] newBlockDataBuffer, List<Object> newBlockEntities) {
ClientboundLevelChunkWithLightPacket clonedPacket = (ClientboundLevelChunkWithLightPacket) chunkPacketShallowCloner.apply(originalPacket);
ClientboundLevelChunkPacketData clonedPacketChunkData = (ClientboundLevelChunkPacketData) chunkDataShallowCloner.apply(originalPacket.getChunkData());
private ClientboundLevelChunkWithLightPacket buildNewChunkPacket(ClientboundLevelChunkWithLightPacket originalPacket, byte[] newBlockDataBuffer, List<ClientboundLevelChunkPacketData.BlockEntityInfo> newBlockEntities) {
ClientboundLevelChunkWithLightPacket clonedPacket = chunkPacketShallowCloner.apply(originalPacket);
ClientboundLevelChunkPacketData clonedPacketChunkData = chunkDataShallowCloner.apply(originalPacket.getChunkData());
chunkBlockDataField.set(clonedPacketChunkData, newBlockDataBuffer);
chunkBlockEntitiesDataField.set(clonedPacketChunkData, newBlockEntities);
levelChunkPacketDataField.set(clonedPacket, clonedPacketChunkData);
clonedPacketChunkData.buffer = newBlockDataBuffer;
clonedPacketChunkData.blockEntitiesData = newBlockEntities;
clonedPacket.chunkData = clonedPacketChunkData;
return clonedPacket;
}
private static final Class<?> blockEntitiyInfoClass = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo");
private static final Reflection.Field<BlockEntityType> blockEntityInfoTypeField = Reflection.getField(blockEntitiyInfoClass, BlockEntityType.class, 0);
private static final Reflection.Field<Integer> packedXZField = Reflection.getField(blockEntitiyInfoClass, int.class, 0);
private static final Reflection.Field<Integer> yField = Reflection.getField(blockEntitiyInfoClass, int.class, 1);
private List<Object> filterBlockEntities(Player player, List<Object> blockEntities, int chunkX, int chunkZ) {
private List<ClientboundLevelChunkPacketData.BlockEntityInfo> filterBlockEntities(Player player, List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntities, int chunkX, int chunkZ) {
int fourBitBitmask = 0b0000_1111;
return blockEntities.stream()
.filter((blockEntityInfo) -> {
BlockEntityType<?> type = blockEntityInfoTypeField.get(blockEntityInfo);
int packedXZ = packedXZField.get(blockEntityInfo);
BlockEntityType<?> type = blockEntityInfo.type;
int packedXZ = blockEntityInfo.packedXZ;
int localX = (packedXZ >> 4) & fourBitBitmask;
int localZ = packedXZ & fourBitBitmask;
@@ -271,7 +255,7 @@ public class ChunkHider {
int worldX = (chunkX * SECTION_SPAN_SIZE) + localX;
int worldZ = (chunkZ * SECTION_SPAN_SIZE) + localZ;
int worldY = yField.get(blockEntityInfo);
int worldY = blockEntityInfo.y;
return accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, worldX, worldY, worldZ) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlockEntity(player, worldX, worldY, worldZ, type);
}).toList();
@@ -19,64 +19,37 @@
package de.steamwar.techhider;
import com.google.common.primitives.Bytes;
import de.steamwar.Reflection;
import io.netty.buffer.ByteBuf;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
public class ProtocolUtils {
private ProtocolUtils() {
}
@Deprecated
public static BiFunction<Object, UnaryOperator<Object>, Object> arrayCloneGenerator(Class<?> elementClass) {
return (array, worker) -> {
int length = Array.getLength(array);
Object result = Array.newInstance(elementClass, length);
for (int i = 0; i < length; i++) {
Array.set(result, i, worker.apply(Array.get(array, i)));
}
return result;
};
}
public static UnaryOperator<Object> shallowCloneGenerator(Class<?> clazz) {
BiConsumer<Object, Object> filler = shallowFill(clazz);
public static <T> UnaryOperator<T> shallowCloneGenerator(Class<T> clazz, Supplier<T> supplier) {
BiConsumer<T, T> filler = shallowFill(clazz);
return source -> {
Object clone = Reflection.newInstance(clazz);
T clone = supplier.get();
filler.accept(source, clone);
return clone;
};
}
public static <T> UnaryOperator<T> shallowTypedCloneGenerator(Class<T> clazz) {
BiConsumer<Object, Object> filler = shallowFill(clazz);
return source -> {
Object clone = Reflection.newInstance(clazz);
filler.accept(source, clone);
return (T) clone;
};
}
private static BiConsumer<Object, Object> shallowFill(Class<?> clazz) {
private static <T> BiConsumer<T, T> shallowFill(Class<T> clazz) {
if (clazz == null) {
return (source, clone) -> {
};
}
BiConsumer<Object, Object> superFiller = shallowFill(clazz.getSuperclass());
BiConsumer superFiller = shallowFill(clazz.getSuperclass());
Field[] fds = clazz.getDeclaredFields();
List<Field> fields = new ArrayList<>();
@@ -106,25 +79,6 @@ public class ProtocolUtils {
return chunk;
}
@Deprecated
public static int readVarInt(byte[] array, int startPos) {
int numRead = 0;
int result = 0;
byte read;
do {
read = array[startPos + numRead];
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 5) {
break;
}
} while ((read & 0b10000000) != 0);
return result;
}
public static int readVarInt(ByteBuf buf) {
int numRead = 0;
int result = 0;
@@ -167,53 +121,4 @@ public class ProtocolUtils {
writeVarInt(buf, varInt);
}
}
@Deprecated
public static int readVarIntLength(byte[] array, int startPos) {
int numRead = 0;
byte read;
do {
read = array[startPos + numRead];
numRead++;
if (numRead > 5) {
break;
}
} while ((read & 0b10000000) != 0);
return numRead;
}
@Deprecated
public static byte[] writeVarInt(int value) {
List<Byte> buffer = new ArrayList<>(5);
do {
byte temp = (byte) (value & 0b01111111);
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
buffer.add(temp);
} while (value != 0);
return Bytes.toArray(buffer);
}
@Deprecated
public static class ChunkPos {
final int x;
final int z;
public ChunkPos(int x, int z) {
this.x = x;
this.z = z;
}
public final int x() {
return x;
}
public final int z() {
return z;
}
}
}
@@ -20,7 +20,6 @@
package de.steamwar.techhider;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.shorts.ShortArraySet;
@@ -364,24 +363,16 @@ public class TechHider {
};
}
private final Reflection.Field<Integer> moveEntityPacketEntityIdField = Reflection.getField(ClientboundMoveEntityPacket.class, int.class, 0);
private Packet<?> processMoveEntityPacket(Player player, ClientboundMoveEntityPacket packet) {
int entityId = moveEntityPacketEntityIdField.get(packet);
if (privilegeProvider.isPlayerPrivilegedToAccessEntity(player, entityId)) {
if (privilegeProvider.isPlayerPrivilegedToAccessEntity(player, packet.entityId)) {
return packet;
} else {
return null;
}
}
private final Reflection.Field<Integer> rotateHeadPacketEntityIdField = Reflection.getField(ClientboundRotateHeadPacket.class, int.class, 0);
private Packet<?> processRotateHeadPacket(Player player, ClientboundRotateHeadPacket packet) {
int entityId = rotateHeadPacketEntityIdField.get(packet);
if (privilegeProvider.isPlayerPrivilegedToAccessEntity(player, entityId)) {
if (privilegeProvider.isPlayerPrivilegedToAccessEntity(player, packet.entityId)) {
return packet;
} else {
return null;
@@ -463,14 +454,10 @@ public class TechHider {
}
}
private final Reflection.Field<SectionPos> sectionPosField = Reflection.getField(ClientboundSectionBlocksUpdatePacket.class, SectionPos.class, 0);
private final Reflection.Field<short[]> oldPosField = Reflection.getField(ClientboundSectionBlocksUpdatePacket.class, short[].class, 0);
private final Reflection.Field<BlockState[]> oldStatesField = Reflection.getField(ClientboundSectionBlocksUpdatePacket.class, BlockState[].class, 0);
private ClientboundSectionBlocksUpdatePacket processSectionUpdate(Player p, ClientboundSectionBlocksUpdatePacket packet) {
SectionPos sectionPos = sectionPosField.get(packet);
short[] oldPos = oldPosField.get(packet);
BlockState[] oldStates = oldStatesField.get(packet);
SectionPos sectionPos = packet.sectionPos;
short[] oldPos = packet.positions;
BlockState[] oldStates = packet.states;
List<Short> filteredPos = new ArrayList<>(oldPos.length);
List<BlockState> filteredStates = new ArrayList<>(oldStates.length);
@@ -19,22 +19,18 @@
package de.steamwar.techhider.legacy;
import de.steamwar.Reflection;
import de.steamwar.techhider.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.resources.ResourceLocation;
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;
@@ -44,35 +40,26 @@ import java.util.stream.Collectors;
public class ChunkHider {
public static final ChunkHider impl = new ChunkHider();
public Class<?> mapChunkPacket() {
return ClientboundLevelChunkWithLightPacket.class;
}
private static final UnaryOperator<ClientboundLevelChunkWithLightPacket> chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new);
private static final UnaryOperator<ClientboundLevelChunkPacketData> chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class, ClientboundLevelChunkPacketData::new);
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) {
public BiFunction<Player, ClientboundLevelChunkWithLightPacket, ClientboundLevelChunkWithLightPacket> chunkHiderGenerator(TechHider techHider) {
return (p, packet) -> {
int chunkX = chunkXField.get(packet);
int chunkZ = chunkZField.get(packet);
int chunkX = packet.getX();
int chunkZ = packet.getZ();
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ)) {
return packet;
}
packet = chunkPacketCloner.apply(packet);
Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet));
ClientboundLevelChunkPacketData dataWrapper = chunkDataCloner.apply(packet.getChunkData());
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
tileEntities.set(dataWrapper, ((List<?>) tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList()));
dataWrapper.blockEntitiesData = dataWrapper.blockEntitiesData.stream()
.filter(te -> tileEntityVisible(hiddenBlockEntities, te))
.collect(Collectors.toList());
ByteBuf in = Unpooled.wrappedBuffer(dataField.get(dataWrapper));
ByteBuf in = Unpooled.wrappedBuffer(dataWrapper.buffer);
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);
@@ -88,21 +75,16 @@ public class ChunkHider {
byte[] data = new byte[out.readableBytes()];
out.readBytes(data);
dataField.set(dataWrapper, data);
dataWrapper.buffer = data;
chunkData.set(packet, dataWrapper);
packet.chunkData = dataWrapper;
return packet;
};
}
private static final Registry<BlockEntityType<?>> registry = Reflection.getField(BuiltInRegistries.class, "BLOCK_ENTITY_TYPE", Registry.class).get(null);
private static final Reflection.Method getKey = Reflection.getTypedMethod(Reflection.getClass("net.minecraft.core.Registry"), "getKey", ResourceLocation.class, Object.class);
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);
protected boolean tileEntityVisible(Set<String> hiddenBlockEntities, Object tile) {
BlockEntityType type = entityType.get(tile);
String path = ((ResourceLocation) getKey.invoke(registry, type)).getPath();
protected boolean tileEntityVisible(Set<String> hiddenBlockEntities, ClientboundLevelChunkPacketData.BlockEntityInfo tile) {
BlockEntityType<?> type = tile.type;
String path = BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(type).getPath();
return !hiddenBlockEntities.contains(path);
}
@@ -19,10 +19,8 @@
package de.steamwar.techhider.legacy;
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.network.protocol.game.ClientboundSectionBlocksUpdatePacket;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.entity.Player;
@@ -33,24 +31,20 @@ import java.util.function.BiFunction;
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) {
public BiFunction<Player, ClientboundSectionBlocksUpdatePacket, ClientboundSectionBlocksUpdatePacket> 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);
SectionPos chunkCoords = packet.sectionPos;
int chunkX = chunkCoords.getX();
int chunkY = chunkCoords.getY();
int chunkZ = chunkCoords.getZ();
if (locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ)) {
return packet;
}
packet = TechHider.multiBlockChangeCloner.apply(packet);
final short[] oldPos = multiBlockChangePos.get(packet);
final BlockState[] oldBlocks = multiBlockChangeBlocks.get(packet);
final short[] oldPos = packet.positions;
final BlockState[] oldBlocks = packet.states;
ArrayList<Short> poss = new ArrayList<>(oldPos.length);
ArrayList<BlockState> blocks = new ArrayList<>(oldPos.length);
for (int i = 0; i < oldPos.length; i++) {
@@ -77,16 +71,9 @@ public class ProtocolWrapper {
newPos[i] = poss.get(i);
}
multiBlockChangePos.set(packet, newPos);
multiBlockChangeBlocks.set(packet, blocks.toArray(new BlockState[0]));
packet.positions = newPos;
packet.states = blocks.toArray(BlockState[]::new);
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;
}
}
@@ -20,7 +20,6 @@
package de.steamwar.techhider.legacy;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import de.steamwar.techhider.BlockIds;
import de.steamwar.techhider.ProtocolUtils;
import lombok.Getter;
@@ -28,6 +27,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.network.protocol.game.*;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Material;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
@@ -37,7 +37,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
@@ -45,10 +44,6 @@ import java.util.stream.Collectors;
public class TechHider {
public static final Class<?> blockPosition = BlockPos.class;
private static final Class<?> baseBlockPosition = Vec3i.class;
public static final Reflection.Field<Integer> blockPositionX = Reflection.getField(baseBlockPosition, int.class, 0);
public static final Reflection.Field<Integer> blockPositionY = Reflection.getField(baseBlockPosition, int.class, 1);
public static final Reflection.Field<Integer> blockPositionZ = Reflection.getField(baseBlockPosition, int.class, 2);
public static final Class<?> iBlockData = BlockState.class;
public static final Class<?> block = Block.class;
@@ -79,11 +74,11 @@ public class TechHider {
this.obfuscationTarget = CraftMagicNumbers.getBlock(obfuscationTarget).defaultBlockState();
this.obfuscationTargetId = BlockIds.impl.materialToId(obfuscationTarget);
techhiders.put(blockActionPacket, this::blockActionHider);
techhiders.put(blockChangePacket, this::blockChangeHider);
techhiders.put(tileEntityDataPacket, this::tileEntityDataHider);
techhiders.put(multiBlockChangePacket, ProtocolWrapper.impl.multiBlockChangeGenerator(this));
techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(this));
techhiders.put(ClientboundBlockEventPacket.class, (player, o) -> this.blockActionHider(player, (ClientboundBlockEventPacket) o));
techhiders.put(ClientboundBlockUpdatePacket.class, (player, o) -> this.blockChangeHider(player, (ClientboundBlockUpdatePacket) o));
techhiders.put(ClientboundBlockEntityDataPacket.class, (player, o) -> this.tileEntityDataHider(player, (ClientboundBlockEntityDataPacket) o));
techhiders.put(ClientboundSectionBlocksUpdatePacket.class, (BiFunction) ProtocolWrapper.impl.multiBlockChangeGenerator(this));
techhiders.put(ClientboundLevelChunkWithLightPacket.class, (BiFunction) ChunkHider.impl.chunkHiderGenerator(this));
techhiders.put(ServerboundUseItemOnPacket.class, (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet);
techhiders.put(ServerboundInteractPacket.class, (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet);
@@ -97,53 +92,43 @@ public class TechHider {
techhiders.forEach(TinyProtocol.instance::removeFilter);
}
public static final Class<?> multiBlockChangePacket = ClientboundSectionBlocksUpdatePacket.class;
public static final UnaryOperator<Object> multiBlockChangeCloner = ProtocolUtils.shallowCloneGenerator(TechHider.multiBlockChangePacket);
public static final UnaryOperator<ClientboundSectionBlocksUpdatePacket> multiBlockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new);
private static final Class<?> blockChangePacket = ClientboundBlockUpdatePacket.class;
private static final Function<Object, Object> blockChangeCloner = ProtocolUtils.shallowCloneGenerator(blockChangePacket);
private static final Reflection.Field<?> blockChangePosition = Reflection.getField(blockChangePacket, blockPosition, 0);
private static final Reflection.Field<?> blockChangeBlockData = Reflection.getField(blockChangePacket, iBlockData, 0);
private static final UnaryOperator<ClientboundBlockUpdatePacket> blockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new);
private Object blockChangeHider(Player p, Object packet) {
switch (locationEvaluator.checkBlockPos(p, blockChangePosition.get(packet))) {
private ClientboundBlockUpdatePacket blockChangeHider(Player p, ClientboundBlockUpdatePacket packet) {
switch (locationEvaluator.checkBlockPos(p, packet.getPos())) {
case SKIP:
return packet;
case CHECK:
if (!iBlockDataHidden((BlockState) blockChangeBlockData.get(packet))) {
if (!iBlockDataHidden(packet.blockState)) {
return packet;
}
case HIDE:
packet = blockChangeCloner.apply(packet);
blockChangeBlockData.set(packet, obfuscationTarget);
packet.blockState = (BlockState) obfuscationTarget;
return packet;
case HIDE_AIR:
default:
packet = blockChangeCloner.apply(packet);
blockChangeBlockData.set(packet, AIR);
packet.blockState = (BlockState) AIR;
return packet;
}
}
private static final Class<?> blockActionPacket = ClientboundBlockEventPacket.class;
private static final Reflection.Field<?> blockActionPosition = Reflection.getField(blockActionPacket, blockPosition, 0);
private Object blockActionHider(Player p, Object packet) {
if (locationEvaluator.checkBlockPos(p, blockActionPosition.get(packet)) == State.SKIP) {
private Object blockActionHider(Player p, ClientboundBlockEventPacket packet) {
if (locationEvaluator.checkBlockPos(p, packet.getPos()) == State.SKIP) {
return packet;
}
return null;
}
public static final Class<?> tileEntityDataPacket = ClientboundBlockEntityDataPacket.class;
private static final Reflection.Field<?> tileEntityDataPosition = Reflection.getField(tileEntityDataPacket, blockPosition, 0);
private Object tileEntityDataHider(Player p, Object packet) {
switch (locationEvaluator.checkBlockPos(p, tileEntityDataPosition.get(packet))) {
private ClientboundBlockEntityDataPacket tileEntityDataHider(Player p, ClientboundBlockEntityDataPacket packet) {
switch (locationEvaluator.checkBlockPos(p, packet.getPos())) {
case SKIP:
return packet;
case CHECK:
if (ProtocolWrapper.impl.unfilteredTileEntityDataAction(packet)) {
if (packet.getType() != BlockEntityType.SIGN) {
return packet;
}
default:
@@ -173,8 +158,8 @@ public class TechHider {
return skipChunkSection(player, ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(y), ProtocolUtils.posToChunk(z)) ? State.SKIP : State.CHECK;
}
default State checkBlockPos(Player player, Object pos) {
return check(player, blockPositionX.get(pos), blockPositionY.get(pos), blockPositionZ.get(pos));
default State checkBlockPos(Player player, Vec3i pos) {
return check(player, pos.getX(), pos.getY(), pos.getZ());
}
default boolean blockPrecise(Player player, int x, int y, int z) {
@@ -0,0 +1,71 @@
accessWidener v2 named
# For TinyProtocol and CheckpointUtilsJ9
accessible field net/minecraft/server/network/ServerConnectionListener channels Ljava/util/List;
# For ErrorHandler
accessible field org/spigotmc/WatchdogThread instance Lorg/spigotmc/WatchdogThread;
# For ResourceKey
accessible method net/minecraft/resources/ResourceKey <init> (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceLocation;)V
accessible method net/minecraft/resources/ResourceLocation <init> (Ljava/lang/String;Ljava/lang/String;)V
# For SteamwarGameProfileRepository
accessible field net/minecraft/server/MinecraftServer services Lnet/minecraft/server/Services;
mutable field net/minecraft/server/MinecraftServer services Lnet/minecraft/server/Services;
# REntity
## transitive-extendable means that a public no args constructor is added without any super initialization
transitive-extendable class net/minecraft/network/protocol/game/ClientboundAnimatePacket
accessible field net/minecraft/network/protocol/game/ClientboundAnimatePacket id I
mutable field net/minecraft/network/protocol/game/ClientboundAnimatePacket id I
accessible field net/minecraft/network/protocol/game/ClientboundAnimatePacket action I
mutable field net/minecraft/network/protocol/game/ClientboundAnimatePacket action I
## transitive-extendable means that a public no args constructor is added without any super initialization
transitive-extendable class net/minecraft/network/protocol/game/ClientboundEntityEventPacket
accessible field net/minecraft/network/protocol/game/ClientboundEntityEventPacket entityId I
mutable field net/minecraft/network/protocol/game/ClientboundEntityEventPacket entityId I
accessible field net/minecraft/network/protocol/game/ClientboundEntityEventPacket eventId B
mutable field net/minecraft/network/protocol/game/ClientboundEntityEventPacket eventId B
## transitive-extendable means that a public no args constructor is added without any super initialization
transitive-extendable class net/minecraft/network/protocol/game/ClientboundRotateHeadPacket
accessible field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket yHeadRot B
mutable field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket yHeadRot B
## + TechHider
accessible field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket entityId I
mutable field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket entityId I
# For ChunkHider
## transitive-extendable means that a public no args constructor is added without any super initialization
transitive-extendable class net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket chunkData Lnet/minecraft/network/protocol/game/ClientboundLevelChunkPacketData;
mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket chunkData Lnet/minecraft/network/protocol/game/ClientboundLevelChunkPacketData;
## transitive-extendable means that a public no args constructor is added without any super initialization
transitive-extendable class net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData buffer [B
mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData buffer [B
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData blockEntitiesData Ljava/util/List;
mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData blockEntitiesData Ljava/util/List;
accessible class net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo type Lnet/minecraft/world/level/block/entity/BlockEntityType;
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo packedXZ I
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo y I
# For TechHider
accessible field net/minecraft/network/protocol/game/ClientboundMoveEntityPacket entityId I
## transitive-extendable means that a public no args constructor is added without any super initialization
transitive-extendable class net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket
accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket sectionPos Lnet/minecraft/core/SectionPos;
accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket positions [S
mutable field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket positions [S
accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket states [Lnet/minecraft/world/level/block/state/BlockState;
mutable field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket states [Lnet/minecraft/world/level/block/state/BlockState;
# For legacy/TechHider
## transitive-extendable means that a public no args constructor is added without any super initialization
transitive-extendable class net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket
mutable field net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket blockState Lnet/minecraft/world/level/block/state/BlockState;
@@ -63,7 +63,7 @@ public abstract class Node {
nodes.forEach(consumer);
}
public abstract ProcessBuilder startServer(String serverJar, File directory, String worldDir, String levelName, int port, String... dParams);
public abstract ProcessBuilder startServer(ServerVersion version, File directory, String worldDir, String levelName, int port, String... dParams);
protected abstract ProcessBuilder prepareExecution(String... command);
@@ -97,7 +97,8 @@ public abstract class Node {
return hostname;
}
protected void constructServerstart(File directory, List<String> cmd, String serverJar, String worldDir, String levelName, int port, String... dParams) {
protected void constructServerstart(File directory, List<String> cmd, ServerVersion version, String worldDir, String levelName, int port, String... dParams) {
String serverJar = version.getServerJar();
if (JAVA_8.contains(serverJar)) {
cmd.add("/usr/lib/jvm/openj9-8/bin/java");
} else {
@@ -107,6 +108,10 @@ public abstract class Node {
for (String param : dParams) {
cmd.add("-D" + param);
}
if (version.isExtendedStartup()) {
cmd.add("-Dpaper.disablePluginRemapping=true");
cmd.add("-javaagent:/jars/AccessWidener.jar=start");
}
cmd.add("-Xshareclasses:nonfatal,name=" + directory.getName());
cmd.add("-Xmx768M");
cmd.addAll(OPENJ9_ARGS);
@@ -145,9 +150,9 @@ public abstract class Node {
}
@Override
public ProcessBuilder startServer(String serverJar, File directory, String worldDir, String levelName, int port, String... dParams) {
public ProcessBuilder startServer(ServerVersion version, File directory, String worldDir, String levelName, int port, String... dParams) {
List<String> cmd = new ArrayList<>();
constructServerstart(directory, cmd, serverJar, worldDir, levelName, port, dParams);
constructServerstart(directory, cmd, version, worldDir, levelName, port, dParams);
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.directory(directory);
return builder;
@@ -177,7 +182,7 @@ public abstract class Node {
}
@Override
public ProcessBuilder startServer(String serverJar, File directory, String worldDir, String levelName, int port, String... dParams) {
public ProcessBuilder startServer(ServerVersion version, File directory, String worldDir, String levelName, int port, String... dParams) {
List<String> cmd = new ArrayList<>();
cmd.add("ssh");
cmd.add("-L");
@@ -186,7 +191,7 @@ public abstract class Node {
cmd.add("cd");
cmd.add(directory.getPath());
cmd.add(";");
constructServerstart(directory, cmd, serverJar, worldDir, levelName, port, dParams);
constructServerstart(directory, cmd, version, worldDir, levelName, port, dParams);
return new ProcessBuilder(cmd);
}
@@ -325,7 +325,7 @@ public class ServerStarter {
private void regularStart(String serverName, int port) {
postStart(constructor.construct(serverName, port, node.startServer(
version.getServerJar(), directory, worldDir, worldName, port, arguments.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).toArray(String[]::new)
version, directory, worldDir, worldName, port, arguments.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).toArray(String[]::new)
), worldCleanup, null));
}
@@ -23,6 +23,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
import de.steamwar.sql.GameModeConfig;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.io.File;
import java.util.HashMap;
@@ -33,6 +34,7 @@ import java.util.regex.Pattern;
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum ServerVersion {
SPIGOT_8("spigot-1.8.8.jar", 8, ProtocolVersion.MINECRAFT_1_8),
SPIGOT_9("spigot-1.9.4.jar", 9, ProtocolVersion.MINECRAFT_1_9),
@@ -47,7 +49,7 @@ public enum ServerVersion {
PAPER_18("paper-1.18.2.jar", 15, ProtocolVersion.MINECRAFT_1_18_2),
PAPER_19("paper-1.19.3.jar", 19, ProtocolVersion.MINECRAFT_1_19_3),
PAPER_20("paper-1.20.1.jar", 20, ProtocolVersion.MINECRAFT_1_20),
PAPER_21("paper-1.21.6.jar", 21, ProtocolVersion.MINECRAFT_1_21_6);
PAPER_21("paper-1.21.6.jar", 21, ProtocolVersion.MINECRAFT_1_21_6, true);
private static final Map<String, ServerVersion> chatMap = new HashMap<>();
@@ -104,6 +106,10 @@ public enum ServerVersion {
private final String serverJar;
private final int versionSuffix;
private final ProtocolVersion protocolVersion;
/**
* Adding AccessWidener agent and setting System Property (paper.disablePluginRemapping) to true
*/
private boolean extendedStartup;
public String getWorldFolder(String base) {
return base + versionSuffix + "/";
@@ -22,7 +22,6 @@ package de.steamwar.velocitycore.discord;
import de.steamwar.command.SWCommand;
import de.steamwar.messages.Chatter;
import de.steamwar.sql.Event;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.discord.channels.*;
import de.steamwar.velocitycore.discord.listeners.ChannelListener;
@@ -53,12 +52,12 @@ import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import java.awt.*;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class DiscordBot {
public static final String ARGUMENT_NAME = "arguments";

Some files were not shown because too many files have changed in this diff Show More