9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-19 14:59:21 +00:00

build: Use multi-version and preprocessor to build all target versions from one branch (#463)

* feat: convert Fabric to use essential-multi-version

* fix: populate compatibility.yml with mc version

* feat: start WIP work on doing the same for bukkit

* refactor: use preprocessor plugin to multi-version bukkit

* docs: update README to mention multi-version stuff

* build: also include javadocs for Bukkit

* build: update CI workflows

also slightly simplifies buildscript
This commit is contained in:
William
2025-03-05 16:52:21 +00:00
committed by GitHub
parent 1ff4cab88d
commit be6bebe361
46 changed files with 594 additions and 398 deletions

View File

@@ -0,0 +1,7 @@
essential.defaults.loom.mappings=net.fabricmc:yarn:1.20.1+build.10:v2
fabric_loader_version=0.15.11
fabric_api_version=0.92.2+1.20.1
fabric_permissions_api_version=0.2-SNAPSHOT
fabric_adventure_platform_version=5.9.0
fabric_sgui_version=1.2.2+1.20

View File

@@ -0,0 +1,17 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.william278.husksync.mixins",
"compatibilityLevel": "JAVA_17",
"server": [
"ItemEntityMixin",
"PlayerEntityMixin",
"ServerPlayerEntityMixin",
"ServerPlayNetworkHandlerMixin",
"ServerWorldMixin"
],
"client": [],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -0,0 +1,7 @@
essential.defaults.loom.mappings=net.fabricmc:yarn:1.21.1+build.3:v2
fabric_loader_version=0.16.10
fabric_api_version=0.107.0+1.21.1
fabric_permissions_api_version=0.3.1
fabric_adventure_platform_version=5.14.2
fabric_sgui_version=1.6.0+1.21

View File

@@ -0,0 +1,17 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.william278.husksync.mixins",
"compatibilityLevel": "JAVA_17",
"server": [
"ItemEntityMixin",
"PlayerEntityMixin",
"ServerPlayerEntityMixin",
"ServerPlayNetworkHandlerMixin",
"ServerWorldMixin"
],
"client": [],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -0,0 +1,7 @@
essential.defaults.loom.mappings=net.fabricmc:yarn:1.21.4+build.4:v2
fabric_loader_version=0.16.10
fabric_api_version=0.115.0+1.21.4
fabric_permissions_api_version=0.3.3
fabric_adventure_platform_version=6.2.0
fabric_sgui_version=1.8.2+1.21.4

View File

@@ -1,8 +1,8 @@
plugins {
id 'fabric-loom' version "$fabric_loom_version"
id 'gg.essential.multi-version'
id 'gg.essential.defaults'
}
apply plugin: 'fabric-loom'
loom.serverOnlyMinecraftJar()
repositories {
@@ -11,30 +11,39 @@ repositories {
}
dependencies {
minecraft "com.mojang:minecraft:${minecraft_version}"
mappings "net.fabricmc:yarn:${fabric_yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
modImplementation include("net.kyori:adventure-platform-fabric:${fabric_adventure_platform_version}")
modImplementation include("me.lucko:fabric-permissions-api:${fabric_permissions_api_version}")
modImplementation include("eu.pb4:sgui:${fabric_sgui_version}")
modImplementation include("net.william278.uniform:uniform-fabric:1.3.1+${minecraft_version}")
modCompileOnly "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
modImplementation include("net.william278.uniform:uniform-fabric:1.3.1+${project.name}")
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
implementation include('org.apache.commons:commons-pool2:2.12.1')
implementation include("redis.clients:jedis:$jedis_version")
implementation include("com.mysql:mysql-connector-j:$mysql_driver_version")
implementation include("org.mariadb.jdbc:mariadb-java-client:$mariadb_driver_version")
implementation include("org.postgresql:postgresql:$postgres_driver_version")
implementation include("org.mariadb.jdbc:mariadb-java-client:$mariadb_driver_version")
implementation include("redis.clients:jedis:$jedis_version")
implementation include("org.xerial.snappy:snappy-java:$snappy_version")
compileOnly 'org.jetbrains:annotations:26.0.2'
compileOnly 'net.william278:DesertWell:2.0.4'
compileOnly 'org.jetbrains:annotations:26.0.2'
compileOnly 'org.projectlombok:lombok:1.18.36'
annotationProcessor 'org.projectlombok:lombok:1.18.36'
shadow project(path: ":common")
implementation include(project(path: ":common"))
project(":common").configurations.api.dependencies.each { dependency ->
include(dependency)
}
}
processResources {
filesMatching(Arrays.asList("fabric.mod.json", "compatibility.yml")) {
expand([
version: version,
fabric_loader_version: fabric_loader_version,
fabric_minecraft_version: project.name
])
}
}
shadowJar {
@@ -44,20 +53,6 @@ shadowJar {
exclude('net.fabricmc:.*')
exclude('net.kyori:.*')
exclude '/mappings/*'
relocate 'org.apache.commons.io', 'net.william278.husksync.libraries.commons.io'
relocate 'org.apache.commons.text', 'net.william278.husksync.libraries.commons.text'
relocate 'org.apache.commons.lang3', 'net.william278.husksync.libraries.commons.lang3'
relocate 'com.google.gson', 'net.william278.husksync.libraries.gson'
relocate 'com.fatboyindustrial', 'net.william278.husksync.libraries'
relocate 'de.themoep', 'net.william278.husksync.libraries'
relocate 'org.jetbrains', 'net.william278.husksync.libraries'
relocate 'org.intellij', 'net.william278.husksync.libraries'
relocate 'com.zaxxer', 'net.william278.husksync.libraries'
relocate 'de.exlll', 'net.william278.husksync.libraries'
relocate 'net.william278.desertwell', 'net.william278.husksync.libraries.desertwell'
relocate 'net.william278.paginedown', 'net.william278.husksync.libraries.paginedown'
relocate 'org.json', 'net.william278.husksync.libraries.json'
}
remapJar {

10
fabric/gradle.properties Normal file
View File

@@ -0,0 +1,10 @@
loom.platform=fabric
essential.defaults.loom=1
essential.defaults.loom.fabric-loader=net.fabricmc:fabric-loader:0.16.10
org.gradle.daemon=false
org.gradle.parallel=true
org.gradle.configureoncommand=true
org.gradle.parallel.threads=4
org.gradle.jvmargs=-Xmx8G

1
fabric/mainProject Normal file
View File

@@ -0,0 +1 @@
1.21.4

13
fabric/root.gradle Normal file
View File

@@ -0,0 +1,13 @@
plugins {
id("gg.essential.multi-version.root")
}
preprocess {
def fabric12104 = createNode("1.21.4", 12104, "yarn")
def fabric12101 = createNode("1.21.1", 12101, "yarn")
def fabric12001 = createNode("1.20.1", 12001, "yarn")
strictExtraMappings.set(true)
fabric12101.link(fabric12104, null)
fabric12001.link(fabric12104, null)
}

View File

@@ -31,8 +31,11 @@ import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.kyori.adventure.platform.AudienceProvider;
//#if MC==12104
import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences;
//#else
//$$ import net.kyori.adventure.platform.fabric.FabricServerAudiences;
//#endif
import net.minecraft.server.MinecraftServer;
import net.william278.desertwell.util.Version;
import net.william278.husksync.adapter.DataAdapter;
@@ -78,7 +81,6 @@ import java.util.logging.Level;
@Getter
@NoArgsConstructor
@SuppressWarnings("unchecked")
public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync, FabricTask.Supplier,
FabricEventDispatcher {
@@ -111,7 +113,11 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
private MinecraftServer minecraftServer;
private boolean disabling;
private Gson gson;
private AudienceProvider audiences;
//#if MC==12104
private MinecraftServerAudiences audiences;
//#else
//$$ private FabricServerAudiences audiences;
//#endif
private Database database;
private RedisManager redisManager;
private EventListener eventListener;
@@ -156,11 +162,21 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
}
private void onEnable() {
// Initial plugin setup
// Audiences
//#if MC==12104
this.audiences = MinecraftServerAudiences.of(minecraftServer);
//#else
//$$ this.audiences = FabricServerAudiences.of(minecraftServer);
//#endif
// Check compatibility
checkCompatibility();
log(Level.WARNING, """
**************
WARNING:
HuskSync for Fabric is still in an alpha state and is
not considered production ready.
**************""");
// Prepare data adapter
initialize("data adapter", (plugin) -> {
@@ -352,7 +368,6 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
return Version.fromString(minecraftServer.getVersion());
}
@NotNull
public int getDataVersion(@NotNull Version mcVersion) {
return switch (mcVersion.toStringWithoutMetadata()) {
case "1.16", "1.16.1", "1.16.2", "1.16.3", "1.16.4", "1.16.5" -> VERSION1_16_5;
@@ -367,7 +382,13 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
case "1.21", "1.21.1" -> VERSION1_21_1;
case "1.21.2", "1.21.3" -> VERSION1_21_3;
case "1.21.4" -> VERSION1_21_4;
default -> VERSION1_21_4; // Current supported ver
//#if MC==12104
default -> VERSION1_21_4;
//#elseif MC==12101
//$$ default -> VERSION1_21_1;
//#elseif MC==12001
//$$ default -> VERSION1_20_1;
//#endif
};
}

View File

@@ -26,7 +26,12 @@ import com.google.gson.annotations.SerializedName;
import lombok.*;
import net.minecraft.advancement.AdvancementProgress;
import net.minecraft.advancement.PlayerAdvancementTracker;
//#if MC==12001
//$$ import net.minecraft.enchantment.EnchantmentHelper;
//$$ import net.minecraft.nbt.NbtCompound;
//#else
import net.minecraft.component.DataComponentTypes;
//#endif
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeInstance;
import net.minecraft.entity.attribute.EntityAttributeModifier;
@@ -39,17 +44,19 @@ import net.minecraft.registry.Registry;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.stat.StatType;
import net.minecraft.stat.Stats;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.world.TeleportTarget;
import net.william278.desertwell.util.ThrowingConsumer;
import net.william278.husksync.FabricHuskSync;
import net.william278.husksync.HuskSync;
import net.william278.husksync.adapter.Adaptable;
import net.william278.husksync.config.Settings.SynchronizationSettings.AttributeSettings;
//#if MC==12104
import net.william278.husksync.mixins.HungerManagerMixin;
//#endif
import net.william278.husksync.user.FabricUser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -88,11 +95,24 @@ public abstract class FabricData implements Data {
stack.getItem().toString(),
stack.getCount(),
stack.getName().getString(),
stack.getComponents().get(DataComponentTypes.LORE).lines().stream().map(Text::getString).toList(),
//#if MC==12001
//$$ Optional.ofNullable(stack.getSubNbt(ItemStack.DISPLAY_KEY))
//$$ .flatMap(display -> Optional.ofNullable(display.get(ItemStack.LORE_KEY))
//$$ .map(lore -> ((List<String>) lore).stream().toList()))
//$$ .orElse(null),
//$$ stack.getEnchantments().stream()
//$$ .map(element -> EnchantmentHelper.getIdFromNbt((NbtCompound) element))
//$$ .filter(Objects::nonNull).map(Identifier::toString)
//$$ .toList()
//#else
stack.getComponents().get(DataComponentTypes.LORE).lines().stream()
.map(Text::getString)
.toList(),
stack.getEnchantments().getEnchantments().stream()
.map(RegistryEntry::getIdAsString)
.filter(Objects::nonNull)
.toList()
//#endif
) : null)
.toArray(Stack[]::new);
}
@@ -158,7 +178,11 @@ public abstract class FabricData implements Data {
@Override
public void apply(@NotNull FabricUser user, @NotNull FabricHuskSync plugin) throws IllegalStateException {
final ServerPlayerEntity player = user.getPlayer();
//#if MC==12104
player.playerScreenHandler.getCraftingInput().clear();
//#else
//$$ player.playerScreenHandler.clearCraftingSlots();
//#endif
player.currentScreenHandler.setCursorStack(ItemStack.EMPTY);
final ItemStack[] items = getContents();
for (int slot = 0; slot < player.getInventory().size(); slot++) {
@@ -246,7 +270,11 @@ public abstract class FabricData implements Data {
.map(effect -> {
final StatusEffect type = matchEffectType(effect.type());
return type != null ? new StatusEffectInstance(
//#if MC==12001
//$$ type,
//#else
RegistryEntry.of(type),
//#endif
effect.duration(),
effect.amplifier(),
effect.isAmbient(),
@@ -268,10 +296,16 @@ public abstract class FabricData implements Data {
@Override
public void apply(@NotNull FabricUser user, @NotNull FabricHuskSync plugin) throws IllegalStateException {
final ServerPlayerEntity player = user.getPlayer();
//#if MC==12001
//$$ final List<StatusEffect> effectsToRemove = player.getActiveStatusEffects().entrySet().stream()
//$$ .filter(e -> !e.getValue().isAmbient()).map(Map.Entry::getKey).toList();
//$$ effectsToRemove.forEach(player::removeStatusEffect);
//#else
//todo ambient check
List<StatusEffect> effectsToRemove = new ArrayList<>(player.getActiveStatusEffects().keySet().stream()
final List<StatusEffect> effectsToRemove = new ArrayList<>(player.getActiveStatusEffects().keySet().stream()
.map(RegistryEntry::value).toList());
effectsToRemove.forEach(effect -> player.removeStatusEffect(RegistryEntry.of(effect)));
//#endif
getEffects().forEach(player::addStatusEffect);
}
@@ -281,7 +315,11 @@ public abstract class FabricData implements Data {
public List<Effect> getActiveEffects() {
return effects.stream()
.map(potionEffect -> {
//#if MC==12001
//$$ final String key = getEffectId(potionEffect.getEffectType());
//#else
final String key = getEffectId(potionEffect.getEffectType().value());
//#endif
return key != null ? new Effect(
key,
potionEffect.getAmplifier(),
@@ -313,12 +351,25 @@ public abstract class FabricData implements Data {
final AdvancementProgress advancementProgress = player.getAdvancementTracker().getProgress(advancementEntry);
final Map<String, Date> awardedCriteria = Maps.newHashMap();
advancementProgress.getObtainedCriteria().forEach((criteria) -> awardedCriteria.put(criteria,
Date.from(advancementProgress.getEarliestProgressObtainDate())));
advancementProgress.getObtainedCriteria().forEach((criteria) -> awardedCriteria.put(
criteria,
//#if MC==12001
//$$ advancementProgress.getEarliestProgressObtainDate()
//#else
Date.from(advancementProgress.getEarliestProgressObtainDate())
//#endif
));
// Only save the advancement if criteria has been completed
if (!awardedCriteria.isEmpty()) {
advancements.add(Advancement.adapt(advancementEntry.id().asString(), awardedCriteria));
advancements.add(Advancement.adapt(
//#if MC==12001
//$$ advancementEntry.getId().toString(),
//#else
advancementEntry.id().asString(),
//#endif
awardedCriteria
));
}
});
return new FabricData.Advancements(advancements);
@@ -336,7 +387,13 @@ public abstract class FabricData implements Data {
plugin.runAsync(() -> forEachAdvancementEntry(server, advancementEntry -> {
final AdvancementProgress progress = player.getAdvancementTracker().getProgress(advancementEntry);
final Optional<Advancement> record = completed.stream()
.filter(r -> r.getKey().equals(advancementEntry.id().toString()))
.filter(r -> r.getKey().equals(
//#if MC==12001
//$$ advancementEntry.getId().toString()
//#else
advancementEntry.id().asString()
//#endif
))
.findFirst();
if (record.isEmpty()) {
return;
@@ -353,7 +410,11 @@ public abstract class FabricData implements Data {
}
private void setAdvancement(@NotNull FabricHuskSync plugin,
//#if MC==12001
//$$ @NotNull net.minecraft.advancement.Advancement advancementEntry,
//#else
@NotNull net.minecraft.advancement.AdvancementEntry advancementEntry,
//#endif
@NotNull ServerPlayerEntity player,
@NotNull FabricUser user,
@NotNull List<String> toAward,
@@ -370,7 +431,7 @@ public abstract class FabricData implements Data {
// Restore player exp level & progress
if (!toAward.isEmpty()
&& (player.experienceLevel != expLevel || player.experienceProgress != expProgress)) {
&& (player.experienceLevel != expLevel || player.experienceProgress != expProgress)) {
player.setExperienceLevel(expLevel);
player.setExperiencePoints((int) (player.getNextLevelExperience() * expProgress));
}
@@ -378,8 +439,14 @@ public abstract class FabricData implements Data {
}
// Performs a consuming function for every advancement entry registered on the server
private static void forEachAdvancementEntry(@NotNull MinecraftServer server,
@NotNull ThrowingConsumer<net.minecraft.advancement.AdvancementEntry> con) {
private static void forEachAdvancementEntry(
@NotNull MinecraftServer server,
//#if MC==12001
//$$ @NotNull ThrowingConsumer<net.minecraft.advancement.Advancement> con
//#else
@NotNull ThrowingConsumer<net.minecraft.advancement.AdvancementEntry> con
//#endif
) {
server.getAdvancementLoader().getAdvancements().forEach(con);
}
@@ -411,6 +478,11 @@ public abstract class FabricData implements Data {
@NotNull
public static FabricData.Location adapt(@NotNull ServerPlayerEntity player) {
//#if MC==12001
//$$ final String worldName = player.getWorld().getDimensionKey().getValue().toString();
//#else
final String worldName = player.getWorld().getDimensionEntry().getIdAsString();
//#endif
return from(
player.getX(),
player.getY(),
@@ -421,10 +493,8 @@ public abstract class FabricData implements Data {
Objects.requireNonNull(
player.getWorld(), "World is null"
).getRegistryKey().getValue().toString(),
UUID.nameUUIDFromBytes(
player.getWorld().getDimensionEntry().getIdAsString().getBytes()
),
player.getWorld().getDimensionEntry().getIdAsString()
UUID.nameUUIDFromBytes(worldName.getBytes()),
worldName
)
);
}
@@ -433,19 +503,21 @@ public abstract class FabricData implements Data {
public void apply(@NotNull FabricUser user, @NotNull FabricHuskSync plugin) throws IllegalStateException {
final ServerPlayerEntity player = user.getPlayer();
final MinecraftServer server = plugin.getMinecraftServer();
// Find world
final String worldName = world.name();
final ServerWorld target = server.getWorld(server.getWorldRegistryKeys().stream()
.filter(key -> key.getValue().equals(Identifier.tryParse(worldName))).findFirst()
.orElseThrow(() -> new IllegalStateException("Invalid target world: %s".formatted(worldName))));
// Apply teleport
try {
player.dismountVehicle();
player.teleportTo(
new TeleportTarget(
server.getWorld(server.getWorldRegistryKeys().stream()
.filter(key -> key.getValue().equals(Identifier.tryParse(world.name())))
.findFirst().orElseThrow(
() -> new IllegalStateException("Invalid world")
)),
player,
TeleportTarget.NO_OP
)
);
//#if MC==12104
player.teleport(target, x, y, z, Set.of(), yaw, pitch, true);
//#else
//$$ player.teleport(target, x, y, z, yaw, pitch);
//#endif
} catch (Throwable e) {
throw new IllegalStateException("Failed to apply location", e);
}
@@ -477,12 +549,21 @@ public abstract class FabricData implements Data {
final Map<String, Map<String, Integer>> blocks = Maps.newHashMap(),
items = Maps.newHashMap(), entities = Maps.newHashMap();
Registries.STAT_TYPE.getEntrySet().forEach(stat -> {
// This is necessary to prevent weird re-mappings with Registry#getKey()
//#if MC>0
//$$ final Registry<?> registry = stat.getValue().getRegistry();
//$$ final String registryId = registry.getKey().getValue().toString();
//$$ if (registryId.equals("custom_stat")) {
//$$ return;
//$$ }
//#else
final Registry<?> registry = stat.getValue().getRegistry();
final String registryId = registry.getKey().getValue().getPath();
final String registryId = registry.getKey().getValue().toString();
if (registryId.equals("custom_stat")) {
return;
}
//#endif
final Map<String, Integer> map = (switch (registryId) {
case BLOCK_STAT_TYPE -> blocks;
case ITEM_STAT_TYPE -> items;
@@ -574,6 +655,21 @@ public abstract class FabricData implements Data {
final List<Attribute> attributes = Lists.newArrayList();
final AttributeSettings settings = plugin.getSettings().getSynchronization().getAttributes();
Registries.ATTRIBUTE.forEach(id -> {
//#if MC==12001
//$$ final EntityAttributeInstance instance = player.getAttributeInstance(id);
//$$ final Identifier key = Registries.ATTRIBUTE.getId(id);
//$$ if (instance == null || key == null || settings.isIgnoredAttribute(key.asString())) {
//$$ return;
//$$ }
//$$ final Set<Modifier> modifiers = Sets.newHashSet();
//$$ instance.getModifiers().forEach(modifier -> modifiers.add(new Modifier(
//$$ modifier.getId(),
//$$ modifier.getName(),
//$$ modifier.getValue(),
//$$ modifier.getOperation().getId(),
//$$ -1
//$$ )));
//#else
final EntityAttributeInstance instance = player.getAttributeInstance(RegistryEntry.of(id));
final Identifier key = Registries.ATTRIBUTE.getId(id);
if (instance == null || key == null || settings.isIgnoredAttribute(key.asString())) {
@@ -586,6 +682,7 @@ public abstract class FabricData implements Data {
modifier.operation().getId(),
Modifier.ANY_EQUIPMENT_SLOT_GROUP
)));
//#endif
attributes.add(new Attribute(
key.toString(),
instance.getBaseValue(),
@@ -618,7 +715,11 @@ public abstract class FabricData implements Data {
return;
}
applyAttribute(
//#if MC==12001
//$$ user.getPlayer().getAttributeInstance(id),
//#else
user.getPlayer().getAttributeInstance(RegistryEntry.of(id)),
//#endif
getAttribute(id).orElse(null)
);
});
@@ -633,11 +734,20 @@ public abstract class FabricData implements Data {
instance.getModifiers().forEach(instance::removeModifier);
instance.setBaseValue(attribute == null ? instance.getValue() : attribute.baseValue());
if (attribute != null) {
//#if MC==12001
//$$ attribute.modifiers().forEach(modifier -> instance.addPersistentModifier(new EntityAttributeModifier(
//$$ modifier.uuid(),
//$$ modifier.name(),
//$$ modifier.amount(),
//$$ EntityAttributeModifier.Operation.fromId(modifier.operation())
//$$ )));
//#else
attribute.modifiers().forEach(modifier -> instance.addTemporaryModifier(new EntityAttributeModifier(
Identifier.of(modifier.uuid().toString()),
Identifier.of(modifier.name()),
modifier.amount(),
EntityAttributeModifier.Operation.ID_TO_VALUE.apply(modifier.operation())
)));
//#endif
}
}
@@ -694,7 +804,12 @@ public abstract class FabricData implements Data {
@NotNull
public static FabricData.Hunger adapt(@NotNull ServerPlayerEntity player) {
final HungerManager hunger = player.getHungerManager();
return from(hunger.getFoodLevel(), hunger.getSaturationLevel(), ((HungerManagerMixin) hunger).getExhaustion());
//#if MC==12104
float exhaustion = ((HungerManagerMixin) hunger).getExhaustion();
//#else
//$$ float exhaustion = hunger.getExhaustion();
//#endif
return from(hunger.getFoodLevel(), hunger.getSaturationLevel(), exhaustion);
}
@NotNull
@@ -708,7 +823,11 @@ public abstract class FabricData implements Data {
final HungerManager hunger = player.getHungerManager();
hunger.setFoodLevel(foodLevel);
hunger.setSaturationLevel(saturation);
//#if MC==12104
((HungerManagerMixin) hunger).setExhaustion(exhaustion);
//#else
//$$ hunger.setExhaustion(exhaustion);
//#endif
}
}

View File

@@ -26,6 +26,9 @@ import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import net.minecraft.datafixer.TypeReferences;
import net.minecraft.item.ItemStack;
//#if MC==12001
//$$ import net.minecraft.nbt.NbtCompound;
//#endif
import net.minecraft.nbt.*;
import net.minecraft.registry.DynamicRegistryManager;
import net.william278.desertwell.util.Version;
@@ -154,7 +157,7 @@ public abstract class FabricSerializer {
final DynamicRegistryManager registryManager = plugin.getMinecraftServer().getRegistryManager();
itemList.forEach(element -> {
final NbtCompound compound = (NbtCompound) element;
contents[compound.getInt("Slot")] = ItemStack.fromNbt(registryManager, element).get();
contents[compound.getInt("Slot")] = decodeNbt(element, registryManager);
});
plugin.debug(Arrays.toString(contents));
return contents;
@@ -175,7 +178,8 @@ public abstract class FabricSerializer {
if (item == null || item.isEmpty()) {
continue;
}
NbtCompound entry = (NbtCompound) item.toNbt(registryManager);
final NbtCompound entry = encodeNbt(item, registryManager);
entry.putInt("Slot", i);
itemList.add(entry);
}
@@ -197,7 +201,7 @@ public abstract class FabricSerializer {
}
final NbtCompound compound = list.getCompound(i);
final int slot = compound.getInt("Slot");
itemStacks[slot] = ItemStack.fromNbt(registryManager, upgradeItemData(list.getCompound(i), mcVersion, plugin)).get();
itemStacks[slot] = decodeNbt(upgradeItemData(list.getCompound(i), mcVersion, plugin), registryManager);
}
return itemStacks;
}
@@ -212,6 +216,32 @@ public abstract class FabricSerializer {
).getValue();
}
@NotNull
private NbtCompound encodeNbt(@NotNull ItemStack item, @NotNull DynamicRegistryManager registryManager) {
//#if MC==12104
return (NbtCompound) item.toNbt(registryManager);
//#elseif MC==12101
//$$ return (NbtCompound) item.encode(registryManager);
//#elseif MC==12001
//$$ final NbtCompound compound = new NbtCompound();
//$$ item.writeNbt(compound);
//$$ return compound;
//#endif
}
@NotNull
private ItemStack decodeNbt(@NotNull NbtElement item, @NotNull DynamicRegistryManager registryManager) {
//#if MC==12001
//$$ final @Nullable ItemStack stack = ItemStack.fromNbt((NbtCompound) item);
//#else
final @Nullable ItemStack stack = ItemStack.fromNbt(registryManager, item).orElse(null);
//#endif
if (stack == null) {
throw new IllegalStateException("Failed to decode item NBT (got null 'fromNbt'): (%s)".formatted(item));
}
return stack;
}
}
public static class PotionEffects extends FabricSerializer implements Serializer<FabricData.PotionEffects> {

View File

@@ -104,7 +104,11 @@ public interface FabricUserDataHolder extends UserDataHolder {
@Override
default Optional<Data.Items.EnderChest> getEnderChest() {
return Optional.of(FabricData.Items.EnderChest.adapt(
//#if MC==12001
//$$ getPlayer().getEnderChestInventory().stacks
//#else
getPlayer().getEnderChestInventory().getHeldStacks()
//#endif
));
}

View File

@@ -39,6 +39,9 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
//#if MC<12104
//$$ import net.minecraft.util.TypedActionResult;
//#endif
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
@@ -123,9 +126,16 @@ public class FabricEventListener extends EventListener implements LockedHandler
return (cancelPlayerEvent(player.getUuid())) ? ActionResult.FAIL : ActionResult.PASS;
}
//#if MC==12104
private ActionResult handleItemInteract(PlayerEntity player, World world, Hand hand) {
return (cancelPlayerEvent(player.getUuid())) ? ActionResult.FAIL : ActionResult.PASS;
}
//#else
//$$ private TypedActionResult<ItemStack> handleItemInteract(PlayerEntity player, World world, Hand hand) {
//$$ final ItemStack stackInHand = player.getStackInHand(hand);
//$$ return (cancelPlayerEvent(player.getUuid())) ? TypedActionResult.fail(stackInHand) : TypedActionResult.pass(stackInHand);
//$$ }
//#endif
private boolean handleBlockBreak(World world, PlayerEntity player, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) {
return !cancelPlayerEvent(player.getUuid());

View File

@@ -17,6 +17,7 @@
* limitations under the License.
*/
//#if MC==12104
package net.william278.husksync.mixins;
import net.minecraft.entity.player.HungerManager;
@@ -33,3 +34,4 @@ public interface HungerManagerMixin {
void setExhaustion(float exhaustion);
}
//#endif

View File

@@ -42,7 +42,7 @@ public class PlayerEntityMixin {
@Final
@Shadow
private PlayerInventory inventory;
PlayerInventory inventory;
@Inject(method = "dropInventory", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;vanishCursedItems()V"))
protected void dropInventory(@NotNull CallbackInfo ci) {
@@ -56,7 +56,7 @@ public class PlayerEntityMixin {
final @Nullable ItemStack @NotNull [] toKeep = new ItemStack[inventory.size()];
for (int i = 0; i < inventory.size(); ++i) {
ItemStack itemStack = inventory.getStack(i);
if (!itemStack.isEmpty() && EnchantmentHelper.hasAnyEnchantmentsIn(itemStack, TagKey.of(Enchantments.VANISHING_CURSE.getRegistryRef(), Enchantments.VANISHING_CURSE.getValue()))) {
if (!itemStack.isEmpty() && hasVanishingCurse(itemStack)) {
toKeep[i] = null;
continue;
}
@@ -71,7 +71,7 @@ public class PlayerEntityMixin {
final @Nullable ItemStack @NotNull [] toDrop = new ItemStack[inventory.size()];
for (int i = 0; i < inventory.size(); ++i) {
ItemStack itemStack = inventory.getStack(i);
if (!itemStack.isEmpty() && EnchantmentHelper.hasAnyEnchantmentsIn(itemStack, TagKey.of(Enchantments.VANISHING_CURSE.getRegistryRef(), Enchantments.VANISHING_CURSE.getValue()))) {
if (!itemStack.isEmpty() && hasVanishingCurse(itemStack)) {
toDrop[i] = itemStack;
continue;
}
@@ -80,4 +80,15 @@ public class PlayerEntityMixin {
return toDrop;
}
@Unique
private boolean hasVanishingCurse(@NotNull ItemStack stack) {
//#if MC==12001
//$$ return EnchantmentHelper.hasVanishingCurse(stack);
//#else
return EnchantmentHelper.hasAnyEnchantmentsIn(
stack, TagKey.of(Enchantments.VANISHING_CURSE.getRegistryRef(), Enchantments.VANISHING_CURSE.getValue())
);
//#endif
}
}

View File

@@ -88,7 +88,11 @@ public abstract class ServerPlayNetworkHandlerMixin {
@Inject(method = "onCreativeInventoryAction", at = @At("HEAD"), cancellable = true)
public void onCreativeInventoryAction(CreativeInventoryActionC2SPacket packet, CallbackInfo ci) {
//#if MC==12001
//$$ int slot = packet.getSlot();
//#else
int slot = packet.slot();
//#endif
if (slot < 0) {
return;
}
@@ -111,4 +115,5 @@ public abstract class ServerPlayNetworkHandlerMixin {
ci.cancel();
}
}
}

View File

@@ -36,7 +36,11 @@ public class ServerWorldMixin {
@Shadow
private MinecraftServer server;
//#if MC==12104
@Inject(method = "savePersistentState", at = @At("HEAD"))
//#else
//$$ @Inject(method = "saveLevel", at = @At("HEAD"))
//#endif
public void saveLevel(CallbackInfo ci) {
if (server.isStopping() || server.isStopped()) {
return;

View File

@@ -25,7 +25,11 @@ import eu.pb4.sgui.api.elements.GuiElementInterface;
import eu.pb4.sgui.api.gui.SimpleGui;
import me.lucko.fabric.api.permissions.v0.Permissions;
import net.kyori.adventure.audience.Audience;
//#if MC==12104
import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences;
//#else
//$$ import net.kyori.adventure.platform.fabric.FabricServerAudiences;
//#endif
import net.minecraft.item.ItemStack;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
@@ -102,7 +106,11 @@ public class FabricUser extends OnlineUser implements FabricUserDataHolder {
this.editable = editable;
// Set title, items
//#if MC==12104
this.setTitle(((MinecraftServerAudiences) plugin.getAudiences()).asNative(title.toComponent()));
//#else
//$$ this.setTitle(((FabricServerAudiences) plugin.getAudiences()).toNative(title.toComponent()));
//#endif
this.setLockPlayerInventory(!editable);
for (int i = 0; i < size; i++) {
final ItemStack item = items.getContents()[i];

View File

@@ -0,0 +1,2 @@
# File used for checking Minecraft server compatibility with this version of HuskSync
minecraft_version: '${fabric_minecraft_version}'

View File

@@ -40,11 +40,12 @@
},
"depends": {
"fabricloader": ">=${fabric_loader_version}",
"minecraft": ">=${minecraft_version}",
"minecraft": "${fabric_minecraft_version}",
"fabric-api": "*"
},
"suggests": {
"plan": "*"
"luckperms": ">=5.4",
"plan": ">=5.5"
},
"mixins": [
"husksync.mixins.json"