From 2d0b363fe3179087de59d9ef4a2d14af21d89071 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Wed, 17 Aug 2022 21:21:26 -0300 Subject: [Project] ChewStuff Chew Necklaces for Minecraft! --- LICENSE | 21 +++ README.md | 11 +- build.gradle | 15 ++ gradle.properties | 13 +- .../java/ganarchy/chewstuff/ChewComponent.java | 93 ++++++++++ .../java/ganarchy/chewstuff/ChewComponents.java | 28 +++ src/main/java/ganarchy/chewstuff/ChewStuff.java | 90 ++++++++++ src/main/java/ganarchy/chewstuff/ChewableItem.java | 195 +++++++++++++++++++++ .../java/ganarchy/chewstuff/mixin/DesyncFix.java | 30 ++++ .../java/ganarchy/chewstuff/mixin/PotionMix.java | 67 +++++++ src/main/java/net/fabricmc/example/ExampleMod.java | 21 --- .../net/fabricmc/example/mixin/ExampleMixin.java | 16 -- src/main/resources/assets/chewstuff/icon.png | Bin 0 -> 999 bytes .../resources/assets/chewstuff/lang/en_us.json | 6 + .../assets/chewstuff/models/item/hard_chew.json | 6 + .../assets/chewstuff/models/item/medium_chew.json | 6 + .../assets/chewstuff/models/item/silicone.json | 6 + .../assets/chewstuff/models/item/soft_chew.json | 6 + .../assets/chewstuff/textures/item/hard_chew.png | Bin 0 -> 143 bytes .../assets/chewstuff/textures/item/medium_chew.png | Bin 0 -> 155 bytes .../assets/chewstuff/textures/item/silicone.png | Bin 0 -> 473 bytes .../assets/chewstuff/textures/item/soft_chew.png | Bin 0 -> 154 bytes src/main/resources/assets/modid/icon.png | Bin 453 -> 0 bytes src/main/resources/chewstuff.mixins.json | 15 ++ .../data/chewstuff/recipes/hard_chew.json | 20 +++ .../data/chewstuff/recipes/medium_chew.json | 17 ++ .../resources/data/chewstuff/recipes/silicone.json | 14 ++ .../data/chewstuff/recipes/soft_chew.json | 14 ++ .../data/trinkets/entities/chewstuff.json | 8 + .../data/trinkets/tags/items/chest/necklace.json | 8 + src/main/resources/fabric.mod.json | 33 ++-- src/main/resources/modid.mixins.json | 14 -- 32 files changed, 696 insertions(+), 77 deletions(-) create mode 100644 src/main/java/ganarchy/chewstuff/ChewComponent.java create mode 100644 src/main/java/ganarchy/chewstuff/ChewComponents.java create mode 100644 src/main/java/ganarchy/chewstuff/ChewStuff.java create mode 100644 src/main/java/ganarchy/chewstuff/ChewableItem.java create mode 100644 src/main/java/ganarchy/chewstuff/mixin/DesyncFix.java create mode 100644 src/main/java/ganarchy/chewstuff/mixin/PotionMix.java delete mode 100644 src/main/java/net/fabricmc/example/ExampleMod.java delete mode 100644 src/main/java/net/fabricmc/example/mixin/ExampleMixin.java create mode 100644 src/main/resources/assets/chewstuff/icon.png create mode 100644 src/main/resources/assets/chewstuff/lang/en_us.json create mode 100644 src/main/resources/assets/chewstuff/models/item/hard_chew.json create mode 100644 src/main/resources/assets/chewstuff/models/item/medium_chew.json create mode 100644 src/main/resources/assets/chewstuff/models/item/silicone.json create mode 100644 src/main/resources/assets/chewstuff/models/item/soft_chew.json create mode 100644 src/main/resources/assets/chewstuff/textures/item/hard_chew.png create mode 100644 src/main/resources/assets/chewstuff/textures/item/medium_chew.png create mode 100644 src/main/resources/assets/chewstuff/textures/item/silicone.png create mode 100644 src/main/resources/assets/chewstuff/textures/item/soft_chew.png delete mode 100644 src/main/resources/assets/modid/icon.png create mode 100644 src/main/resources/chewstuff.mixins.json create mode 100644 src/main/resources/data/chewstuff/recipes/hard_chew.json create mode 100644 src/main/resources/data/chewstuff/recipes/medium_chew.json create mode 100644 src/main/resources/data/chewstuff/recipes/silicone.json create mode 100644 src/main/resources/data/chewstuff/recipes/soft_chew.json create mode 100644 src/main/resources/data/trinkets/entities/chewstuff.json create mode 100644 src/main/resources/data/trinkets/tags/items/chest/necklace.json delete mode 100644 src/main/resources/modid.mixins.json diff --git a/LICENSE b/LICENSE index 0e259d4..bbb5704 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,24 @@ +BSD Zero Clause License + +Copyright (c) 2022 Soni L. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +- - - + +Based on the official fabric mod example, which is under the CC0 license. + +- - - + Creative Commons Legal Code CC0 1.0 Universal diff --git a/README.md b/README.md index fd96346..cae175e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,4 @@ -# Fabric Example Mod +# Chewable Necklaces -## Setup - -For setup instructions please see the [fabric wiki page](https://fabricmc.net/wiki/tutorial:setup) that relates to the IDE that you are using. - -## License - -This template is available under the CC0 license. Feel free to learn from it and incorporate it in your own projects. +This was originally a mod about Autism Acceptance Month, but we're updating it +outside of Autism Acceptance Month. diff --git a/build.gradle b/build.gradle index 7a3be5d..c7be481 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,14 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + maven { + name = "TerraformersMC" + url = "https://maven.terraformersmc.com/" + } + maven { + name = "Ladysnake Libs" + url = "https://ladysnake.jfrog.io/artifactory/mods" + } } dependencies { @@ -27,6 +35,13 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + // Trinkets + modImplementation("dev.emi:trinkets:${project.trinkets_version}") { + exclude group: "net.fabricmc" + exclude group: "net.fabricmc.fabric-api" + exclude group: "com.terraformersmc" + } + // Uncomment the following line to enable the deprecated Fabric API modules. // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. diff --git a/gradle.properties b/gradle.properties index a0db7e9..0aef053 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,13 +4,14 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop minecraft_version=1.19.2 - yarn_mappings=1.19.2+build.1 - loader_version=0.14.8 + yarn_mappings=1.19.2+build.3 + loader_version=0.14.9 # Mod Properties - mod_version = 1.0.0 - maven_group = com.example - archives_base_name = fabric-example-mod + mod_version = 1.0.0-SNAPSHOT + maven_group = ganarchy.chewstuff.mc_1_19_2 + archives_base_name = chewstuff-mc1.19.2 # Dependencies - fabric_version=0.58.6+1.19.2 + fabric_version=0.59.0+1.19.2 + trinkets_version=3.4.0 diff --git a/src/main/java/ganarchy/chewstuff/ChewComponent.java b/src/main/java/ganarchy/chewstuff/ChewComponent.java new file mode 100644 index 0000000..4b6dcd8 --- /dev/null +++ b/src/main/java/ganarchy/chewstuff/ChewComponent.java @@ -0,0 +1,93 @@ +package ganarchy.chewstuff; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.onyxstudios.cca.api.v3.component.ComponentV3; +import net.minecraft.entity.effect.StatusEffect; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtOps; +import net.minecraft.util.registry.Registry; + +import java.util.*; + +/** + * Component for chews. + */ +public class ChewComponent implements ComponentV3 { + /** + * Codec for encoding/decoding this component. + */ + public static final Codec CODEC = RecordCodecBuilder.create( + inst -> inst.group( + Codec.unboundedMap( + Registry.STATUS_EFFECT.getCodec(), Codec.INT + ).fieldOf("effects").forGetter(i -> i.effects), + Codec.list( + Registry.STATUS_EFFECT.getCodec() + ).fieldOf("applied").forGetter(i -> new ArrayList<>(i.applied)), + Codec.BOOL.fieldOf("sendUpdate").forGetter(i -> i.sendUpdate) + ).apply(inst, ChewComponent::new) + ); + /** + * The effects we're currently consuming. + */ + public Map effects; + /** + * The effects which have been applied and should be skipped. + */ + public Set applied; + /** + * Whether to send updated effects to the client. + */ + public boolean sendUpdate; + + /** + * Creates a new ChewInfo with no effects. + */ + public ChewComponent() { + this.effects = new HashMap<>(); + this.applied = new HashSet<>(); + } + + /** + * Creates a new ChewInfo with the specified effects. + * + * @param effects The bound effects. + * @param applied The applied effects. + */ + public ChewComponent( + Map effects, + List applied, + boolean sendUpdate + ) { + if (effects instanceof HashMap) { + this.effects = effects; + } else { + // ideally we'd just make the HashMap directly but DFU doesn't let + // you set the Map class. + // actually ideally we'd use IdentityHashMap but w/e. + this.effects = new HashMap<>(effects); + } + this.applied = new HashSet<>(applied); + this.sendUpdate = sendUpdate; + } + + @Override + public void readFromNbt(NbtCompound tag) { + var info = ChewComponent.CODEC.parse( + NbtOps.INSTANCE, + tag + ).result().orElseGet(ChewComponent::new); + + this.effects = info.effects; + this.applied = info.applied; + } + + @Override + public void writeToNbt(NbtCompound tag) { + tag.copyFrom((NbtCompound) ChewComponent.CODEC.encodeStart( + NbtOps.INSTANCE, + this + ).result().orElseThrow()); + } +} diff --git a/src/main/java/ganarchy/chewstuff/ChewComponents.java b/src/main/java/ganarchy/chewstuff/ChewComponents.java new file mode 100644 index 0000000..427d86e --- /dev/null +++ b/src/main/java/ganarchy/chewstuff/ChewComponents.java @@ -0,0 +1,28 @@ +package ganarchy.chewstuff; + +import dev.onyxstudios.cca.api.v3.component.ComponentKey; +import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; +import dev.onyxstudios.cca.api.v3.entity.EntityComponentFactoryRegistry; +import dev.onyxstudios.cca.api.v3.entity.EntityComponentInitializer; +import dev.onyxstudios.cca.api.v3.entity.RespawnCopyStrategy; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.Identifier; + +public class ChewComponents implements EntityComponentInitializer { + public static final ComponentKey CHEW = + ComponentRegistry.getOrCreate( + new Identifier("chewstuff", "chew"), ChewComponent.class + ); + + @Override + public void registerEntityComponentFactories( + EntityComponentFactoryRegistry registry + ) { + registry.registerFor( + LivingEntity.class, CHEW, entity -> new ChewComponent() + ); + registry.registerForPlayers( + CHEW, entity -> new ChewComponent(), RespawnCopyStrategy.ALWAYS_COPY + ); + } +} diff --git a/src/main/java/ganarchy/chewstuff/ChewStuff.java b/src/main/java/ganarchy/chewstuff/ChewStuff.java new file mode 100644 index 0000000..7bea0ec --- /dev/null +++ b/src/main/java/ganarchy/chewstuff/ChewStuff.java @@ -0,0 +1,90 @@ +package ganarchy.chewstuff; + +import net.fabricmc.api.ModInitializer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The mod's entry point. + */ +public class ChewStuff implements ModInitializer { + /** + * The ChewStuff Logger. + */ + public static final Logger LOGGER = LoggerFactory.getLogger("chewstuff"); + + /** + * Silicone. Not to be confused with silicon. Crafting material for + * chews. + */ + public static final Item SILICONE = new Item( + new Item.Settings().group(ItemGroup.MISC) + ); + /** + * 1 day, in ticks. + */ + public static final int DAY_MULTIPLIER = 24 * 60 * 60 * 20; + /** + * Soft chew. Lasts 5 days, 1 effect slot. + */ + public static final Item SOFT_CHEW = new ChewableItem( + 1, + new Item.Settings().maxDamage(5 * DAY_MULTIPLIER).group(ItemGroup.TOOLS) + ); + /** + * Medium chew. Lasts 6 days, 2 effect slots. + */ + public static final Item MEDIUM_CHEW = new ChewableItem( + 2, + new Item.Settings().maxDamage(6 * DAY_MULTIPLIER).group(ItemGroup.TOOLS) + ); + /** + * Hard chew. Lasts 7 days, 3 effect slots. + */ + public static final Item HARD_CHEW = new ChewableItem( + 3, + new Item.Settings().maxDamage(7 * DAY_MULTIPLIER).group(ItemGroup.TOOLS) + ); + /** + * The stat for chew effects. + */ + public static final Identifier CHEW_EFFECTS = new Identifier( + "chewstuff", "effects" + ); + + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + LOGGER.info("This software is made with love by a queer trans person."); + + Registry.register( + Registry.ITEM, + new Identifier("chewstuff", "silicone"), + SILICONE + ); + Registry.register( + Registry.ITEM, + new Identifier("chewstuff", "soft_chew"), + SOFT_CHEW + ); + Registry.register( + Registry.ITEM, + new Identifier("chewstuff", "medium_chew"), + MEDIUM_CHEW + ); + Registry.register( + Registry.ITEM, + new Identifier("chewstuff", "hard_chew"), + HARD_CHEW + ); +// Registry.register(Registry.CUSTOM_STAT, CHEW_EFFECTS, CHEW_EFFECTS); +// Stats.CUSTOM.getOrCreateStat(CHEW_EFFECTS, StatFormatter.DEFAULT); + } +} diff --git a/src/main/java/ganarchy/chewstuff/ChewableItem.java b/src/main/java/ganarchy/chewstuff/ChewableItem.java new file mode 100644 index 0000000..e3c8f60 --- /dev/null +++ b/src/main/java/ganarchy/chewstuff/ChewableItem.java @@ -0,0 +1,195 @@ +package ganarchy.chewstuff; + +import dev.emi.trinkets.api.SlotReference; +import dev.emi.trinkets.api.TrinketItem; +import dev.emi.trinkets.api.TrinketsApi; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffect; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Wearable; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.packet.s2c.play.EntityStatusEffectS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * An item that can be chewed. + */ +public class ChewableItem extends TrinketItem implements Wearable { + /** + * The cooldown between activations, in ticks. + */ + private static final int COOLDOWN = 5 * 20; + /** + * Number of effects to bind to. + */ + private final int effects; + + /** + * @param effects Number of effects to bind to. + * @param settings The item settings. + */ + public ChewableItem(int effects, Settings settings) { + super(settings); + this.effects = effects; + } + + @Override + public void onEquip(ItemStack stack, SlotReference slot, LivingEntity entity) { + if (entity.world.isClient) { + return; + } + var maybeInfo = ChewComponents.CHEW.maybeGet(entity); + maybeInfo.ifPresent(info -> { + info.sendUpdate = true; + }); + } + + @Override + public void onUnequip( + ItemStack stack, SlotReference slot, LivingEntity entity + ) { + if (entity.world.isClient) { + return; + } + var maybeInfo = ChewComponents.CHEW.maybeGet(entity); + maybeInfo.ifPresent(info -> { + if (!info.effects.isEmpty()) { + resetEffects(entity, info); + } + }); + } + + @Override + public void tick(ItemStack stack, SlotReference slot, LivingEntity entity) { + if (entity.world.isClient) { + return; + } + if (entity instanceof PlayerEntity player) { + if (player.getItemCooldownManager().isCoolingDown(this)) { + return; + } + } + var maybeInfo = ChewComponents.CHEW.maybeGet(entity); + maybeInfo.ifPresent(info -> { + if (info.effects.isEmpty()) { + var effects = entity.getStatusEffects(); + if (effects.size() >= this.effects) { + effects = new ArrayList<>(effects); + Collections.shuffle((List) effects); + info.effects = effects.stream().filter( + effect -> !effect.isAmbient() + ).limit(this.effects).collect( + Collectors.toMap( + StatusEffectInstance::getEffectType, + StatusEffectInstance::getDuration, + (i1, i2) -> { + // don't crash the game in prod + if ( + FabricLoader.getInstance() + .isDevelopmentEnvironment() + ) { + throw new IllegalStateException(); + } else { + return Integer.min(i1, i2); + } + }, + HashMap::new + ) + ); + info.sendUpdate = true; + } else { + return; + } + } + if (info.effects.size() != this.effects) { + return; + } + if (info.sendUpdate) { + sendEffectUpdate(entity, info); + } + var effects = info.effects.keySet(); + for (StatusEffect effect : effects) { + if (info.effects.get(effect) <= 0) { + continue; + } + var effectInstance = entity.getStatusEffect(effect); + if (effectInstance == null || effectInstance.isAmbient()) { + info.effects.put(effect, 0); + continue; + } + // don't wanna deal with LivingEntity internals. + if (effectInstance.getDuration() == 1) { + continue; + } + if (!effectInstance.update(entity, () -> {})) { + throw new IllegalStateException(); + } + } + if (info.effects.values().stream().allMatch(i -> i == 0)) { + resetEffects(entity, info); + } + stack.damage(1, entity, livingEntity -> { + TrinketsApi.onTrinketBroken(stack, slot, livingEntity); + }); + }); + } + + private void sendEffectUpdate(LivingEntity entity, ChewComponent info) { + if (entity instanceof ServerPlayerEntity player) { + for (StatusEffect effect : info.effects.keySet()) { + var instance = player.getStatusEffect(effect); + if (instance == null) { + continue; + } + NbtCompound nbt = new NbtCompound(); + instance.writeNbt(nbt); + nbt.putInt("Duration", instance.getDuration() / 2); + var toSend = StatusEffectInstance.fromNbt(nbt); + if (toSend != null) { + player.networkHandler.sendPacket( + new EntityStatusEffectS2CPacket( + player.getId(), + toSend + ) + ); + } + } + } + } + + /** + * Stops tracking effects, enables the cooldown, and updates the player, + * as needed. + * + * @param entity The entity. + * @param info The tracked effects. + */ + private void resetEffects(LivingEntity entity, ChewComponent info) { + if (entity instanceof ServerPlayerEntity player) { + for (StatusEffect effect : info.effects.keySet()) { + var instance = player.getStatusEffect(effect); + if (instance == null) { + continue; + } + player.networkHandler.sendPacket( + new EntityStatusEffectS2CPacket( + player.getId(), + instance + ) + ); + } + player.getItemCooldownManager().set(this, COOLDOWN); + } + info.effects.clear(); + info.applied.clear(); + } +} diff --git a/src/main/java/ganarchy/chewstuff/mixin/DesyncFix.java b/src/main/java/ganarchy/chewstuff/mixin/DesyncFix.java new file mode 100644 index 0000000..7a62a41 --- /dev/null +++ b/src/main/java/ganarchy/chewstuff/mixin/DesyncFix.java @@ -0,0 +1,30 @@ +package ganarchy.chewstuff.mixin; + +import ganarchy.chewstuff.ChewComponents; +import net.minecraft.server.network.ServerPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * The mixin for server player entities. + */ +@Mixin(ServerPlayerEntity.class) +public class DesyncFix { + /** + * Checks and corrects for desyncs. + */ + @Inject( + at = @At("HEAD"), + method = + "onStatusEffectUpgraded(Lnet/minecraft/entity/effect/StatusEffectInstance;ZLnet/minecraft/entity/Entity;)V" + ) + private void chewstuff_onDesync(CallbackInfo cbinfo) { + var self = (ServerPlayerEntity) (Object) this; + var maybeInfo = ChewComponents.CHEW.maybeGet(self); + maybeInfo.ifPresent(info -> { + info.sendUpdate = true; + }); + } +} diff --git a/src/main/java/ganarchy/chewstuff/mixin/PotionMix.java b/src/main/java/ganarchy/chewstuff/mixin/PotionMix.java new file mode 100644 index 0000000..5ed97ab --- /dev/null +++ b/src/main/java/ganarchy/chewstuff/mixin/PotionMix.java @@ -0,0 +1,67 @@ +package ganarchy.chewstuff.mixin; + +import ganarchy.chewstuff.ChewComponents; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffectInstance; +import org.spongepowered.asm.mixin.Mixin; +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; + +/** + * The mixin for status effect instances. + */ +@Mixin(StatusEffectInstance.class) +public class PotionMix { + /** + * Checks the apply effect and cancels it when we're force-ticking it. + */ + @Inject( + at = @At("HEAD"), + method = "applyUpdateEffect(Lnet/minecraft/entity/LivingEntity;)V", + cancellable = true + ) + private void chewstuff_checkApplyEffect( + LivingEntity entity, CallbackInfo cbinfo + ) { + StatusEffectInstance self = (StatusEffectInstance) (Object) this; + var maybeInfo = ChewComponents.CHEW.maybeGet(entity); + maybeInfo.ifPresent(info -> { + var effect = self.getEffectType(); + if (info.effects.getOrDefault(effect, 0) <= 0) { + return; + } + if (info.applied.contains(effect)) { + info.applied.remove(effect); + cbinfo.cancel(); + } else { + info.applied.add(effect); + } + }); + } + + /** + * Checks for effect ticks. + */ + @Inject( + at = @At("HEAD"), + method = + "update(Lnet/minecraft/entity/LivingEntity;Ljava/lang/Runnable;)Z" + ) + private void chewstuff_checkUpdate( + LivingEntity entity, + Runnable runnable, + CallbackInfoReturnable cbinfo + ) { + StatusEffectInstance self = (StatusEffectInstance) (Object) this; + var maybeInfo = ChewComponents.CHEW.maybeGet(entity); + maybeInfo.ifPresent(info -> { + var effect = self.getEffectType(); + if (info.effects.getOrDefault(effect, 0) <= 0) { + return; + } + info.effects.computeIfPresent(effect, (k, v) -> v - 1); + }); + } +} diff --git a/src/main/java/net/fabricmc/example/ExampleMod.java b/src/main/java/net/fabricmc/example/ExampleMod.java deleted file mode 100644 index a964189..0000000 --- a/src/main/java/net/fabricmc/example/ExampleMod.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.fabricmc.example; - -import net.fabricmc.api.ModInitializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ExampleMod implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - public static final Logger LOGGER = LoggerFactory.getLogger("modid"); - - @Override - public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - - LOGGER.info("Hello Fabric world!"); - } -} diff --git a/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java b/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java deleted file mode 100644 index 356cb38..0000000 --- a/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.fabricmc.example.mixin; - -import net.fabricmc.example.ExampleMod; -import net.minecraft.client.gui.screen.TitleScreen; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(TitleScreen.class) -public class ExampleMixin { - @Inject(at = @At("HEAD"), method = "init()V") - private void init(CallbackInfo info) { - ExampleMod.LOGGER.info("This line is printed by an example mod mixin!"); - } -} diff --git a/src/main/resources/assets/chewstuff/icon.png b/src/main/resources/assets/chewstuff/icon.png new file mode 100644 index 0000000..b9d942a Binary files /dev/null and b/src/main/resources/assets/chewstuff/icon.png differ diff --git a/src/main/resources/assets/chewstuff/lang/en_us.json b/src/main/resources/assets/chewstuff/lang/en_us.json new file mode 100644 index 0000000..47af750 --- /dev/null +++ b/src/main/resources/assets/chewstuff/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "item.chewstuff.silicone": "Silicone", + "item.chewstuff.soft_chew": "Soft Chew Necklace", + "item.chewstuff.medium_chew": "Medium Chew Necklace", + "item.chewstuff.hard_chew": "Hard Chew Necklace" +} \ No newline at end of file diff --git a/src/main/resources/assets/chewstuff/models/item/hard_chew.json b/src/main/resources/assets/chewstuff/models/item/hard_chew.json new file mode 100644 index 0000000..0191e60 --- /dev/null +++ b/src/main/resources/assets/chewstuff/models/item/hard_chew.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "chewstuff:item/hard_chew" + } +} diff --git a/src/main/resources/assets/chewstuff/models/item/medium_chew.json b/src/main/resources/assets/chewstuff/models/item/medium_chew.json new file mode 100644 index 0000000..596291a --- /dev/null +++ b/src/main/resources/assets/chewstuff/models/item/medium_chew.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "chewstuff:item/medium_chew" + } +} diff --git a/src/main/resources/assets/chewstuff/models/item/silicone.json b/src/main/resources/assets/chewstuff/models/item/silicone.json new file mode 100644 index 0000000..36fcd35 --- /dev/null +++ b/src/main/resources/assets/chewstuff/models/item/silicone.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "chewstuff:item/silicone" + } +} diff --git a/src/main/resources/assets/chewstuff/models/item/soft_chew.json b/src/main/resources/assets/chewstuff/models/item/soft_chew.json new file mode 100644 index 0000000..3923e9e --- /dev/null +++ b/src/main/resources/assets/chewstuff/models/item/soft_chew.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "chewstuff:item/soft_chew" + } +} diff --git a/src/main/resources/assets/chewstuff/textures/item/hard_chew.png b/src/main/resources/assets/chewstuff/textures/item/hard_chew.png new file mode 100644 index 0000000..be5712c Binary files /dev/null and b/src/main/resources/assets/chewstuff/textures/item/hard_chew.png differ diff --git a/src/main/resources/assets/chewstuff/textures/item/medium_chew.png b/src/main/resources/assets/chewstuff/textures/item/medium_chew.png new file mode 100644 index 0000000..871ad3c Binary files /dev/null and b/src/main/resources/assets/chewstuff/textures/item/medium_chew.png differ diff --git a/src/main/resources/assets/chewstuff/textures/item/silicone.png b/src/main/resources/assets/chewstuff/textures/item/silicone.png new file mode 100644 index 0000000..aad04bb Binary files /dev/null and b/src/main/resources/assets/chewstuff/textures/item/silicone.png differ diff --git a/src/main/resources/assets/chewstuff/textures/item/soft_chew.png b/src/main/resources/assets/chewstuff/textures/item/soft_chew.png new file mode 100644 index 0000000..2cc2f29 Binary files /dev/null and b/src/main/resources/assets/chewstuff/textures/item/soft_chew.png differ diff --git a/src/main/resources/assets/modid/icon.png b/src/main/resources/assets/modid/icon.png deleted file mode 100644 index 047b91f..0000000 Binary files a/src/main/resources/assets/modid/icon.png and /dev/null differ diff --git a/src/main/resources/chewstuff.mixins.json b/src/main/resources/chewstuff.mixins.json new file mode 100644 index 0000000..ef0b3fa --- /dev/null +++ b/src/main/resources/chewstuff.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "ganarchy.chewstuff.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "PotionMix", + "DesyncFix" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/data/chewstuff/recipes/hard_chew.json b/src/main/resources/data/chewstuff/recipes/hard_chew.json new file mode 100644 index 0000000..8cea939 --- /dev/null +++ b/src/main/resources/data/chewstuff/recipes/hard_chew.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "chewstuff:silicone" + }, + { + "item": "chewstuff:silicone" + }, + { + "item": "chewstuff:silicone" + }, + { + "item": "minecraft:string" + } + ], + "result": { + "item": "chewstuff:hard_chew" + } +} diff --git a/src/main/resources/data/chewstuff/recipes/medium_chew.json b/src/main/resources/data/chewstuff/recipes/medium_chew.json new file mode 100644 index 0000000..a4b9639 --- /dev/null +++ b/src/main/resources/data/chewstuff/recipes/medium_chew.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "chewstuff:silicone" + }, + { + "item": "chewstuff:silicone" + }, + { + "item": "minecraft:string" + } + ], + "result": { + "item": "chewstuff:medium_chew" + } +} diff --git a/src/main/resources/data/chewstuff/recipes/silicone.json b/src/main/resources/data/chewstuff/recipes/silicone.json new file mode 100644 index 0000000..137e5fd --- /dev/null +++ b/src/main/resources/data/chewstuff/recipes/silicone.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "tag": "minecraft:coals" + }, + { + "tag": "minecraft:sand" + } + ], + "result": { + "item": "chewstuff:silicone" + } +} diff --git a/src/main/resources/data/chewstuff/recipes/soft_chew.json b/src/main/resources/data/chewstuff/recipes/soft_chew.json new file mode 100644 index 0000000..1e15630 --- /dev/null +++ b/src/main/resources/data/chewstuff/recipes/soft_chew.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "chewstuff:silicone" + }, + { + "item": "minecraft:string" + } + ], + "result": { + "item": "chewstuff:soft_chew" + } +} diff --git a/src/main/resources/data/trinkets/entities/chewstuff.json b/src/main/resources/data/trinkets/entities/chewstuff.json new file mode 100644 index 0000000..fd5f0d3 --- /dev/null +++ b/src/main/resources/data/trinkets/entities/chewstuff.json @@ -0,0 +1,8 @@ +{ + "entities": [ + "player" + ], + "slots": [ + "chest/necklace" + ] +} diff --git a/src/main/resources/data/trinkets/tags/items/chest/necklace.json b/src/main/resources/data/trinkets/tags/items/chest/necklace.json new file mode 100644 index 0000000..4d31011 --- /dev/null +++ b/src/main/resources/data/trinkets/tags/items/chest/necklace.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "chewstuff:soft_chew", + "chewstuff:medium_chew", + "chewstuff:hard_chew" + ] +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 730d843..9f07af9 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,38 +1,47 @@ { "schemaVersion": 1, - "id": "modid", + "id": "chewstuff", "version": "${version}", - "name": "Example Mod", - "description": "This is an example description! Tell everyone what your mod is about!", + "name": "Chew Necklaces", + "description": "There once was an Autism Acceptance Mod but it hasn't been updated in forever. This is more or less a complete rewrite, from scratch, of that.", "authors": [ - "Me!" + "SoniEx2" ], + "contributors": { + "torako" + }, "contact": { - "homepage": "https://fabricmc.net/", - "sources": "https://github.com/FabricMC/fabric-example-mod" + "sources": "https://soniex2.autistic.space/git-repos/chewstuff.git" }, - "license": "CC0-1.0", - "icon": "assets/modid/icon.png", + "license": "0BSD", + "icon": "assets/chewstuff/icon.png", "environment": "*", "entrypoints": { "main": [ - "net.fabricmc.example.ExampleMod" + "ganarchy.chewstuff.ChewStuff" + ], + "cardinal-components": [ + "ganarchy.chewstuff.ChewComponents" ] }, "mixins": [ - "modid.mixins.json" + "chewstuff.mixins.json" ], "depends": { + "trinkets": "~3.4", "fabricloader": ">=0.14.6", "fabric": "*", "minecraft": "~1.19", "java": ">=17" }, - "suggests": { - "another-mod": "*" + + "custom": { + "cardinal-components": [ + "chewstuff:chew" + ] } } diff --git a/src/main/resources/modid.mixins.json b/src/main/resources/modid.mixins.json deleted file mode 100644 index 7c42cb4..0000000 --- a/src/main/resources/modid.mixins.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "net.fabricmc.example.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - ], - "client": [ - "ExampleMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} -- cgit 1.4.1