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

feat: support Minecraft 1.21.1 on Fabric

This commit is contained in:
William
2024-08-25 20:49:25 +01:00
8 changed files with 66 additions and 68 deletions

View File

@@ -74,6 +74,7 @@ allprojects {
maven { url 'https://repo.william278.net/releases/' }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
maven { url 'https://repo.papermc.io/repository/maven-public/' }
maven { url "https://repo.dmulloy2.net/repository/public/" }
maven { url 'https://repo.codemc.io/repository/maven-public/' }
maven { url 'https://repo.minebench.de/' }

View File

@@ -15,7 +15,7 @@ dependencies {
mappings "net.fabricmc:yarn:${fabric_yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
modImplementation include("net.kyori:adventure-platform-mod-shared:${fabric_adventure_platform_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.2.1+1.20.1')

View File

@@ -24,10 +24,9 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.annotations.SerializedName;
import lombok.*;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensions;
import net.minecraft.advancement.AdvancementProgress;
import net.minecraft.advancement.PlayerAdvancementTracker;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeInstance;
import net.minecraft.entity.attribute.EntityAttributeModifier;
@@ -35,15 +34,15 @@ import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.player.HungerManager;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.Registries;
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.stat.StatType;
import net.minecraft.stat.Stats;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.TeleportTarget;
import net.william278.desertwell.util.ThrowingConsumer;
import net.william278.husksync.FabricHuskSync;
@@ -87,13 +86,10 @@ public abstract class FabricData implements Data {
stack.getItem().toString(),
stack.getCount(),
stack.getName().getString(),
Optional.ofNullable(stack.getSubNbt(ItemStack.DISPLAY_KEY))
.flatMap(display -> Optional.ofNullable(display.get(ItemStack.LORE_KEY))
.map(lore -> ((List<String>) lore).stream().toList())) //todo check this is ok
.orElse(null),
stack.getEnchantments().stream()
.map(element -> EnchantmentHelper.getIdFromNbt((NbtCompound) element))
.filter(Objects::nonNull).map(Identifier::toString)
stack.getComponents().get(DataComponentTypes.LORE).lines().stream().map(Text::getString).toList(),
stack.getEnchantments().getEnchantments().stream()
.map(RegistryEntry::getIdAsString)
.filter(Objects::nonNull)
.toList()
) : null)
.toArray(Stack[]::new);
@@ -248,7 +244,7 @@ public abstract class FabricData implements Data {
.map(effect -> {
final StatusEffect type = matchEffectType(effect.type());
return type != null ? new StatusEffectInstance(
type,
RegistryEntry.of(type),
effect.duration(),
effect.amplifier(),
effect.isAmbient(),
@@ -270,9 +266,10 @@ public abstract class FabricData implements Data {
@Override
public void apply(@NotNull FabricUser user, @NotNull FabricHuskSync plugin) throws IllegalStateException {
final ServerPlayerEntity player = user.getPlayer();
final List<StatusEffect> effectsToRemove = player.getActiveStatusEffects().entrySet().stream()
.filter(e -> !e.getValue().isAmbient()).map(Map.Entry::getKey).toList();
effectsToRemove.forEach(player::removeStatusEffect);
//todo ambient check
List<StatusEffect> effectsToRemove = new ArrayList<>(player.getActiveStatusEffects().keySet().stream()
.map(RegistryEntry::value).toList());
effectsToRemove.forEach(effect -> player.removeStatusEffect(RegistryEntry.of(effect)));
getEffects().forEach(player::addStatusEffect);
}
@@ -282,7 +279,7 @@ public abstract class FabricData implements Data {
public List<Effect> getActiveEffects() {
return effects.stream()
.map(potionEffect -> {
final String key = getEffectId(potionEffect.getEffectType());
final String key = getEffectId(potionEffect.getEffectType().value());
return key != null ? new Effect(
key,
potionEffect.getAmplifier(),
@@ -310,16 +307,16 @@ public abstract class FabricData implements Data {
public static FabricData.Advancements adapt(@NotNull ServerPlayerEntity player) {
final MinecraftServer server = Objects.requireNonNull(player.getServer(), "Server is null");
final List<Advancement> advancements = Lists.newArrayList();
forEachAdvancement(server, advancement -> {
final AdvancementProgress advancementProgress = player.getAdvancementTracker().getProgress(advancement);
forEachAdvancementEntry(server, advancementEntry -> {
final AdvancementProgress advancementProgress = player.getAdvancementTracker().getProgress(advancementEntry);
final Map<String, Date> awardedCriteria = Maps.newHashMap();
advancementProgress.getObtainedCriteria().forEach((criteria) -> awardedCriteria.put(criteria,
advancementProgress.getEarliestProgressObtainDate()));
Date.from(advancementProgress.getEarliestProgressObtainDate())));
// Only save the advancement if criteria has been completed
if (!awardedCriteria.isEmpty()) {
advancements.add(Advancement.adapt(advancement.getId().toString(), awardedCriteria));
advancements.add(Advancement.adapt(advancementEntry.id().asString(), awardedCriteria));
}
});
return new FabricData.Advancements(advancements);
@@ -334,10 +331,10 @@ 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 = Objects.requireNonNull(player.getServer(), "Server is null");
plugin.runAsync(() -> forEachAdvancement(server, advancement -> {
final AdvancementProgress progress = player.getAdvancementTracker().getProgress(advancement);
plugin.runAsync(() -> forEachAdvancementEntry(server, advancementEntry -> {
final AdvancementProgress progress = player.getAdvancementTracker().getProgress(advancementEntry);
final Optional<Advancement> record = completed.stream()
.filter(r -> r.getKey().equals(advancement.getId().toString()))
.filter(r -> r.getKey().equals(advancementEntry.id().toString()))
.findFirst();
if (record.isEmpty()) {
return;
@@ -346,7 +343,7 @@ public abstract class FabricData implements Data {
final Map<String, Date> criteria = record.get().getCompletedCriteria();
final List<String> awarded = Lists.newArrayList(progress.getObtainedCriteria());
this.setAdvancement(
plugin, advancement, player, user,
plugin, advancementEntry, player, user,
criteria.keySet().stream().filter(key -> !awarded.contains(key)).toList(),
awarded.stream().filter(key -> !criteria.containsKey(key)).toList()
);
@@ -354,7 +351,7 @@ public abstract class FabricData implements Data {
}
private void setAdvancement(@NotNull FabricHuskSync plugin,
@NotNull net.minecraft.advancement.Advancement advancement,
@NotNull net.minecraft.advancement.AdvancementEntry advancementEntry,
@NotNull ServerPlayerEntity player,
@NotNull FabricUser user,
@NotNull List<String> toAward,
@@ -366,8 +363,8 @@ public abstract class FabricData implements Data {
// Award and revoke advancement criteria
final PlayerAdvancementTracker progress = player.getAdvancementTracker();
toAward.forEach(a -> progress.grantCriterion(advancement, a));
toRevoke.forEach(r -> progress.revokeCriterion(advancement, r));
toAward.forEach(a -> progress.grantCriterion(advancementEntry, a));
toRevoke.forEach(r -> progress.revokeCriterion(advancementEntry, r));
// Restore player exp level & progress
if (!toAward.isEmpty()
@@ -378,9 +375,9 @@ public abstract class FabricData implements Data {
});
}
// Performs a consuming function for every advancement registered on the server
private static void forEachAdvancement(@NotNull MinecraftServer server,
@NotNull ThrowingConsumer<net.minecraft.advancement.Advancement> con) {
// 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) {
server.getAdvancementLoader().getAdvancements().forEach(con);
}
@@ -423,9 +420,9 @@ public abstract class FabricData implements Data {
player.getWorld(), "World is null"
).getRegistryKey().getValue().toString(),
UUID.nameUUIDFromBytes(
player.getWorld().getDimensionKey().getValue().toString().getBytes()
player.getWorld().getDimensionEntry().getIdAsString().getBytes()
),
player.getWorld().getDimensionKey().getValue().toString()
player.getWorld().getDimensionEntry().getIdAsString()
)
);
}
@@ -436,18 +433,15 @@ public abstract class FabricData implements Data {
final MinecraftServer server = plugin.getMinecraftServer();
try {
player.dismountVehicle();
FabricDimensions.teleport(
player,
player.teleportTo(
new TeleportTarget(
server.getWorld(server.getWorldRegistryKeys().stream()
.filter(key -> key.getValue().equals(Identifier.tryParse(world.name())))
.findFirst().orElseThrow(
() -> new IllegalStateException("Invalid world")
)),
new TeleportTarget(
new Vec3d(x, y, z),
Vec3d.ZERO,
yaw,
pitch
player,
TeleportTarget.NO_OP
)
);
} catch (Throwable e) {
@@ -577,17 +571,17 @@ public abstract class FabricData implements Data {
public static FabricData.Attributes adapt(@NotNull ServerPlayerEntity player, @NotNull HuskSync plugin) {
final List<Attribute> attributes = Lists.newArrayList();
Registries.ATTRIBUTE.forEach(id -> {
final EntityAttributeInstance instance = player.getAttributeInstance(id);
final EntityAttributeInstance instance = player.getAttributeInstance(RegistryEntry.of(id));
final Identifier key = Registries.ATTRIBUTE.getId(id);
if (instance == null || key == null) {
return;
}
final Set<Modifier> modifiers = Sets.newHashSet();
instance.getModifiers().forEach(modifier -> modifiers.add(new Modifier(
modifier.getId(),
modifier.getName(),
modifier.getValue(),
modifier.getOperation().getId(),
UUID.nameUUIDFromBytes(modifier.id().toString().getBytes()),
modifier.id().examinableName(),
modifier.value(),
modifier.operation().getId(),
-1
)));
attributes.add(new Attribute(
@@ -616,7 +610,7 @@ public abstract class FabricData implements Data {
@Override
protected void apply(@NotNull FabricUser user, @NotNull FabricHuskSync plugin) {
Registries.ATTRIBUTE.forEach(id -> applyAttribute(
user.getPlayer().getAttributeInstance(id),
user.getPlayer().getAttributeInstance(RegistryEntry.of(id)),
getAttribute(id).orElse(null)
));
@@ -627,14 +621,13 @@ public abstract class FabricData implements Data {
if (instance == null) {
return;
}
instance.setBaseValue(attribute == null ? instance.getAttribute().getDefaultValue() : attribute.baseValue());
instance.setBaseValue(attribute == null ? instance.getAttribute().value().getDefaultValue() : attribute.baseValue());
instance.getModifiers().forEach(instance::removeModifier);
if (attribute != null) {
attribute.modifiers().forEach(modifier -> instance.addPersistentModifier(new EntityAttributeModifier(
modifier.uuid(),
modifier.name(),
Identifier.of(modifier.uuid().toString()),
modifier.amount(),
EntityAttributeModifier.Operation.fromId(modifier.operationType())
EntityAttributeModifier.Operation.ID_TO_VALUE.apply(modifier.operationType())
)));
}
}

View File

@@ -27,6 +27,7 @@ import lombok.AllArgsConstructor;
import net.minecraft.datafixer.TypeReferences;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
import net.minecraft.registry.DynamicRegistryManager;
import net.william278.desertwell.util.Version;
import net.william278.husksync.FabricHuskSync;
import net.william278.husksync.HuskSync;
@@ -94,7 +95,7 @@ public abstract class FabricSerializer {
public String serialize(@NotNull FabricData.Items.Inventory data) throws SerializationException {
try {
final NbtCompound root = new NbtCompound();
root.put(ITEMS_TAG, serializeItemArray(data.getContents()));
root.put(ITEMS_TAG, serializeItemArray(data.getContents(), (FabricHuskSync) getPlugin()));
root.putInt(HELD_ITEM_SLOT_TAG, data.getHeldItemSlot());
return root.toString();
} catch (Throwable e) {
@@ -132,7 +133,7 @@ public abstract class FabricSerializer {
@Override
public String serialize(@NotNull FabricData.Items.EnderChest data) throws SerializationException {
try {
return serializeItemArray(data.getContents()).toString();
return serializeItemArray(data.getContents(), (FabricHuskSync) getPlugin()).toString();
} catch (Throwable e) {
throw new SerializationException("Failed to serialize ender chest item NBT to string", e);
}
@@ -161,9 +162,10 @@ public abstract class FabricSerializer {
final ItemStack[] contents = new ItemStack[tag.getInt("size")];
final NbtList itemList = tag.getList("items", NbtElement.COMPOUND_TYPE);
final DynamicRegistryManager registryManager = plugin.getMinecraftServer().getRegistryManager();
itemList.forEach(element -> {
final NbtCompound compound = (NbtCompound) element;
contents[compound.getInt("Slot")] = ItemStack.fromNbt(compound);
contents[compound.getInt("Slot")] = ItemStack.fromNbt(registryManager, element).get();
});
plugin.debug(Arrays.toString(contents));
return contents;
@@ -174,18 +176,18 @@ public abstract class FabricSerializer {
// Serialize items slot-by-slot
@NotNull
default NbtCompound serializeItemArray(@Nullable ItemStack @NotNull [] items) {
default NbtCompound serializeItemArray(@Nullable ItemStack @NotNull [] items, @NotNull FabricHuskSync plugin) {
final NbtCompound container = new NbtCompound();
container.putInt("size", items.length);
final NbtList itemList = new NbtList();
final DynamicRegistryManager registryManager = plugin.getMinecraftServer().getRegistryManager();
for (int i = 0; i < items.length; i++) {
final ItemStack item = items[i];
if (item == null || item.isEmpty()) {
continue;
}
NbtCompound entry = new NbtCompound();
NbtCompound entry = (NbtCompound) item.encode(registryManager);
entry.putInt("Slot", i);
item.writeNbt(entry);
itemList.add(entry);
}
container.put(ITEMS_TAG, itemList);
@@ -198,6 +200,7 @@ public abstract class FabricSerializer {
final int size = items.getInt("size");
final NbtList list = items.getList("items", NbtElement.COMPOUND_TYPE);
final ItemStack[] itemStacks = new ItemStack[size];
final DynamicRegistryManager registryManager = plugin.getMinecraftServer().getRegistryManager();
Arrays.fill(itemStacks, ItemStack.EMPTY);
for (int i = 0; i < size; i++) {
if (list.getCompound(i) == null) {
@@ -205,7 +208,7 @@ public abstract class FabricSerializer {
}
final NbtCompound compound = list.getCompound(i);
final int slot = compound.getInt("Slot");
itemStacks[slot] = ItemStack.fromNbt(upgradeItemData(list.getCompound(i), mcVersion, plugin));
itemStacks[slot] = ItemStack.fromNbt(registryManager, upgradeItemData(list.getCompound(i), mcVersion, plugin)).get();
}
return itemStacks;
}

View File

@@ -104,7 +104,7 @@ public interface FabricUserDataHolder extends UserDataHolder {
@Override
default Optional<Data.Items.EnderChest> getEnderChest() {
return Optional.of(FabricData.Items.EnderChest.adapt(
getPlayer().getEnderChestInventory().stacks
getPlayer().getEnderChestInventory().getHeldStacks()
));
}

View File

@@ -20,9 +20,11 @@
package net.william278.husksync.mixins;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.network.ServerPlayerEntity;
import net.william278.husksync.event.PlayerDeathDropsCallback;
import org.jetbrains.annotations.NotNull;
@@ -54,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.hasVanishingCurse(itemStack)) {
if (!itemStack.isEmpty() && EnchantmentHelper.hasAnyEnchantmentsIn(itemStack, TagKey.of(Enchantments.VANISHING_CURSE.getRegistryRef(), Enchantments.VANISHING_CURSE.getValue()))) {
toKeep[i] = null;
continue;
}
@@ -69,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.hasVanishingCurse(itemStack)) {
if (!itemStack.isEmpty() && EnchantmentHelper.hasAnyEnchantmentsIn(itemStack, TagKey.of(Enchantments.VANISHING_CURSE.getRegistryRef(), Enchantments.VANISHING_CURSE.getValue()))) {
toDrop[i] = itemStack;
continue;
}

View File

@@ -44,7 +44,6 @@ public abstract class ServerPlayNetworkHandlerMixin {
@Shadow
public ServerPlayerEntity player;
@Shadow
public abstract void sendPacket(Packet<?> packet);
@Inject(method = "onPlayerAction", at = @At("HEAD"), cancellable = true)
@@ -83,7 +82,7 @@ public abstract class ServerPlayNetworkHandlerMixin {
@Inject(method = "onCreativeInventoryAction", at = @At("HEAD"), cancellable = true)
public void onCreativeInventoryAction(CreativeInventoryActionC2SPacket packet, CallbackInfo ci) {
int slot = packet.getSlot();
int slot = packet.slot();
if (slot < 0) return;
ItemStack stack = this.player.getInventory().getStack(slot);

View File

@@ -25,6 +25,6 @@ bukkit_paper_api=1.21.1-R0.1-SNAPSHOT
fabric_loader_version=0.16.2
fabric_yarn_mappings=1.21.1+build.3
fabric_api_version=0.102.1+1.21.1
fabric_adventure_platform_version=6.0.0
fabric_adventure_platform_version=5.14.1
fabric_permissions_api_version=0.3.1
fabric_sgui_version=1.6.0+1.21