Skip to content

Commit a771395

Browse files
committed
feat: the start of the full plugin support
1 parent 0530880 commit a771395

36 files changed

Lines changed: 146045 additions & 67289 deletions

projects/magma/build.gradle

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ dependencies {
137137
implementation(jarJar(project(":neoforge-coremods")))
138138

139139
// Magma - Bukkit
140-
libraries "org.magmafoundation:SpigotToNeoForgeLibs:1.0.0"
140+
libraries "org.magmafoundation:SpigotToNeoForgeLibs:1.0.5"
141141
libraries 'org.apache.maven:maven-resolver-provider:3.9.6'
142142
libraries 'org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18'
143143
libraries ('org.apache.maven.resolver:maven-resolver-transport-http:1.9.18') {
@@ -153,6 +153,12 @@ dependencies {
153153

154154
// Magma - Spigot
155155
libraries 'net.md-5:bungeecord-chat:1.20-R0.2'
156+
libraries('net.md-5:SpecialSource:1.11.2') {
157+
exclude group: 'com.opencsv'
158+
}
159+
160+
// Magma
161+
libraries 'io.izzel:tools:1.3.0'
156162
}
157163

158164
tasks.register('generateMagmaLibs', dev.vankka.dependencydownload.task.GenerateDependencyDownloadResourceTask) {

src/main/java/org/bukkit/craftbukkit/util/ApiVersion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public final class ApiVersion implements Comparable<ApiVersion>, Serializable {
1515

1616
static {
1717
versions = new HashMap<>();
18-
CURRENT = getOrCreateVersion("1.21");
18+
CURRENT = getOrCreateVersion("1.21.1");
1919
FLATTENING = getOrCreateVersion("1.13");
2020
FIELD_NAME_PARITY = getOrCreateVersion("1.20.5");
2121
NONE = getOrCreateVersion("none");

src/main/java/org/bukkit/craftbukkit/util/Versioning.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
public final class Versioning {
44
public static String getBukkitVersion() {
5-
return "1.21-R0.1-SNAPSHOT";
5+
return "1.21.1-R0.1-SNAPSHOT";
66
}
77
}

src/main/java/org/bukkit/plugin/java/PluginClassLoader.java

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.common.base.Preconditions;
44
import com.google.common.io.ByteStreams;
5+
import io.izzel.tools.product.Product2;
56
import java.io.File;
67
import java.io.IOException;
78
import java.io.InputStream;
@@ -10,28 +11,33 @@
1011
import java.net.MalformedURLException;
1112
import java.net.URL;
1213
import java.net.URLClassLoader;
13-
import java.security.CodeSigner;
14+
import java.net.URLConnection;
1415
import java.security.CodeSource;
1516
import java.util.Collection;
1617
import java.util.Collections;
1718
import java.util.Enumeration;
1819
import java.util.Map;
1920
import java.util.Set;
21+
import java.util.concurrent.Callable;
2022
import java.util.concurrent.ConcurrentHashMap;
21-
import java.util.jar.JarEntry;
2223
import java.util.jar.JarFile;
2324
import java.util.jar.Manifest;
2425
import java.util.logging.Level;
26+
import org.bukkit.Bukkit;
2527
import org.bukkit.plugin.InvalidPluginException;
2628
import org.bukkit.plugin.PluginDescriptionFile;
2729
import org.bukkit.plugin.SimplePluginManager;
2830
import org.jetbrains.annotations.NotNull;
2931
import org.jetbrains.annotations.Nullable;
32+
import org.magmafoundation.magma.asm.SwitchTableFixer;
33+
import org.magmafoundation.magma.remapping.ClassLoaderRemapper;
34+
import org.magmafoundation.magma.remapping.MagmaRemapper;
35+
import org.magmafoundation.magma.remapping.loaders.RemappingClassLoader;
3036

3137
/**
3238
* A ClassLoader for plugins, to allow shared classes across multiple plugins
3339
*/
34-
final class PluginClassLoader extends URLClassLoader {
40+
final class PluginClassLoader extends URLClassLoader implements RemappingClassLoader {
3541
private final JavaPluginLoader loader;
3642
private final Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>();
3743
private final PluginDescriptionFile description;
@@ -50,6 +56,18 @@ final class PluginClassLoader extends URLClassLoader {
5056
ClassLoader.registerAsParallelCapable();
5157
}
5258

59+
// Magma start
60+
private ClassLoaderRemapper remapper;
61+
62+
@Override
63+
public ClassLoaderRemapper getRemapper() {
64+
if (remapper == null) {
65+
remapper = MagmaRemapper.createClassLoaderRemapper(this);
66+
}
67+
return remapper;
68+
}
69+
// Magma end
70+
5371
PluginClassLoader(@NotNull final JavaPluginLoader loader, @Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader) throws IOException, InvalidPluginException, MalformedURLException {
5472
super(new URL[] { file.toURI().toURL() }, parent);
5573
Preconditions.checkArgument(loader != null, "Loader cannot be null");
@@ -167,26 +185,36 @@ protected Class<?> findClass(String name) throws ClassNotFoundException {
167185

168186
if (result == null) {
169187
String path = name.replace('.', '/').concat(".class");
170-
JarEntry entry = jar.getJarEntry(path);
171-
172-
if (entry != null) {
173-
byte[] classBytes;
174-
175-
try (InputStream is = jar.getInputStream(entry)) {
176-
classBytes = ByteStreams.toByteArray(is);
177-
} catch (IOException ex) {
178-
throw new ClassNotFoundException(name, ex);
188+
URL url = this.findResource(path);
189+
190+
if (url != null) {
191+
192+
URLConnection connection;
193+
Callable<byte[]> byteSource;
194+
try {
195+
connection = url.openConnection();
196+
connection.connect();
197+
byteSource = () -> {
198+
try (InputStream is = connection.getInputStream()) {
199+
byte[] classBytes = ByteStreams.toByteArray(is);
200+
classBytes = SwitchTableFixer.INSTANCE.apply(classBytes);
201+
classBytes = Bukkit.getUnsafe().processClass(description, path, classBytes);
202+
return classBytes;
203+
}
204+
};
205+
} catch (IOException e) {
206+
throw new ClassNotFoundException(name, e);
179207
}
180208

181-
classBytes = loader.server.getUnsafe().processClass(description, path, classBytes);
209+
Product2<byte[], CodeSource> classBytes = this.getRemapper().remapClass(name, byteSource, connection);
182210

183211
int dot = name.lastIndexOf('.');
184212
if (dot != -1) {
185213
String pkgName = name.substring(0, dot);
186214
if (getPackage(pkgName) == null) {
187215
try {
188216
if (manifest != null) {
189-
definePackage(pkgName, manifest, url);
217+
definePackage(pkgName, manifest, this.url);
190218
} else {
191219
definePackage(pkgName, null, null, null, null, null, null, null);
192220
}
@@ -198,10 +226,7 @@ protected Class<?> findClass(String name) throws ClassNotFoundException {
198226
}
199227
}
200228

201-
CodeSigner[] signers = entry.getCodeSigners();
202-
CodeSource source = new CodeSource(url, signers);
203-
204-
result = defineClass(name, classBytes, 0, classBytes.length, source);
229+
result = defineClass(name, classBytes._1, 0, classBytes._1.length, classBytes._2);
205230
}
206231

207232
if (result == null) {

src/main/java/org/magmafoundation/magma/Magma.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import org.apache.logging.log4j.Logger;
55

66
public class Magma {
7-
private static final Logger LOGGER = LogManager.getLogger();
7+
public static final Logger LOGGER = LogManager.getLogger();
88

99
private static String version = "";
10+
private static final String BUKKIT_VERSION = "v1_21_R1";
1011

1112
static {
1213
version = Magma.class.getPackage().getImplementationVersion();
@@ -19,4 +20,8 @@ public static String getVersion() {
1920
public static Logger getLogger() {
2021
return LOGGER;
2122
}
23+
24+
public static String getBukkitVersion() {
25+
return BUKKIT_VERSION;
26+
}
2227
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.magmafoundation.magma.asm;
2+
3+
import java.lang.reflect.Modifier;
4+
import java.util.Set;
5+
import org.objectweb.asm.Opcodes;
6+
import org.objectweb.asm.tree.ClassNode;
7+
import org.objectweb.asm.tree.FieldNode;
8+
9+
/**
10+
* EnumDefinalizer
11+
*
12+
* @author Mainly by IzzelAliz and modified by Hex
13+
* @originalClassName EnumDefinalizer
14+
* @classFrom <a href="https://github.com/IzzelAliz/Arclight/blob/FeudalKings/bootstrap/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java">Click here to get to github</a>
15+
* <p>
16+
* This classes is modified by Magma to support the Magma software.
17+
*/
18+
public class EnumDefinalizer implements Implementer {
19+
static final Set<String> ENUM = Set.of(
20+
"org/bukkit/Material",
21+
"org/bukkit/potion/PotionType",
22+
"org/bukkit/entity/EntityType",
23+
"org/bukkit/block/Biome",
24+
"org/bukkit/Art",
25+
"org/bukkit/Statistic",
26+
"org/bukkit/inventory/CreativeCategory",
27+
"org/bukkit/entity/SpawnCategory",
28+
"org/bukkit/entity/EnderDragon$Phase",
29+
"org/bukkit/inventory/recipe/CookingBookCategory",
30+
"org/bukkit/Fluid",
31+
"org/bukkit/entity/Spellcaster$Spell",
32+
"org/bukkit/entity/Pose");
33+
34+
@Override
35+
public boolean processClass(ClassNode node) {
36+
if (ENUM.contains(node.name)) {
37+
var find = false;
38+
for (FieldNode field : node.fields) {
39+
if (Modifier.isStatic(field.access) && Modifier.isFinal(field.access) && (field.name.equals("ENUM$VALUES") || field.name.equals("$VALUES"))) {
40+
field.access &= ~Opcodes.ACC_FINAL;
41+
Implementer.LOGGER.debug("Definalize enum class {} values field {}", node.name, field.name);
42+
if (find) {
43+
throw new IllegalStateException("Duplicate static final field found for " + node.name + ": " + field.name);
44+
} else {
45+
find = true;
46+
}
47+
}
48+
}
49+
if (!find) {
50+
throw new IllegalStateException("No static final field found for " + node.name);
51+
}
52+
return true;
53+
}
54+
return false;
55+
}
56+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.magmafoundation.magma.asm;
2+
3+
import java.lang.reflect.Modifier;
4+
import org.apache.logging.log4j.LogManager;
5+
import org.apache.logging.log4j.Logger;
6+
import org.objectweb.asm.Opcodes;
7+
import org.objectweb.asm.Type;
8+
import org.objectweb.asm.tree.ClassNode;
9+
import org.objectweb.asm.tree.InsnList;
10+
import org.objectweb.asm.tree.MethodNode;
11+
import org.objectweb.asm.tree.VarInsnNode;
12+
13+
/**
14+
* Implementer
15+
*
16+
* @author Mainly by IzzelAliz and modified by Hex
17+
* @originalClassName Implementer
18+
* @classFrom <a href="https://github.com/IzzelAliz/Arclight/blob/FeudalKings/bootstrap/src/main/java/io/izzel/arclight/boot/asm/Implementer.java">Click here to get to github</a>
19+
* <p>
20+
* This classes is modified by Magma to support the Magma software.
21+
*/
22+
public interface Implementer {
23+
Logger LOGGER = LogManager.getLogger("Implementer");
24+
25+
boolean processClass(ClassNode node);
26+
27+
static void loadArgs(InsnList list, MethodNode methodNode, Type[] types, int i) {
28+
if (!Modifier.isStatic(methodNode.access)) {
29+
list.add(new VarInsnNode(Opcodes.ALOAD, i));
30+
i += 1;
31+
}
32+
for (Type type : types) {
33+
list.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), i));
34+
i += type.getSize();
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)