Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
project(':versions:v1_21_R1'),
project(':versions:v1_21_R3'),
project(':versions:v1_21_R5'),
project(':versions:v1_21_r7'),

project(':database'),

Expand Down
13 changes: 12 additions & 1 deletion core/src/main/java/com/wizardlybump17/wlib/WLib.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,18 @@ private void setupAdapters() {
PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_R5.player.PlayerAdapter());
AttributeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_R5.AttributeAdapter());
}
default -> getLogger().severe("The server version (" + version + ") is not supported by WLib yet.");
case "1.21.11" -> {
ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_r7.ItemAdapter());
PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_r7.player.PlayerAdapter());
AttributeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_r7.AttributeAdapter());
}
default -> {
getLogger().severe("The server version (" + version + ") is not supported by WLib yet. Using last known version (1.21.11), but expect stuff to break.");

ItemAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_r7.ItemAdapter());
PlayerAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_r7.player.PlayerAdapter());
AttributeAdapter.setInstance(new com.wizardlybump17.wlib.adapter.v1_21_r7.AttributeAdapter());
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ findProject(':versions:v1_21_R1')?.name = 'v1_21_R1'
include 'versions:v1_21_R3'
findProject(':versions:v1_21_R3')?.name = 'v1_21_R3'
include 'versions:v1_21_R5'
findProject(':versions:v1_21_R5')?.name = 'v1_21_R5'
findProject(':versions:v1_21_R5')?.name = 'v1_21_R5'

include 'versions:v1_21_r7'
18 changes: 18 additions & 0 deletions versions/v1_21_r7/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
plugins {
id("io.papermc.paperweight.userdev") version "2.0.0-SNAPSHOT"
}

apply(plugin = "io.papermc.paperweight.userdev")

val paper = "1.21.11-R0.1-SNAPSHOT"
val jetbrainsAnnotations = "26.0.2"

dependencies {
paperweightDevelopmentBundle("io.papermc.paper:dev-bundle:${paper}")

compileOnly("org.jetbrains:annotations:${jetbrainsAnnotations}")

implementation(project(":versions:adapter"))
implementation(project(":utils"))
implementation(project(":bukkit-utils"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.wizardlybump17.wlib.adapter.v1_21_r7;

import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.jetbrains.annotations.NotNull;

import java.util.*;

public class AttributeAdapter extends com.wizardlybump17.wlib.adapter.AttributeAdapter {

public static final @NotNull Map<String, Attribute> ATTRIBUTES;

static {
Map<String, Attribute> attributes = new HashMap<>();
attributes.put("GENERIC_MAX_HEALTH", Attribute.MAX_HEALTH);
attributes.put("GENERIC_FOLLOW_RANGE", Attribute.FOLLOW_RANGE);
attributes.put("GENERIC_KNOCKBACK_RESISTANCE", Attribute.KNOCKBACK_RESISTANCE);
attributes.put("GENERIC_MOVEMENT_SPEED", Attribute.MOVEMENT_SPEED);
attributes.put("GENERIC_FLYING_SPEED", Attribute.FLYING_SPEED);
attributes.put("GENERIC_ATTACK_DAMAGE", Attribute.ATTACK_DAMAGE);
attributes.put("GENERIC_ATTACK_KNOCKBACK", Attribute.ATTACK_KNOCKBACK);
attributes.put("GENERIC_ATTACK_SPEED", Attribute.ATTACK_SPEED);
attributes.put("GENERIC_ARMOR", Attribute.ARMOR);
attributes.put("GENERIC_ARMOR_TOUGHNESS", Attribute.ARMOR_TOUGHNESS);
attributes.put("GENERIC_FALL_DAMAGE_MULTIPLIER", Attribute.FALL_DAMAGE_MULTIPLIER);
attributes.put("GENERIC_LUCK", Attribute.LUCK);
attributes.put("GENERIC_MAX_ABSORPTION", Attribute.MAX_ABSORPTION);
attributes.put("GENERIC_SAFE_FALL_DISTANCE", Attribute.SAFE_FALL_DISTANCE);
attributes.put("GENERIC_SCALE", Attribute.SCALE);
attributes.put("GENERIC_STEP_HEIGHT", Attribute.STEP_HEIGHT);
attributes.put("GENERIC_GRAVITY", Attribute.GRAVITY);
attributes.put("GENERIC_JUMP_STRENGTH", Attribute.JUMP_STRENGTH);
attributes.put("PLAYER_BLOCK_INTERACTION_RANGE", Attribute.BLOCK_INTERACTION_RANGE);
attributes.put("PLAYER_ENTITY_INTERACTION_RANGE", Attribute.ENTITY_INTERACTION_RANGE);
attributes.put("PLAYER_BLOCK_BREAK_SPEED", Attribute.BLOCK_BREAK_SPEED);
attributes.put("ZOMBIE_SPAWN_REINFORCEMENTS", Attribute.SPAWN_REINFORCEMENTS);
ATTRIBUTES = Collections.unmodifiableMap(attributes);
}

@Override
public Attribute getAttribute(@NotNull String name) {
Attribute converted = ATTRIBUTES.get(name.toUpperCase());
if (converted != null)
return converted;
return Registry.ATTRIBUTE.get(NamespacedKey.fromString(name.toLowerCase()));
}

@Override
public @NotNull Map<String, Object> serialize(@NotNull Multimap<Attribute, AttributeModifier> attributes) {
Map<String, Object> result = new TreeMap<>();
for (Attribute attribute : attributes.keySet())
result.put(attribute.getKey().toString(), List.copyOf(attributes.get(attribute)));
return result;
}

@SuppressWarnings("unchecked")
@Override
public @NotNull Multimap<Attribute, AttributeModifier> deserialize(@NotNull Map<String, ? extends Object> serialized) {
Multimap<Attribute, AttributeModifier> result = TreeMultimap.create(
Comparator.comparing(attribute -> attribute.getKey().toString()),
Comparator.comparing(AttributeModifier::getKey)
.thenComparing(AttributeModifier::getAmount)
.thenComparing(AttributeModifier::getOperation)
);
serialized.forEach((attribute, modifiers) -> {
if (modifiers != null)
for (AttributeModifier modifier : ((Collection<AttributeModifier>) modifiers))
result.put(getAttribute(attribute), modifier);
});
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package com.wizardlybump17.wlib.adapter.v1_21_r7;

import com.wizardlybump17.wlib.util.ReflectionUtil;
import net.minecraft.nbt.*;
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.util.*;

public class ItemAdapter extends com.wizardlybump17.wlib.adapter.ItemAdapter {

public static final @NotNull Class<?> CRAFT_META_ITEM = ReflectionUtil.getClass("org.bukkit.craftbukkit.inventory.CraftMetaItem");
public static final @NotNull Field CUSTOM_TAG = ReflectionUtil.getField("customTag", CRAFT_META_ITEM);

@Override
public void transferPersistentData(@NotNull PersistentDataContainer from, @NotNull PersistentDataContainer to) {
Map<String, Tag> tags = ((CraftPersistentDataContainer) to).getRaw();
tags.clear();
tags.putAll(((CraftPersistentDataContainer) from).getTagsCloned());
}

@Override
public void copyPersistentData(@NotNull PersistentDataContainer from, @NotNull PersistentDataContainer to) {
((CraftPersistentDataContainer) to).getRaw().putAll(((CraftPersistentDataContainer) from).getTagsCloned());
}

@Override
public void setDamage(@NotNull ItemMeta meta, @Nullable Integer damage) {
if (!(meta instanceof Damageable damageable))
return;

if (damage == null)
damageable.resetDamage();
else
damageable.setDamage(damage);
}

@Override
public @Nullable Integer getDamage(@NotNull ItemMeta meta) {
return meta instanceof Damageable damageable && damageable.hasDamage() ? damageable.getDamage() : null;
}

@Override
public @NotNull Map<String, Object> getCustomData(@NotNull ItemMeta meta) {
Map<String, Object> result = new HashMap<>();

CompoundTag tag = ReflectionUtil.getFieldValue(CUSTOM_TAG, meta);
if (tag == null)
return result;

for (String key : tag.keySet()) {
Tag data = tag.get(key);
if (data != null)
result.put(key, fromNBT(data));
}

return result;
}

@Override
public void setCustomData(@NotNull ItemMeta meta, @NotNull Map<String, Object> customData) {
CompoundTag tag = new CompoundTag();
for (Map.Entry<String, Object> entry : customData.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
tag.put(key, toNBT(value));
}

ReflectionUtil.setFieldValue(CUSTOM_TAG, meta, tag);
}

@Override
protected @NotNull Tag toNBT(@NotNull Object java) {
return switch (java) {
case Byte b -> ByteTag.valueOf(b);
case Short s -> ShortTag.valueOf(s);
case Integer i -> IntTag.valueOf(i);
case Long l -> LongTag.valueOf(l);
case Float f -> FloatTag.valueOf(f);
case Double d -> DoubleTag.valueOf(d);

case Boolean b -> ByteTag.valueOf(b);

case String string -> StringTag.valueOf(string);

case byte[] byteArray -> new ByteArrayTag(byteArray);
case Byte[] byteArray -> {
byte[] array = new byte[byteArray.length];
for (int i = 0; i < byteArray.length; i++)
array[i] = byteArray[i];
yield new ByteArrayTag(array);
}
case int[] intArray -> new IntArrayTag(intArray);
case Integer[] intArray -> {
int[] array = new int[intArray.length];
for (int i = 0; i < intArray.length; i++)
array[i] = intArray[i];
yield new IntArrayTag(array);
}
case long[] longArray -> new LongArrayTag(longArray);
case Long[] longArray -> {
long[] array = new long[longArray.length];
for (int i = 0; i < longArray.length; i++)
array[i] = longArray[i];
yield new LongArrayTag(array);
}

case Collection<?> collection -> {
List<Tag> values = new ArrayList<>(collection.size());
for (Object object : collection) {
Tag tag = toNBT(object);
values.add(tag);
}
yield new ListTag(values);
}

case Map<?, ?> map -> {
Map<String, Tag> values = new HashMap<>(map.size());
map.forEach((key, value) -> values.put(String.valueOf(key), toNBT(value)));

CompoundTag tag = new CompoundTag();
values.forEach(tag::put);
yield tag;
}

default -> throw new UnsupportedOperationException("Unsupported Java type: " + java);
};
}

@Override
protected @NotNull Object fromNBT(@NotNull Object nbt) {
return switch (nbt) {
case ByteTag tag -> tag.byteValue();
case ShortTag tag -> tag.shortValue();
case IntTag tag -> tag.intValue();
case LongTag tag -> tag.longValue();
case FloatTag tag -> tag.floatValue();
case DoubleTag tag -> tag.doubleValue();

case StringTag tag -> tag.value();

case ByteArrayTag tag -> tag.getAsByteArray();
case IntArrayTag tag -> tag.getAsIntArray();
case LongArrayTag tag -> tag.getAsLongArray();

case CollectionTag tag -> {
List<Object> list = new ArrayList<>(tag.size());
for (Tag value : tag)
list.add(fromNBT(value));
yield list;
}

case CompoundTag tag -> {
Map<String, Object> map = new HashMap<>(tag.size());
for (String key : tag.keySet()) {
Tag value = tag.get(key);
if (value != null)
map.put(key, fromNBT(value));
}
yield map;
}

default -> throw new UnsupportedOperationException("Unsupported NBT type: " + nbt);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.wizardlybump17.wlib.adapter.v1_21_r7.player;

import com.wizardlybump17.wlib.util.ReflectionUtil;
import org.bukkit.conversations.Conversation;
import org.bukkit.craftbukkit.conversations.ConversationTracker;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class PlayerAdapter extends com.wizardlybump17.wlib.adapter.player.PlayerAdapter {

public static final @NotNull Field CONVERSATION_TRACKER = ReflectionUtil.getField("conversationTracker", CraftPlayer.class);
public static final @NotNull Field CONVERSATION_QUEUE = ReflectionUtil.getField("conversationQueue", ConversationTracker.class);

@Override
public @Nullable Conversation getConversation(@NotNull Player player) {
return getConversationQueue(player).getFirst();
}

@Override
public @NotNull List<Conversation> getConversationQueue(@NotNull Player player) {
return ReflectionUtil.getFieldValue(CONVERSATION_QUEUE, ReflectionUtil.getFieldValue(CONVERSATION_TRACKER, player));
}

@Override
public @NotNull List<Conversation> abandonConversations(@NotNull Player player, @NotNull Predicate<Conversation> filter) {
List<Conversation> queue = getConversationQueue(player);
List<Conversation> removed = new ArrayList<>(queue);
queue.removeIf(filter);
removed.removeAll(queue);
return removed;
}
}