Skip to content

Commit

Permalink
Add support for server side entity attributes, fix support for polyme…
Browse files Browse the repository at this point in the history
…r things used in enchantment definitions
  • Loading branch information
Patbox committed Jun 16, 2024
1 parent 751ca1b commit 229ccbb
Show file tree
Hide file tree
Showing 23 changed files with 366 additions and 44 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fabric_version=0.100.0+1.21

maven_group = eu.pb4

mod_version = 0.9.1
mod_version = 0.9.2

minecraft_version_supported = ">=1.20.5-"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
import net.minecraft.registry.Registries;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Util;
import net.minecraft.village.VillagerProfession;
Expand All @@ -29,6 +31,7 @@ private PolymerEntityUtils() {
}

private static final Set<EntityType<?>> ENTITY_TYPES = new ObjectOpenCustomHashSet<>(CommonImplUtils.IDENTITY_HASH);
private static final Set<EntityAttribute> ENTITY_ATTRIBUTES = new ObjectOpenCustomHashSet<>(CommonImplUtils.IDENTITY_HASH);

private static final Map<VillagerProfession, PolymerVillagerProfession> VILLAGER_PROFESSIONS = new Object2ObjectOpenCustomHashMap<>(CommonImplUtils.IDENTITY_HASH);

Expand All @@ -54,6 +57,18 @@ public static void registerType(EntityType<?>... types) {
}
}


/**
* Marks EntityAttribute as server-side only
*/
@SafeVarargs
public static void registerAttribute(RegistryEntry<EntityAttribute>... attributes) {
for (var type : attributes) {
ENTITY_ATTRIBUTES.add(type.value());
RegistrySyncUtils.setServerEntry(Registries.ATTRIBUTE, type.value());
}
}

/**
* Marks EntityTypes as server-side only
*
Expand All @@ -75,10 +90,14 @@ public static PolymerVillagerProfession getPolymerProfession(VillagerProfession
*
* @param type EntityType
*/
public static boolean isRegisteredEntityType(EntityType<?> type) {
public static boolean isPolymerEntityType(EntityType<?> type) {
return ENTITY_TYPES.contains(type);
}

public static boolean isPolymerEntityAttribute(RegistryEntry<EntityAttribute> type) {
return ENTITY_ATTRIBUTES.contains(type.value());
}

/**
* @param type EntityType
* @return Array of default DataTracker entries for entity type
Expand Down Expand Up @@ -140,4 +159,10 @@ public static Entity getEntityContext(Packet<?> packet) {
public static void sendEntityType(ServerPlayerEntity player, int entityId, EntityType<?> entityType) {
PolymerServerProtocol.sendEntityInfo(player.networkHandler, entityId, entityType);
}

@Deprecated
public static boolean isRegisteredEntityType(EntityType<?> type) {
return ENTITY_TYPES.contains(type);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@
import eu.pb4.polymer.common.api.events.FunctionEvent;
import eu.pb4.polymer.common.impl.CompatStatus;
import eu.pb4.polymer.core.api.block.PolymerBlockUtils;
import eu.pb4.polymer.core.api.entity.PolymerEntityUtils;
import eu.pb4.polymer.core.api.other.PolymerComponent;
import eu.pb4.polymer.core.api.utils.PolymerUtils;
import eu.pb4.polymer.core.impl.PolymerImpl;
import eu.pb4.polymer.core.impl.PolymerImplUtils;
import eu.pb4.polymer.core.impl.TransformingDataComponent;
import eu.pb4.polymer.core.impl.TransformingComponent;
import eu.pb4.polymer.core.impl.compat.polymc.PolyMcUtils;
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
import eu.pb4.polymer.rsm.api.RegistrySyncUtils;
import net.minecraft.component.ComponentType;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.EnchantmentEffectComponentTypes;
import net.minecraft.component.type.*;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.DefaultAttributeRegistry;
import net.minecraft.item.BlockPredicatesChecker;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
Expand Down Expand Up @@ -294,12 +297,26 @@ public static boolean isPolymerServerItem(ItemStack itemStack, @Nullable ServerP
if (!PolymerComponent.canSync(x.getKey(), x.getValue().orElse(null), ctx)) {
return true;
} else if (x.getValue() != null && x.getValue().isPresent()
&& x.getValue().get() instanceof TransformingDataComponent t
&& x.getValue().get() instanceof TransformingComponent t
&& t.polymer$requireModification(player)) {
return true;
}
}

if (itemStack.contains(DataComponentTypes.ENCHANTMENTS) && itemStack.getOrDefault(DataComponentTypes.ATTRIBUTE_MODIFIERS, AttributeModifiersComponent.DEFAULT).showInTooltip()) {
for (var ench : itemStack.get(DataComponentTypes.ENCHANTMENTS).getEnchantments()) {
var attributes = ench.value().getEffect(EnchantmentEffectComponentTypes.ATTRIBUTES);
if (attributes != null) {
for (var attr : attributes) {
if (PolymerEntityUtils.isPolymerEntityAttribute(attr.attribute())
&& DefaultAttributeRegistry.get(EntityType.PLAYER).has(attr.attribute())) {
return true;
}
}
}
}
}

if (CompatStatus.POLYMER_RESOURCE_PACK) {
var display = itemStack.get(DataComponentTypes.DYED_COLOR);
if (display != null) {
Expand Down Expand Up @@ -400,7 +417,7 @@ public static ItemStack createItemStack(ItemStack itemStack, TooltipType tooltip
var key = COMPONENTS_TO_COPY[i];
var x = itemStack.get(key);

if (x instanceof TransformingDataComponent t) {
if (x instanceof TransformingComponent t) {
//noinspection unchecked,rawtypes
out.set((ComponentType) key, t.polymer$getTransformed(player));
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package eu.pb4.polymer.core.api.other;

import com.mojang.serialization.*;
import eu.pb4.polymer.common.api.PolymerCommonUtils;
import eu.pb4.polymer.core.api.utils.PolymerObject;
import eu.pb4.polymer.core.api.utils.PolymerUtils;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.AllOfEnchantmentEffects;
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
import net.minecraft.enchantment.effect.EnchantmentLocationBasedEffect;
import net.minecraft.enchantment.effect.EnchantmentValueEffect;

import java.util.List;
import java.util.stream.Stream;

public class PolymerMapCodec<T> extends MapCodec<T> implements PolymerObject {
private final MapCodec<T> selfCodec;
private final MapCodec<Object> fallbackCodec;
private final Object fallbackValue;

public <K> PolymerMapCodec(MapCodec<T> selfCodec, MapCodec<K> fallbackCodec, K fallbackValue) {
this.selfCodec = selfCodec;
//noinspection unchecked
this.fallbackCodec = (MapCodec<Object>) fallbackCodec;
this.fallbackValue = fallbackValue;
}

public static <T extends EnchantmentValueEffect> MapCodec<T> ofEnchantmentValueEffect(MapCodec<T> codec) {
return new PolymerMapCodec<T>(codec, AllOfEnchantmentEffects.ValueEffects.CODEC, new AllOfEnchantmentEffects.ValueEffects(List.of()));
}

public static <T extends EnchantmentLocationBasedEffect> MapCodec<T> ofEnchantmentLocationBasedEffect(MapCodec<T> codec) {
return new PolymerMapCodec<T>(codec, AllOfEnchantmentEffects.LocationBasedEffects.CODEC, new AllOfEnchantmentEffects.LocationBasedEffects(List.of()));
}

public static <T extends EnchantmentEntityEffect> MapCodec<T> ofEnchantmentEntityEffect(MapCodec<T> codec) {
return new PolymerMapCodec<T>(codec, AllOfEnchantmentEffects.EntityEffects.CODEC, new AllOfEnchantmentEffects.EntityEffects(List.of()));
}

public static <T extends EnchantmentLevelBasedValue> MapCodec<T> ofEnchantmentLevelBasedValue(MapCodec<T> codec) {
return new PolymerMapCodec<T>(codec, EnchantmentLevelBasedValue.Constant.TYPE_CODEC, new EnchantmentLevelBasedValue.Constant(0));
}

@Override
public <T1> Stream<T1> keys(DynamicOps<T1> ops) {
return this.selfCodec.keys(ops);
}

@Override
public <T1> DataResult<T> decode(DynamicOps<T1> ops, MapLike<T1> input) {
return this.selfCodec.decode(ops, input);
}

@Override
public <T1> RecordBuilder<T1> encode(T input, DynamicOps<T1> ops, RecordBuilder<T1> prefix) {
if (PolymerCommonUtils.isServerNetworkingThread()) {
return this.fallbackCodec.encode(this.fallbackValue, ops, prefix);
}

return this.selfCodec.encode(input, ops, prefix);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ public static Path getClientJar() {
}

public static boolean isServerOnly(Object obj) {
return obj instanceof PolymerObject || (obj instanceof ItemStack stack && PolymerItemUtils.isPolymerServerItem(stack)) || (obj instanceof EntityType<?> type && PolymerEntityUtils.isRegisteredEntityType(type)) || (obj instanceof BlockEntityType<?> typeBE && PolymerBlockUtils.isPolymerBlockEntityType(typeBE)) || (obj instanceof VillagerProfession villagerProfession && PolymerEntityUtils.getPolymerProfession(villagerProfession) != null);

return obj instanceof PolymerObject || (obj instanceof ItemStack stack && PolymerItemUtils.isPolymerServerItem(stack)) || (obj instanceof EntityType<?> type && PolymerEntityUtils.isPolymerEntityType(type)) || (obj instanceof BlockEntityType<?> typeBE && PolymerBlockUtils.isPolymerBlockEntityType(typeBE)) || (obj instanceof VillagerProfession villagerProfession && PolymerEntityUtils.getPolymerProfession(villagerProfession) != null);
}

public static boolean hasResourcePack(@Nullable ServerPlayerEntity player, UUID uuid) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package eu.pb4.polymer.core.impl;

public interface PolymericObject {
boolean polymer$isPolymeric();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package eu.pb4.polymer.core.impl;

import net.minecraft.component.ComponentType;
import net.minecraft.server.network.ServerPlayerEntity;

public interface TransformingDataComponent {
public interface TransformingComponent {
Object polymer$getTransformed(ServerPlayerEntity player);
boolean polymer$requireModification(ServerPlayerEntity player);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class PolyMcEntrypoint implements io.github.theepicblock.polymc.api.PolyM
@Override
public void registerPolys(PolyRegistry registry) {
for (var entityType : Registries.ENTITY_TYPE) {
if (PolymerEntityUtils.isRegisteredEntityType(entityType)) {
if (PolymerEntityUtils.isPolymerEntityType(entityType)) {
registry.registerEntityPoly(entityType, (info, entity) -> null);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package eu.pb4.polymer.core.mixin.block;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.mojang.serialization.Codec;
import eu.pb4.polymer.common.api.PolymerCommonUtils;
import eu.pb4.polymer.core.api.block.PolymerBlock;
import eu.pb4.polymer.core.api.block.PolymerBlockUtils;
import eu.pb4.polymer.core.api.entity.PolymerEntityUtils;
import eu.pb4.polymer.core.impl.interfaces.BlockStateExtra;
import net.minecraft.block.BlockState;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.registry.entry.RegistryEntry;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;

import java.util.function.Function;

@Mixin(BlockState.class)
public abstract class BlockStateMixin implements BlockStateExtra {
Expand All @@ -31,4 +42,14 @@ public abstract class BlockStateMixin implements BlockStateExtra {

return false;
}

@ModifyExpressionValue(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;createCodec(Lcom/mojang/serialization/Codec;Ljava/util/function/Function;)Lcom/mojang/serialization/Codec;"))
private static Codec<BlockState> patchCodec(Codec<BlockState> codec) {
return codec.xmap(Function.identity(), content -> { // Encode
if (PolymerCommonUtils.isServerNetworkingThread() && content.getBlock() instanceof PolymerBlock) {
return PolymerBlockUtils.getPolymerBlockState(content);
}
return content;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package eu.pb4.polymer.core.mixin.entity;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.mojang.serialization.Codec;
import eu.pb4.polymer.common.api.PolymerCommonUtils;
import eu.pb4.polymer.core.api.entity.PolymerEntityUtils;
import eu.pb4.polymer.core.api.item.PolymerItemUtils;
import eu.pb4.polymer.core.impl.PolymerImplUtils;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.text.HoverEvent;
import net.minecraft.text.Text;
import net.minecraft.text.Texts;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import xyz.nucleoid.packettweaker.PacketContext;

import java.util.Objects;
import java.util.function.Function;

@Mixin(EntityAttribute.class)
public abstract class EntityAttributeMixin {
@ModifyExpressionValue(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/minecraft/registry/Registry;getEntryCodec()Lcom/mojang/serialization/Codec;"))
private static Codec<RegistryEntry<EntityAttribute>> patchCodec(Codec<RegistryEntry<EntityAttribute>> codec) {
return codec.xmap(Function.identity(), content -> { // Encode
if (PolymerCommonUtils.isServerNetworkingThread() && PolymerEntityUtils.isPolymerEntityAttribute(content)) {
return EntityAttributes.ZOMBIE_SPAWN_REINFORCEMENTS;
}
return content;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import eu.pb4.polymer.core.api.entity.PolymerEntity;
import eu.pb4.polymer.core.api.entity.PolymerEntityUtils;
import eu.pb4.polymer.core.api.utils.PolymerUtils;
import eu.pb4.polymer.common.impl.entity.InternalEntityHelpers;
import eu.pb4.polymer.core.impl.interfaces.EntityAttachedPacket;
Expand Down Expand Up @@ -41,13 +42,21 @@ private static PacketCodec<RegistryByteBuf, EntityAttributesS2CPacket> patchCode
var list = ((EntityAttributesS2CPacketAccessor) p).getEntries();
var vanillaContainer = DefaultAttributeRegistry.get((EntityType<? extends LivingEntity>) type);
for (var entry : packet.getEntries()) {
if (vanillaContainer.has(entry.attribute())) {
if (vanillaContainer.has(entry.attribute()) && !PolymerEntityUtils.isPolymerEntityAttribute(entry.attribute())) {
list.add(entry);
}
}
return p;
} else {
var p = new EntityAttributesS2CPacket(packet.getEntityId(), List.of());
var list = ((EntityAttributesS2CPacketAccessor) p).getEntries();
for (var entry : packet.getEntries()) {
if (!PolymerEntityUtils.isPolymerEntityAttribute(entry.attribute())) {
list.add(entry);
}
}
return p;
}
return packet;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package eu.pb4.polymer.core.mixin.item.component;

import eu.pb4.polymer.core.api.entity.PolymerEntityUtils;
import eu.pb4.polymer.core.impl.TransformingComponent;
import net.minecraft.component.type.AttributeModifiersComponent;
import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;

import java.util.ArrayList;
import java.util.List;

@Mixin(AttributeModifiersComponent.class)
public class AttributeModifiersComponentMixin implements TransformingComponent {
@Shadow @Final private List<AttributeModifiersComponent.Entry> modifiers;

@Shadow @Final private boolean showInTooltip;

@Override
public Object polymer$getTransformed(ServerPlayerEntity player) {
if (!polymer$requireModification(player)) {
return this;
}
var list = new ArrayList<AttributeModifiersComponent.Entry>();
for (var entry : this.modifiers) {
if (!PolymerEntityUtils.isPolymerEntityAttribute(entry.attribute())) {
list.add(entry);
}
}

return new AttributeModifiersComponent(list, this.showInTooltip);
}

@Override
public boolean polymer$requireModification(ServerPlayerEntity player) {
for (var x : this.modifiers) {
if (PolymerEntityUtils.isPolymerEntityAttribute(x.attribute())) {
return true;
}
}
return false;
}
}
Loading

0 comments on commit 229ccbb

Please sign in to comment.