Skip to content

Commit

Permalink
build: introduce additional source sets to prevent using reflection o…
Browse files Browse the repository at this point in the history
…n API

currently it is demonstrated on 1.20.1, more source sets are coming in the future
  • Loading branch information
Misat11 committed May 30, 2024
1 parent 41c08ff commit a072302
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 21 deletions.
22 changes: 22 additions & 0 deletions core/bukkit/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
def supportVersions = [
'1_20_1': libs.paper.support.one.twenty.one
]

sourceSets {
for (def ver : supportVersions.keySet()) {
"support_${ver}" {
java {
}
}

main {
compileClasspath += sourceSets."support_${ver}".output
output.dir(sourceSets."support_${ver}".output.classesDirs, builtBy: "compileSupport_${ver}Java")
}
}
}

dependencies {
api project(':nms'), {
targetConfiguration = 'shadow'
Expand All @@ -10,6 +28,10 @@ dependencies {
api project(':spectator-bungee')

compileOnly libs.paper
for (def ver : supportVersions) {
"support_${ver.key}CompileOnly" ver.value
}

compileOnly libs.netty
compileOnly libs.viaversion
compileOnly libs.protocolsupport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.screamingsandals.lib.entity.ItemEntity;
import org.screamingsandals.lib.entity.LightningBolt;
import org.screamingsandals.lib.impl.bukkit.BukkitFeature;
import org.screamingsandals.lib.impl.bukkit.compat.v1_20_1.EntitySpawnCompat;
import org.screamingsandals.lib.impl.bukkit.entity.ambient.BukkitAmbientCreature;
import org.screamingsandals.lib.impl.bukkit.entity.ambient.BukkitBat;
import org.screamingsandals.lib.impl.bukkit.entity.animal.BukkitAnimal;
Expand Down Expand Up @@ -993,12 +994,8 @@ public class BukkitEntities extends Entities {
} else if (BukkitFeature.ENTITY_PRE_SPAWN_FUNCTION.isSupported()) {
org.bukkit.entity.Entity entity;
if (preSpawnFunction != null) {
@SuppressWarnings({"deprecation", "rawtypes"})
org.bukkit.util.Consumer cons = preSpawnBukkitEntity -> preSpawnFunction.accept(wrapEntity0(preSpawnBukkitEntity));
// TODO: prepare independent compatibility source sets compiled against older bukkit API instead of using reflection
//noinspection deprecation
entity = (org.bukkit.entity.Entity) Reflect.getMethod(world, "spawn", org.bukkit.Location.class, Class.class, org.bukkit.util.Consumer.class)
.invoke(bukkitLoc, entityClass, cons);
// symbol is no longer in the API, see javadoc
entity = EntitySpawnCompat.spawn(bukkitLoc, entityClass, preSpawnBukkitEntity -> preSpawnFunction.accept(wrapEntity0(preSpawnBukkitEntity)));
} else {
entity = world.spawn(bukkitLoc, entityClass);
}
Expand Down Expand Up @@ -1078,13 +1075,9 @@ public class BukkitEntities extends Entities {
} else if (BukkitFeature.ITEM_ENTITY_PRE_SPAWN_FUNCTION_JAVA_CONSUMER.isSupported()) {
return new BukkitItemEntity(bukkitLoc.getWorld().dropItem(bukkitLoc, item.as(org.bukkit.inventory.ItemStack.class), item1 -> preSpawnFunction.accept(new BukkitItemEntity(item1))));
} else if (BukkitFeature.ITEM_ENTITY_PRE_SPAWN_FUNCTION.isSupported()) {
@SuppressWarnings("deprecation")
org.bukkit.util.Consumer<org.bukkit.entity.Item> cons = item1 -> preSpawnFunction.accept(new BukkitItemEntity(item1));
// TODO: prepare independent compatibility source sets compiled against older bukkit API instead of using reflection
@SuppressWarnings("deprecation")
var entity = (org.bukkit.entity.Entity) Reflect.getMethod(bukkitLoc.getWorld(), "dropItem", org.bukkit.Location.class, org.bukkit.inventory.ItemStack.class, org.bukkit.util.Consumer.class)
.invoke(bukkitLoc, item.as(org.bukkit.inventory.ItemStack.class), cons);
return new BukkitItemEntity((org.bukkit.entity.Item) entity);
// symbol is no longer in the API, see javadoc
var entity = EntitySpawnCompat.dropItem(bukkitLoc, item.as(org.bukkit.inventory.ItemStack.class), item1 -> preSpawnFunction.accept(new BukkitItemEntity(item1)));
return new BukkitItemEntity(entity);
} else {
var itemEntity = new BukkitItemEntity(bukkitLoc.getWorld().dropItem(bukkitLoc, item.as(org.bukkit.inventory.ItemStack.class)));
preSpawnFunction.accept(itemEntity);
Expand All @@ -1103,18 +1096,14 @@ public class BukkitEntities extends Entities {
}
}));
} else if (BukkitFeature.ENTITY_PRE_SPAWN_FUNCTION.isSupported()) {
@SuppressWarnings("deprecation")
org.bukkit.util.Consumer<org.bukkit.entity.ExperienceOrb> cons = experienceOrb -> {
// symbol is no longer in the API, see javadoc
var entity = EntitySpawnCompat.spawn(bukkitLoc, org.bukkit.entity.ExperienceOrb.class, experienceOrb -> {
experienceOrb.setExperience(experience);
if (preSpawnFunction != null) {
preSpawnFunction.accept(new BukkitExperienceOrb(experienceOrb));
}
};
// TODO: prepare independent compatibility source sets compiled against older bukkit API instead of using reflection
@SuppressWarnings("deprecation")
var entity = Reflect.getMethod(bukkitLoc.getWorld(), "spawn", org.bukkit.Location.class, Class.class, org.bukkit.util.Consumer.class)
.invoke(bukkitLoc, org.bukkit.entity.ExperienceOrb.class, cons);
return new BukkitExperienceOrb((org.bukkit.entity.ExperienceOrb) entity);
});
return new BukkitExperienceOrb(entity);
} else {
var orb = bukkitLoc.getWorld().spawn(bukkitLoc, org.bukkit.entity.ExperienceOrb.class);
orb.setExperience(experience);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.screamingsandals.lib.impl.bukkit.compat.v1_20_1;

import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;

@UtilityClass
public class EntitySpawnCompat {
/**
* Provides a way to spawn an entity with pre-spawn callback in 1.11-1.20.1. The overloaded variant
* {@code spawn(org.bukkit.Location, Class, org.bukkit.util.Consumer)} does not exist anymore since 1.20.2,
* making it unable to compile compatible version against newer API.
*/
public static <T extends Entity> @NotNull T spawn(@NotNull Location location, @NotNull Class<T> type, @NotNull java.util.function.Consumer<T> consumer) {
org.bukkit.util.Consumer<T> cons = consumer::accept;
return location.getWorld().spawn(location, type, cons);
}

/**
* Provides a way to drop an item with pre-spawn callback in 1.11-1.20.1. The overloaded variant
* {@code spawn(org.bukkit.Location, org.bukkit.inventory.ItemStack, org.bukkit.util.Consumer)} does not exist anymore since 1.20.2,
* making it unable to compile compatible version against newer API.
*/
public static @NotNull Item dropItem(@NotNull Location location, @NotNull ItemStack item, @NotNull java.util.function.Consumer<Item> consumer) {
org.bukkit.util.Consumer<Item> cons = consumer::accept;
return location.getWorld().dropItem(location, item, cons);
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[versions]
# platforms
paper = "1.20.4-R0.1-SNAPSHOT"
paper-support_1_20_1 = "1.20.1-R0.1-SNAPSHOT"
sponge = "8.2.0"
minestom = "master-SNAPSHOT"
waterfall = "1.20-R0.1-SNAPSHOT"
Expand Down Expand Up @@ -65,6 +66,7 @@ protocolsupport = { group = "com.github.ProtocolSupport", name = "ProtocolSuppor

# platforms
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
paper-support_one_twenty_one = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper-support_1_20_1" }
sponge = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" }
minestom = { group = "com.github.Minestom", name = "Minestom", version.ref = "minestom" }
waterfall = { group = "io.github.waterfallmc", name = "waterfall-api", version.ref = "waterfall" }
Expand Down

0 comments on commit a072302

Please sign in to comment.