Skip to content

Commit

Permalink
Add ModTag and relevant tags (#27)
Browse files Browse the repository at this point in the history
* Add `ModTag` and relevant tags

* Add `Matchable` meta

* Minor cleanup

* Everything can be static

* Revert `fabric.mod.json` changes

* Correct a serious mistake

* Correct the correction for the serious mistake

* Initial fixes from review

* Don't use impl constants
  • Loading branch information
tal5 committed Aug 15, 2023
1 parent bfc94ec commit 5752a26
Show file tree
Hide file tree
Showing 4 changed files with 302 additions and 0 deletions.
Expand Up @@ -9,11 +9,13 @@ public class ClientizenObjectRegistry {
public static ObjectType<LocationTag> TYPE_LOCATION;
public static ObjectType<MaterialTag> TYPE_MATERIAL;
public static ObjectType<ItemTag> TYPE_ITEM;
public static ObjectType<ModTag> TYPE_MOD;

public static void registerObjects() {
TYPE_ENTITY = ObjectFetcher.registerWithObjectFetcher(EntityTag.class, EntityTag.tagProcessor).setAsNOtherCode().generateBaseTag();
TYPE_LOCATION = ObjectFetcher.registerWithObjectFetcher(LocationTag.class, LocationTag.tagProcessor).setAsNOtherCode().setCanConvertStatic().generateBaseTag();
TYPE_MATERIAL = ObjectFetcher.registerWithObjectFetcher(MaterialTag.class, MaterialTag.tagProcessor).generateBaseTag();
TYPE_ITEM = ObjectFetcher.registerWithObjectFetcher(ItemTag.class, ItemTag.tagProcessor).setAsNOtherCode().generateBaseTag();
TYPE_MOD = ObjectFetcher.registerWithObjectFetcher(ModTag.class, ModTag.tagProcessor).setAsNOtherCode().setCanConvertStatic().generateBaseTag();
}
}
254 changes: 254 additions & 0 deletions src/main/java/com/denizenscript/clientizen/objects/ModTag.java
@@ -0,0 +1,254 @@
package com.denizenscript.clientizen.objects;

import com.denizenscript.clientizen.util.Utilities;
import com.denizenscript.denizencore.events.ScriptEvent;
import com.denizenscript.denizencore.objects.Fetchable;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.objects.core.MapTag;
import com.denizenscript.denizencore.tags.Attribute;
import com.denizenscript.denizencore.tags.ObjectTagProcessor;
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.utilities.CoreUtilities;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.metadata.ModMetadata;

import java.util.Optional;

public class ModTag implements ObjectTag {

// <--[ObjectType]
// @name ModTag
// @prefix mod
// @base ElementTag
// @ExampleTagBase mod[clientizen]
// @ExampleValues <mod[clientizen]>
// @ExampleForReturns
// - narrate "The mod is %VALUE%!"
// @format
// The identity format for mods is the mod id.
// For example, 'mod@clientizen' or 'mod@theprinter'.
//
// @description
// A ModTag represents a currently loaded mod.
//
// This can be either a mod that's been downloaded and installed, a built-in mod, or a mod within another mod (a library mod, for example)
//
// @Matchable
// ModTag matchers:
// "mod" plaintext: always matches.
// Mod id: matches if the mod id matches the input, using advanced matchers.
// -->

@Fetchable("mod")
public static ModTag valueOf(String input, TagContext context) {
if (input.startsWith("mod@")) {
input = input.substring("mod@".length());
}
Optional<ModTag> modTag = FabricLoader.getInstance().getModContainer(CoreUtilities.toLowerCase(input)).map(ModTag::new);
if (modTag.isEmpty()) {
Utilities.echoErrorByContext(context, "valueOf ModTag returning null: '" + input + "' isn't a valid mod id.");
return null;
}
return modTag.get();
}

public static boolean matches(String string) {
if (string.startsWith("mod@")) {
return true;
}
return FabricLoader.getInstance().isModLoaded(CoreUtilities.toLowerCase(string));
}

public final ModContainer modContainer;

public ModTag(ModContainer modContainer) {
this.modContainer = modContainer;
}

public ModMetadata getMetadata() {
return modContainer.getMetadata();
}

public static void register() {

// <--[tag]
// @attribute <ModTag.id>
// @returns ElementTag
// @description
// Returns a mod's id.
// -->
tagProcessor.registerStaticTag(ElementTag.class, "id", (attribute, object) -> {
return new ElementTag(object.getMetadata().getId(), true);
});

// <--[tag]
// @attribute <ModTag.display_name>
// @returns ElementTag
// @description
// Returns a mod's display name.
// -->
tagProcessor.registerStaticTag(ElementTag.class, "display_name", (attribute, object) -> {
return new ElementTag(object.getMetadata().getName(), true);
});

// <--[tag]
// @attribute <ModTag.description>
// @returns ElementTag
// @description
// Returns a mod's description.
// -->
tagProcessor.registerStaticTag(ElementTag.class, "description", (attribute, object) -> {
return new ElementTag(object.getMetadata().getDescription(), true);
});

// <--[tag]
// @attribute <ModTag.version>
// @returns ElementTag
// @description
// Returns a mod's version.
// -->
tagProcessor.registerStaticTag(ElementTag.class, "version", (attribute, object) -> {
return new ElementTag(object.getMetadata().getVersion().getFriendlyString(), true);
});

// <--[tag]
// @attribute <ModTag.authors>
// @returns MapTag
// @description
// Returns a mod's authors, as a map of author name to their contact information.
// The contact information is a map of contact platforms to identification on that platform.
// Note that mods can provide anything here, although most mods will obviously provide valid info.
// -->
tagProcessor.registerStaticTag(MapTag.class, "authors", (attribute, object) -> {
return Utilities.personsToMap(object.getMetadata().getAuthors());
});

// <--[tag]
// @attribute <ModTag.contributors>
// @returns MapTag
// @description
// Returns a mod's contributors, as a map of contributor name to their contact information.
// The contact information is a map of contact platforms to identification on that platform.
// Note that mods can provide anything here, although most mods will obviously provide valid info.
// -->
tagProcessor.registerStaticTag(MapTag.class, "contributors", (attribute, object) -> {
return Utilities.personsToMap(object.getMetadata().getContributors());
});

// <--[tag]
// @attribute <ModTag.contact_info>
// @returns MapTag
// @description
// Returns a mod's contact information, as a map of contact platforms to identification on that platform.
// Some common examples are: "repo", "website", "issues", etc.
// Note that mods can provide anything here, although most mods will obviously provide valid info.
// -->
tagProcessor.registerStaticTag(MapTag.class, "contact_info", (attribute, object) -> {
return Utilities.contactInfoToMap(object.getMetadata().getContact());
});

// <--[tag]
// @attribute <ModTag.licenses>
// @returns ListTag
// @description
// Returns a list of a mod's licenses.
// -->
tagProcessor.registerStaticTag(ListTag.class, "licenses", (attribute, object) -> {
return new ListTag(object.getMetadata().getLicense(), true);
});

// <--[tag]
// @attribute <ModTag.type>
// @returns ElementTag
// @description
// Returns a mod's type, either:
// 'fabric' - a regular Fabric mod, either directly installed or included by another mod.
// 'builtin' - a built-in mod, generally used for internal mods included by Fabric itself.
// -->
tagProcessor.registerStaticTag(ElementTag.class, "type", (attribute, object) -> {
return new ElementTag(object.getMetadata().getType(), true);
});

// <--[tag]
// @attribute <ModTag.containing_mod>
// @returns ModTag
// @description
// Returns the mod that contains this mod, if any (for things like library mods included by other mods).
// -->
tagProcessor.registerStaticTag(ModTag.class, "containing_mod", (attribute, object) -> {
return object.modContainer.getContainingMod().map(ModTag::new).orElse(null);
});

// <--[tag]
// @attribute <ModTag.contained_mods>
// @returns ListTag(ModTag)
// @description
// Returns a list of mods contained by this mod (for mods that include libraries, for example).
// -->
tagProcessor.registerStaticTag(ListTag.class, "contained_mods", (attribute, object) -> {
return new ListTag(object.modContainer.getContainedMods(), ModTag::new);
});
}

public static final ObjectTagProcessor<ModTag> tagProcessor = new ObjectTagProcessor<>();

@Override
public ObjectTag getObjectAttribute(Attribute attribute) {
return tagProcessor.getObjectAttribute(this, attribute);
}

@Override
public String identify() {
return "mod@" + getMetadata().getId();
}

@Override
public String debuggable() {
return "<LG>mod@<Y>" + getMetadata().getId();
}

@Override
public String identifySimple() {
return identify();
}

@Override
public String toString() {
return identify();
}

@Override
public ModContainer getJavaObject() {
return modContainer;
}

@Override
public boolean advancedMatches(String matcher) {
String matcherLower = CoreUtilities.toLowerCase(matcher);
if (matcherLower.equals("mod")) {
return true;
}
return ScriptEvent.runGenericCheck(matcherLower, getMetadata().getId());
}

@Override
public boolean isUnique() {
return true;
}

String prefix = "Mod";

@Override
public String getPrefix() {
return prefix;
}

@Override
public ObjectTag setPrefix(String prefix) {
this.prefix = prefix;
return this;
}
}
25 changes: 25 additions & 0 deletions src/main/java/com/denizenscript/clientizen/tags/ClientTagBase.java
Expand Up @@ -3,6 +3,7 @@
import com.denizenscript.clientizen.objects.EntityTag;
import com.denizenscript.clientizen.objects.LocationTag;
import com.denizenscript.clientizen.objects.MaterialTag;
import com.denizenscript.clientizen.objects.ModTag;
import com.denizenscript.denizencore.DenizenCore;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
Expand All @@ -12,6 +13,7 @@
import com.denizenscript.denizencore.scripts.commands.core.AdjustCommand;
import com.denizenscript.denizencore.tags.PseudoObjectTagBase;
import com.denizenscript.denizencore.tags.TagManager;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.Entity;
import net.minecraft.util.hit.BlockHitResult;
Expand Down Expand Up @@ -43,6 +45,29 @@ public void register() {
return entities;
});

// <--[tag]
// @attribute <client.mods>
// @returns ListTag(ModTag)
// @description
// Returns a list of all currently loaded mods (this doesn't include things like mods-within-mods or built-in mods).
// -->
tagProcessor.registerStaticTag(ListTag.class, "mods", (attribute, object) -> {
return new ListTag(FabricLoader.getInstance().getAllMods(),
modContainer -> modContainer.getContainingMod().isEmpty() && modContainer.getMetadata().getType().equals("fabric")
&& !modContainer.getMetadata().getId().equals("fabricloader"),
ModTag::new);
});

// <--[tag]
// @attribute <client.all_mods>
// @returns ListTag(ModTag)
// @description
// Returns a list of all currently loaded mods, including mods-within-mods and built-in mods.
// -->
tagProcessor.registerStaticTag(ListTag.class, "all_mods", (attribute, object) -> {
return new ListTag(FabricLoader.getInstance().getAllMods(), ModTag::new);
});

// <--[tag]
// @attribute <client.target>
// @returns EntityTag
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/denizenscript/clientizen/util/Utilities.java
@@ -1,11 +1,16 @@
package com.denizenscript.clientizen.util;

import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.MapTag;
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import net.fabricmc.loader.api.metadata.ContactInformation;
import net.fabricmc.loader.api.metadata.Person;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Map;
import java.util.UUID;

public class Utilities {
Expand All @@ -30,4 +35,20 @@ public static void echoErrorByContext(TagContext context, String error) {
Debug.echoError(error);
}
}

public static MapTag contactInfoToMap(ContactInformation contactInformation) {
MapTag contact = new MapTag();
for (Map.Entry<String, String> entry : contactInformation.asMap().entrySet()) {
contact.putObject(entry.getKey(), new ElementTag(entry.getValue(), true));
}
return contact;
}

public static MapTag personsToMap(Iterable<Person> persons) {
MapTag personsMap = new MapTag();
for (Person person : persons) {
personsMap.putObject(person.getName(), contactInfoToMap(person.getContact()));
}
return personsMap;
}
}

0 comments on commit 5752a26

Please sign in to comment.