Skip to content

Commit

Permalink
Added stuff related to command tags
Browse files Browse the repository at this point in the history
+ Added a CCA synced component for command tags; allows for checking for command tags in the client
+ Added `has_command_tag` entity condition type
  • Loading branch information
eggohito committed Nov 5, 2023
1 parent ce5a44b commit f4183e8
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/main/java/io/github/apace100/apoli/Apoli.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import dev.onyxstudios.cca.api.v3.entity.RespawnCopyStrategy;
import io.github.apace100.apoli.command.PowerCommand;
import io.github.apace100.apoli.command.ResourceCommand;
import io.github.apace100.apoli.component.CommandTagComponent;
import io.github.apace100.apoli.component.CommandTagComponentImpl;
import io.github.apace100.apoli.component.PowerHolderComponent;
import io.github.apace100.apoli.component.PowerHolderComponentImpl;
import io.github.apace100.apoli.global.GlobalPowerSetLoader;
Expand All @@ -30,6 +32,7 @@
import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditions;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.advancement.criterion.Criteria;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.registry.Registries;
import net.minecraft.resource.ResourceType;
Expand Down Expand Up @@ -128,6 +131,10 @@ public void registerEntityComponentFactories(EntityComponentFactoryRegistry regi
.impl(PowerHolderComponentImpl.class)
.respawnStrategy(RespawnCopyStrategy.ALWAYS_COPY)
.end(PowerHolderComponentImpl::new);
registry.beginRegistration(Entity.class, CommandTagComponent.KEY)
.impl(CommandTagComponentImpl.class)
.respawnStrategy(RespawnCopyStrategy.ALWAYS_COPY)
.end(CommandTagComponentImpl::new);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.github.apace100.apoli.component;

import dev.onyxstudios.cca.api.v3.component.ComponentKey;
import dev.onyxstudios.cca.api.v3.component.ComponentRegistry;
import dev.onyxstudios.cca.api.v3.component.load.ServerLoadAwareComponent;
import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent;
import io.github.apace100.apoli.Apoli;
import org.jetbrains.annotations.ApiStatus;

import java.util.Set;

public interface CommandTagComponent extends AutoSyncedComponent, ServerLoadAwareComponent {

ComponentKey<CommandTagComponent> KEY = ComponentRegistry.getOrCreate(Apoli.identifier("command_tags"), CommandTagComponent.class);

Set<String> getTags();

@ApiStatus.Internal
void setTags(Set<String> commandTags);

@ApiStatus.Internal
boolean addTag(String commandTag);

@ApiStatus.Internal
boolean removeTag(String commandTag);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.github.apace100.apoli.component;

import io.github.apace100.apoli.mixin.EntityAccessor;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.NbtString;

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

public class CommandTagComponentImpl implements CommandTagComponent {

private final Set<String> commandTags;
private final Entity provider;

public CommandTagComponentImpl(Entity provider) {
this.commandTags = new HashSet<>();
this.provider = provider;
}

@Override
public Set<String> getTags() {
return commandTags;
}

@Override
public void setTags(Set<String> commandTags) {
this.commandTags.clear();
this.commandTags.addAll(commandTags);
}

@Override
public boolean addTag(String commandTag) {
return this.commandTags.add(commandTag);
}

@Override
public boolean removeTag(String commandTag) {
return this.commandTags.remove(commandTag);
}

@Override
public void loadServerside() {

Set<String> originalCommandTags = ((EntityAccessor) provider).getOriginalCommandTags();

if (!commandTags.equals(originalCommandTags)) {
this.setTags(originalCommandTags);
CommandTagComponent.KEY.sync(provider);
}

}

@Override
public void readFromNbt(NbtCompound tag) {

NbtList commandTagsNbt = tag.getList("Tags", NbtElement.STRING_TYPE);
this.commandTags.clear();

for (int i = 0; i < commandTagsNbt.size(); ++i) {
this.commandTags.add(commandTagsNbt.getString(i));
}

}

@Override
public void writeToNbt(NbtCompound tag) {

NbtList commandTagsNbt = new NbtList();
this.commandTags.stream()
.map(NbtString::of)
.forEach(commandTagsNbt::add);

tag.put("Tags", commandTagsNbt);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@

import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;

import java.util.Set;

@Mixin(Entity.class)
public interface EntityAccessor {

@Invoker
boolean callIsBeingRainedOn();

@Accessor("commandTags")
Set<String> getOriginalCommandTags();

}
49 changes: 49 additions & 0 deletions src/main/java/io/github/apace100/apoli/mixin/EntityMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.github.apace100.apoli.access.MovingEntity;
import io.github.apace100.apoli.access.SubmergableEntity;
import io.github.apace100.apoli.access.WaterMovingEntity;
import io.github.apace100.apoli.component.CommandTagComponent;
import io.github.apace100.apoli.component.PowerHolderComponent;
import io.github.apace100.apoli.power.*;
import io.github.apace100.calio.Calio;
Expand Down Expand Up @@ -81,6 +82,10 @@ private void makeFullyFireImmune(CallbackInfoReturnable<Boolean> cir) {

@Shadow protected Object2DoubleMap<TagKey<Fluid>> fluidHeight;

@Shadow public abstract World getWorld();

@Shadow public abstract Set<String> getCommandTags();

@Inject(method = "isTouchingWater", at = @At("HEAD"), cancellable = true)
private void makeEntitiesIgnoreWater(CallbackInfoReturnable<Boolean> cir) {
if(PowerHolderComponent.hasPower((Entity)(Object)this, IgnoreWaterPower.class)) {
Expand Down Expand Up @@ -281,4 +286,48 @@ private void modifyGlowingColorFromPower(CallbackInfoReturnable<Integer> cir) {
return !PreventEntityCollisionPower.doesApply((Entity) (Object) this, other) && original;
}

@Unique
private boolean apoli$shouldSyncCommandTags = false;

@Inject(method = "addCommandTag", at = @At("TAIL"))
private void apoli$addCommandTagToComponent(String tag, CallbackInfoReturnable<Boolean> cir) {

boolean result = CommandTagComponent.KEY.get(this).addTag(tag);

if (result) {
apoli$shouldSyncCommandTags = true;
}

}

@Inject(method = "removeScoreboardTag", at = @At("TAIL"))
private void apoli$removeCommandTagFromComponent(String tag, CallbackInfoReturnable<Boolean> cir) {

boolean result = CommandTagComponent.KEY.get(this).removeTag(tag);

if (result) {
apoli$shouldSyncCommandTags = true;
}

}

@ModifyReturnValue(method = "getCommandTags", at = @At("RETURN"))
private Set<String> apoli$overrideCommandTags(Set<String> original) {
return CommandTagComponent.KEY.get(this).getTags();
}

@Inject(method = "baseTick", at = @At("TAIL"))
private void apoli$syncCommandTags(CallbackInfo ci) {

if (!apoli$shouldSyncCommandTags || this.getWorld().isClient) {
return;
}

CommandTagComponent.KEY.get(this).setTags(((EntityAccessor) this).getOriginalCommandTags());
CommandTagComponent.KEY.sync(this);

apoli$shouldSyncCommandTags = false;

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ public static void register() {
register(InThunderstormCondition.getFactory());
register(AdvancementCondition.getFactory());
register(SetSizeCondition.getFactory());
register(HasCommandTagCondition.getFactory());
}

private static void register(ConditionFactory<Entity> conditionFactory) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.github.apace100.apoli.power.factory.condition.entity;

import io.github.apace100.apoli.Apoli;
import io.github.apace100.apoli.power.factory.condition.ConditionFactory;
import io.github.apace100.apoli.util.IdentifierAlias;
import io.github.apace100.calio.data.SerializableData;
import io.github.apace100.calio.data.SerializableDataTypes;
import net.minecraft.entity.Entity;

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

public class HasCommandTagCondition {

public static boolean condition(SerializableData.Instance data, Entity entity) {

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

data.ifPresent("command_tag", specifiedCommandTags::add);
data.ifPresent("command_tags", specifiedCommandTags::addAll);

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

}

public static ConditionFactory<Entity> getFactory() {
IdentifierAlias.addPathAlias("has_tag", "has_command_tag");
return new ConditionFactory<>(
Apoli.identifier("has_command_tag"),
new SerializableData()
.add("tag", SerializableDataTypes.STRING, null)
.addFunctionedDefault("command_tag", SerializableDataTypes.STRING, data -> data.get("tag"))
.add("tags", SerializableDataTypes.STRINGS, null)
.addFunctionedDefault("command_tags", SerializableDataTypes.STRINGS, data -> data.get("tags")),
HasCommandTagCondition::condition
);
}

}
3 changes: 2 additions & 1 deletion src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
],
"custom": {
"cardinal-components": [
"apoli:powers"
"apoli:powers",
"apoli:command_tags"
],
"modmenu": {
"badges": ["library"]
Expand Down

0 comments on commit f4183e8

Please sign in to comment.