Skip to content

Commit

Permalink
Simplified impl. of syncing command tags
Browse files Browse the repository at this point in the history
  • Loading branch information
eggohito committed May 29, 2024
1 parent ea1590f commit 42ed2b1
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 192 deletions.
2 changes: 2 additions & 0 deletions src/main/java/io/github/eggohito/eggolib/Eggolib.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.github.apace100.apoli.util.NamespaceAlias;
import io.github.eggohito.eggolib.compat.EggolibModCompat;
import io.github.eggohito.eggolib.data.EggolibClassData;
import io.github.eggohito.eggolib.data.EggolibTrackedDataHandlers;
import io.github.eggohito.eggolib.integration.EggolibPowerIntegration;
import io.github.eggohito.eggolib.networking.EggolibPacketsC2S;
import io.github.eggohito.eggolib.registry.factory.*;
Expand Down Expand Up @@ -99,6 +100,7 @@ public void onInitialize() {

// Register callbacks used by some power types
EggolibPowerIntegration.register();
EggolibTrackedDataHandlers.register();

// Notify client/server that eggolib has been initialized and if it should perform a version check
LOGGER.info("[{}] Version {} has been initialized. Egg!", MOD_ID, version);
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import io.github.apace100.apoli.power.factory.condition.ConditionFactory;
import io.github.apace100.calio.data.SerializableData;
import io.github.eggohito.eggolib.Eggolib;
import io.github.eggohito.eggolib.component.EggolibComponents;
import net.minecraft.entity.Entity;
import net.minecraft.util.Pair;

Expand All @@ -14,8 +13,8 @@ public class HasMatchingTagCondition {

public static boolean condition(SerializableData.Instance data, Pair<Entity, Entity> actorAndTarget) {

Set<String> actorCommandTags = EggolibComponents.MISC.get(actorAndTarget.getLeft()).getCommandTags();
Set<String> targetCommandTags = EggolibComponents.MISC.get(actorAndTarget.getRight()).getCommandTags();
Set<String> actorCommandTags = actorAndTarget.getLeft().getCommandTags();
Set<String> targetCommandTags = actorAndTarget.getRight().getCommandTags();

return !Collections.disjoint(actorCommandTags, targetCommandTags);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import io.github.apace100.calio.data.SerializableData;
import io.github.apace100.calio.data.SerializableDataTypes;
import io.github.eggohito.eggolib.Eggolib;
import io.github.eggohito.eggolib.component.EggolibComponents;
import net.minecraft.entity.Entity;

import java.util.Collections;
Expand All @@ -16,7 +15,7 @@ public class HasTagCondition {
public static boolean condition(SerializableData.Instance data, Entity entity) {

Set<String> specifiedCommandTags = new HashSet<>();
Set<String> commandTags = EggolibComponents.MISC.get(entity).getCommandTags();
Set<String> commandTags = entity.getCommandTags();

data.ifPresent("tag", specifiedCommandTags::add);
data.ifPresent("tags", specifiedCommandTags::addAll);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.github.eggohito.eggolib.data;

import net.minecraft.entity.data.TrackedDataHandler;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.network.PacketByteBuf;

import java.util.HashSet;
import java.util.Set;

public class EggolibTrackedDataHandlers {

public static final TrackedDataHandler<Set<String>> STRING_SET = TrackedDataHandler.of(
(buf, strings) -> buf.writeCollection(strings, PacketByteBuf::writeString),
buf -> buf.readCollection(value -> new HashSet<>(), PacketByteBuf::readString)
);

public static void register() {
TrackedDataHandlerRegistry.register(STRING_SET);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.google.gson.*;
import io.github.eggohito.eggolib.Eggolib;
import io.github.eggohito.eggolib.component.EggolibComponents;
import net.minecraft.entity.Entity;
import net.minecraft.loot.condition.LootCondition;
import net.minecraft.loot.condition.LootConditionType;
Expand Down Expand Up @@ -42,16 +41,15 @@ public boolean test(LootContext lootContext) {
return false;
}

Set<String> scoreboardTags = EggolibComponents.MISC.get(entity).getCommandTags();
Set<String> specifiedScoreboardTags = new HashSet<>();
Set<String> commandTags = entity.getCommandTags();
Set<String> specifiedCommandTags = new HashSet<>();

this.commandTag.ifPresent(specifiedCommandTags::add);
this.commandTags.ifPresent(specifiedCommandTags::addAll);

this.commandTag.ifPresent(specifiedScoreboardTags::add);
this.commandTags.ifPresent(specifiedScoreboardTags::addAll);

return specifiedScoreboardTags.isEmpty()
? !scoreboardTags.isEmpty()
: !Collections.disjoint(scoreboardTags, specifiedScoreboardTags);
return specifiedCommandTags.isEmpty()
? !commandTags.isEmpty()
: !Collections.disjoint(commandTags, specifiedCommandTags);

}

Expand Down
105 changes: 80 additions & 25 deletions src/main/java/io/github/eggohito/eggolib/mixin/EntityMixin.java
Original file line number Diff line number Diff line change
@@ -1,68 +1,123 @@
package io.github.eggohito.eggolib.mixin;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import io.github.apace100.apoli.component.PowerHolderComponent;
import io.github.eggohito.eggolib.component.EggolibComponents;
import io.github.eggohito.eggolib.Eggolib;
import io.github.eggohito.eggolib.data.EggolibTrackedDataHandlers;
import io.github.eggohito.eggolib.power.GameEventListenerPower;
import io.github.eggohito.eggolib.power.InvisibilityPower;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
import net.minecraft.world.event.listener.EntityGameEventHandler;
import org.spongepowered.asm.mixin.Final;
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 org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.LinkedList;
import java.util.Set;
import java.util.function.BiConsumer;

@Mixin(Entity.class)
public abstract class EntityMixin {

@Shadow
private World world;
@Final
protected DataTracker dataTracker;

@Inject(method = "addCommandTag", at = @At("TAIL"))
private void eggolib$onAddCommandTag(String tag, CallbackInfoReturnable<Boolean> cir) {
if (cir.getReturnValue()) {
EggolibComponents.MISC.get(this).addCommandTag(tag);
@Shadow
protected boolean firstUpdate;

@Shadow
public abstract World getWorld();

@Shadow
@Final
public Set<String> commandTags;

@Unique
private static final TrackedData<Set<String>> COMMAND_TAGS = DataTracker.registerData(Entity.class, EggolibTrackedDataHandlers.STRING_SET);

@Unique
private boolean eggolib$dirtiedCommandTags;

@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;initDataTracker()V"))
private void eggolib$registerCommandTagsDataTracker(EntityType<?> type, World world, CallbackInfo ci) {

try {
this.dataTracker.startTracking(COMMAND_TAGS, Set.of());
}
}

@Inject(method = "removeScoreboardTag", at = @At("TAIL"))
private void eggolib$onRemoveCommandTag(String tag, CallbackInfoReturnable<Boolean> cir) {
EggolibComponents.MISC.get(this).removeCommandTag(tag);
}
catch (Exception e) {
Eggolib.LOGGER.warn("Couldn't register data tracker for command tags", e);
}

@Inject(method = "getCommandTags", at = @At("RETURN"))
private void eggolib$onGetCommandTag(CallbackInfoReturnable<Set<String>> cir) {
EggolibComponents.MISC.get(this).setCommandTags(cir.getReturnValue());
}

@ModifyReturnValue(method = "addCommandTag", at = @At("RETURN"))
private boolean eggolib$trackAddedCommandTag(boolean original) {
return original
&& (this.eggolib$dirtiedCommandTags = true);
}

@ModifyReturnValue(method = "removeScoreboardTag", at = @At("RETURN"))
private boolean eggolib$trackRemovedCommandTag(boolean original) {
return original
&& (this.eggolib$dirtiedCommandTags = true);
}

@ModifyReturnValue(method = "getCommandTags", at = @At("RETURN"))
private Set<String> eggolib$queryTrackedCommandTags(Set<String> original) {
return this.dataTracker.containsKey(COMMAND_TAGS)
? this.dataTracker.get(COMMAND_TAGS)
: original;
}

@Inject(method = "baseTick", at = @At("TAIL"))
private void eggolib$syncCommandTags(CallbackInfo ci) {
@Inject(method = "baseTick", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/Entity;firstUpdate:Z"))
private void eggolib$updateTrackedCommandTags(CallbackInfo ci) {

if (!this.world.isClient) {
EggolibComponents.MISC.get(this).sync(false);
if (this.dataTracker.containsKey(COMMAND_TAGS) && ((this.firstUpdate && !this.getWorld().isClient) || this.eggolib$dirtiedCommandTags)) {
this.dataTracker.set(COMMAND_TAGS, Set.copyOf(this.commandTags));
}

this.eggolib$dirtiedCommandTags = false;

}

@Inject(method = "isInvisibleTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getScoreboardTeam()Lnet/minecraft/scoreboard/AbstractTeam;"), cancellable = true)
private void eggolib$invisibilityException(PlayerEntity playerEntity, CallbackInfoReturnable<Boolean> cir) {
if (PowerHolderComponent.hasPower((Entity) (Object) this, InvisibilityPower.class, eip -> !eip.doesApply(playerEntity))) {
cir.setReturnValue(false);
@WrapOperation(method = "isInvisibleTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isInvisible()Z"))
private boolean eggolib$specificallyInvisibleTo(Entity entity, Operation<Boolean> original, PlayerEntity viewer) {

if (viewer == null) {
return original.call(entity);
}

return PowerHolderComponent.KEY.maybeGet(entity)
.map(pc -> pc.getPowers(InvisibilityPower.class, true))
.orElseGet(LinkedList::new)
.stream()
.anyMatch(p -> p.isActive() && p.doesApply(viewer));

}

@Inject(method = "updateEventHandler", at = @At("HEAD"))
private void eggolib$updateCustomEventHandlers(BiConsumer<EntityGameEventHandler<?>, ServerWorld> callback, CallbackInfo ci) {
if (world instanceof ServerWorld serverWorld) {
PowerHolderComponent.getPowers((Entity) (Object) this, GameEventListenerPower.class).forEach(p -> callback.accept(p.getGameEventHandler(), serverWorld));

if (this.getWorld() instanceof ServerWorld serverWorld) {
PowerHolderComponent
.getPowers((Entity) (Object) this, GameEventListenerPower.class)
.forEach(p -> callback.accept(p.getGameEventHandler(), serverWorld));
}

}

}
Loading

0 comments on commit 42ed2b1

Please sign in to comment.