diff --git a/CHANGELOG.md b/CHANGELOG.md index a026f3d..50feb3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ### Changelog +**1.0.8** +* Update to 20w10a +* Add the ```/spell learn```, ```/spell add```, and ```/spell remove``` commands +* Use CurseForge + **1.0.7** * Play Failure Sound when Inward Spell Fails diff --git a/README.md b/README.md index 6f1d531..18e7153 100644 --- a/README.md +++ b/README.md @@ -67,4 +67,13 @@ This command requires OP permissions. This command clears all known spells from the given player. #### ```/spell list ``` -This lists all the spells the given player knows. \ No newline at end of file +This lists all the spells the given player knows. + +#### ```/spell learn ``` +This teaches the specified spell to the specified player. + +#### ```/spell add ``` +This adds the specified spell to the item in the player's main hand. + +#### ```/spell remove ``` +This removes the specified spell from the item in the player's main hand. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 01d3753..366ef58 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { - id 'fabric-loom' version '0.2.6-SNAPSHOT' + id 'fabric-loom' version '0.2.7-SNAPSHOT' + id 'com.matthewprenger.cursegradle' version '1.4.0' } compileJava { @@ -17,9 +18,9 @@ minecraft { dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modCompile "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" } processResources { @@ -53,3 +54,30 @@ task sourcesJar(type: Jar, dependsOn: classes) { jar { from "LICENSE" } + +curseforge { + if (project.hasProperty('curseforge.api_key')) { + apiKey = project.getProperty('curseforge.api_key') + } + project { + id = project.curseforge_id + changelogType = 'markdown' + changelog = file('CHANGELOG.md') + releaseType = 'release' + addGameVersion project.simple_minecraft_version + addGameVersion 'Fabric' + addGameVersion 'Java 8' + mainArtifact(remapJar) { + displayName = "SorceryCraft v${version} for ${project.minecraft_version}" + } + afterEvaluate { + uploadTask.dependsOn('remapJar') + } + relations { + requiredDependency 'fabric-api' + } + } + options { + forgeGradleIntegration = false + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 84884c2..da5c94a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,15 +3,17 @@ org.gradle.jvmargs = -Xmx1G # Fabric Properties # check these on https://fabricmc.net/use - minecraft_version = 20w09a - yarn_mappings = 20w09a+build.6 - loader_version = 0.7.8+build.184 + minecraft_version = 20w10a + curseforge_id = 365308 + simple_minecraft_version = 1.16-Snapshot + yarn_mappings = 20w10a+build.7 + loader_version = 0.7.8+build.186 # Mod Properties - mod_version = 1.0.7 + mod_version = 1.0.8 maven_group = com.thebrokenrail archives_base_name = sorcerycraft # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - fabric_version = 0.4.33+build.301-1.16 + fabric_version = 0.5.1+build.305-1.16 diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/SorceryCraft.java b/src/main/java/com/thebrokenrail/sorcerycraft/SorceryCraft.java index de279b9..9e0159f 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/SorceryCraft.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/SorceryCraft.java @@ -9,8 +9,8 @@ import com.thebrokenrail.sorcerycraft.entity.SpellEntity; import com.thebrokenrail.sorcerycraft.item.SpellItem; import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket; import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket; -import com.thebrokenrail.sorcerycraft.spell.RandomSpellLootTableFunction; -import com.thebrokenrail.sorcerycraft.spell.Spells; +import com.thebrokenrail.sorcerycraft.spell.util.RandomSpellLootTableFunction; +import com.thebrokenrail.sorcerycraft.spell.registry.Spells; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableContainer.java b/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableContainer.java index 9e4a21f..6efe4bf 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableContainer.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/block/CastingTableContainer.java @@ -1,10 +1,10 @@ package com.thebrokenrail.sorcerycraft.block; import com.thebrokenrail.sorcerycraft.SorceryCraft; -import com.thebrokenrail.sorcerycraft.spell.Spell; -import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity; -import com.thebrokenrail.sorcerycraft.spell.SpellRegistry; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; +import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; +import com.thebrokenrail.sorcerycraft.spell.registry.SpellRegistry; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; import net.minecraft.container.BlockContext; import net.minecraft.container.Container; import net.minecraft.container.ContainerType; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/client/block/CastingTableScreen.java b/src/main/java/com/thebrokenrail/sorcerycraft/client/block/CastingTableScreen.java index b3ebbf7..9558661 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/client/block/CastingTableScreen.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/client/block/CastingTableScreen.java @@ -4,8 +4,8 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.thebrokenrail.sorcerycraft.SorceryCraft; import com.thebrokenrail.sorcerycraft.block.CastingTableContainer; import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket; -import com.thebrokenrail.sorcerycraft.spell.Spell; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.font.TextRenderer; @@ -33,21 +33,21 @@ public class CastingTableScreen extends ContainerScreen { @Override protected void drawForeground(int mouseX, int mouseY) { int j = containerHeight - 94; - font.draw(title.asFormattedString(), (float) (49 + this.containerWidth / 2 - font.getStringWidth(title.asFormattedString()) / 2), 6.0F, 4210752); - font.draw(playerInventory.getDisplayName().asFormattedString(), 107.0F, (float) j, 4210752); + textRenderer.draw(title.asFormattedString(), (float) (49 + this.containerWidth / 2 - textRenderer.getStringWidth(title.asFormattedString()) / 2), 6.0F, 4210752); + textRenderer.draw(playerInventory.getDisplayName().asFormattedString(), 107.0F, (float) j, 4210752); String spells = new TranslatableText("container." + SorceryCraft.NAMESPACE + ".spells").getString(); - font.draw(spells, (float) (5 - font.getStringWidth(spells) / 2 + 48), 6.0F, 4210752); + textRenderer.draw(spells, (float) (5 - textRenderer.getStringWidth(spells) / 2 + 48), 6.0F, 4210752); renderXPCost(); } @Override protected void drawBackground(float delta, int mouseX, int mouseY) { RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - assert minecraft != null; - minecraft.getTextureManager().bindTexture(TEXTURE); + assert client != null; + client.getTextureManager().bindTexture(TEXTURE); int i = (width - containerWidth) / 2; int j = (height - containerHeight) / 2; - blit(i, j, this.getBlitOffset(), 0.0F, 0.0F, containerWidth, containerHeight, 256, 512); + blit(i, j, getZOffset(), 0.0F, 0.0F, containerWidth, containerHeight, 256, 512); } @Override @@ -66,7 +66,7 @@ public class CastingTableScreen extends ContainerScreen { button.visible = button.index < container.getRecipes().length; if (button.visible) { Spell spell = container.getRecipes()[button.getIndex() + indexStartOffset]; - button.setMessage(SpellTag.getTranslatedSpell(spell.getID(), spell.getLevel()).getString()); + button.setMessage(SpellTag.getTranslatedSpell(spell.getID(), spell.getLevel(), true).getString()); button.setFocused((button.getIndex() + indexStartOffset) == selectedIndex); } } @@ -74,8 +74,8 @@ public class CastingTableScreen extends ContainerScreen { private void renderScrollbar() { Spell[] spells = container.getRecipes(); - assert minecraft != null; - minecraft.getTextureManager().bindTexture(TEXTURE); + assert client != null; + client.getTextureManager().bindTexture(TEXTURE); int i = (width - containerWidth) / 2; int j = (height - containerHeight) / 2; int k = spells.length + 1 - 7; @@ -88,9 +88,9 @@ public class CastingTableScreen extends ContainerScreen { o = 113; } - blit(i + 94, j + 18 + o, getBlitOffset(), 0.0F, 199.0F, 6, 27, 256, 512); + blit(i + 94, j + 18 + o, getZOffset(), 0.0F, 199.0F, 6, 27, 256, 512); } else { - blit(i + 94, j + 18, getBlitOffset(), 6.0F, 199.0F, 6, 27, 256, 512); + blit(i + 94, j + 18, getZOffset(), 6.0F, 199.0F, 6, 27, 256, 512); } } @@ -107,7 +107,7 @@ public class CastingTableScreen extends ContainerScreen { int n = k + 2; itemRenderer.renderGuiItem(itemStack, i + 5 + 68, n); - itemRenderer.renderGuiItemOverlay(font, itemStack, i + 5 + 68, n); + itemRenderer.renderGuiItemOverlay(textRenderer, itemStack, i + 5 + 68, n); itemRenderer.zOffset = 0.0F; k += 20; } @@ -118,17 +118,17 @@ public class CastingTableScreen extends ContainerScreen { if (container.getRecipes().length > 0) { int i = container.getRecipes()[selectedIndex].getXPCost(); int j = 8453920; - assert minecraft != null; - assert minecraft.player != null; + assert client != null; + assert client.player != null; String string = new TranslatableText("container.repair.cost", i).getString(); if (!container.canTakeResult(playerInventory.player)) { j = 16736352; } int x2 = containerWidth - 8; - int x1 = x2 - font.getStringWidth(string); + int x1 = x2 - textRenderer.getStringWidth(string); fill(x1, 65, x2, 77, 1325400064); - font.drawWithShadow(string, (float) x1, 67.0F, j); + textRenderer.drawWithShadow(string, (float) x1, 67.0F, j); } } @@ -178,8 +178,8 @@ public class CastingTableScreen extends ContainerScreen { private void syncRecipeIndex() { container.setIndex(selectedIndex); - assert minecraft != null; - SelectSpellC2SPacket.send(minecraft, selectedIndex); + assert client != null; + SelectSpellC2SPacket.send(client, selectedIndex); } private final WidgetButtonPage[] buttons = new WidgetButtonPage[7]; @@ -220,7 +220,7 @@ public class CastingTableScreen extends ContainerScreen { } public void renderToolTip(int mouseX, int mouseY) { - if (isHovered && container.getRecipes().length > index + indexStartOffset && mouseX > this.x + 65) { + if (hovered && container.getRecipes().length > index + indexStartOffset && mouseX > this.x + 65) { ItemStack itemStack = container.getRecipes()[index + indexStartOffset].getItemCost(); if (!itemStack.isEmpty()) { renderTooltip(itemStack, mouseX, mouseY); @@ -229,7 +229,7 @@ public class CastingTableScreen extends ContainerScreen { } @Override - public void drawCenteredString(TextRenderer textRenderer, String str, int ignored, int y, int color) { + public void drawCenteredString(TextRenderer textRenderer, String str, int centerX, int y, int color) { drawString(textRenderer, str, x + 5, y, color); } } diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellArgumentType.java b/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellArgumentType.java new file mode 100644 index 0000000..bcaaa72 --- /dev/null +++ b/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellArgumentType.java @@ -0,0 +1,60 @@ +package com.thebrokenrail.sorcerycraft.command; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import com.thebrokenrail.sorcerycraft.SorceryCraft; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; +import com.thebrokenrail.sorcerycraft.spell.registry.SpellRegistry; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Identifier; + +public class SpellArgumentType implements ArgumentType { + private static final Collection EXAMPLES = Arrays.asList("sorcerycraft:heal_spell", "sorcerycraft:damage_spell"); + public static final DynamicCommandExceptionType NOT_FOUND_EXCEPTION = new DynamicCommandExceptionType((object) -> new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.unknown_spell", object)); + + public SpellArgumentType() { + } + + public static SpellArgumentType spell() { + return new SpellArgumentType(); + } + + public static Identifier getSpell(CommandContext context, String name) throws CommandSyntaxException { + return validate(context.getArgument(name, Identifier.class)); + } + + private static Identifier validate(Identifier identifier) throws CommandSyntaxException { + Spell testSpell = SpellRegistry.getSpell(identifier, 0); + if (testSpell == null) { + throw NOT_FOUND_EXCEPTION.create(identifier); + } + return identifier; + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + Identifier[] spells = SpellRegistry.getSpellsID(); + for (Identifier spell : spells) { + builder.suggest(spell.toString()); + } + return builder.buildFuture(); + } + + public Identifier parse(StringReader stringReader) throws CommandSyntaxException { + return validate(Identifier.fromCommandInput(stringReader)); + } + + public Collection getExamples() { + return EXAMPLES; + } +} diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java b/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java index 0c5320d..e9cb033 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/command/SpellCommand.java @@ -1,11 +1,14 @@ package com.thebrokenrail.sorcerycraft.command; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.thebrokenrail.sorcerycraft.SorceryCraft; -import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; import net.minecraft.command.arguments.EntityArgumentType; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.TranslatableText; @@ -16,6 +19,8 @@ import java.util.HashMap; import java.util.Map; public class SpellCommand { + private static final DynamicCommandExceptionType NOT_HOLDING_SPELL_EXCEPTION = new DynamicCommandExceptionType(object -> new TranslatableText("command."+ SorceryCraft.NAMESPACE + ".spell.not_holding_spell", object)); + public static void register(CommandDispatcher dispatcher) { dispatcher.register(CommandManager.literal("spell") .requires(source -> source.hasPermissionLevel(4)) @@ -27,7 +32,7 @@ public class SpellCommand { SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; Map spells = spellPlayer.getSorceryCraftSpells(); for (Map.Entry entry : spells.entrySet()) { - ctx.getSource().sendFeedback(SpellTag.getTranslatedSpell(entry.getKey(), entry.getValue()).formatted(Formatting.YELLOW), false); + ctx.getSource().sendFeedback(SpellTag.getTranslatedSpell(entry.getKey(), entry.getValue(), true).formatted(Formatting.YELLOW), false); } return 0; }) @@ -44,6 +49,72 @@ public class SpellCommand { }) ) ) + .then(CommandManager.literal("learn") + .then(CommandManager.argument("player", EntityArgumentType.player()) + .then(CommandManager.argument("spell", SpellArgumentType.spell()) + .then(CommandManager.argument("level", IntegerArgumentType.integer()) + .executes(ctx -> { + PlayerEntity player = EntityArgumentType.getPlayer(ctx, "player"); + Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); + int level = IntegerArgumentType.getInteger(ctx, "level") - 1; + Map spellMap = new HashMap<>(); + spellMap.put(spell, level); + SpellTag.learnSpells(player, spellMap); + return 1; + }) + ) + ) + ) + ) + .then(CommandManager.literal("add") + .then(CommandManager.argument("player", EntityArgumentType.player()) + .then(CommandManager.argument("spell", SpellArgumentType.spell()) + .then(CommandManager.argument("level", IntegerArgumentType.integer()) + .executes(ctx -> { + PlayerEntity player = EntityArgumentType.getPlayer(ctx, "player"); + Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); + int level = IntegerArgumentType.getInteger(ctx, "level") - 1; + + ItemStack stack = player.getMainHandStack(); + + if (stack.getItem() != SorceryCraft.SPELL_ITEM) { + throw NOT_HOLDING_SPELL_EXCEPTION.create(player); + } + + Map spellMap = SpellTag.getSpells(stack); + spellMap.put(spell, level); + SpellTag.setSpells(stack, spellMap); + + ctx.getSource().sendFeedback(new TranslatableText("command.sorcerycraft.spell.applied_spell", SpellTag.getTranslatedSpell(spell, level, true)), true); + return 1; + }) + ) + ) + ) + ) + .then(CommandManager.literal("remove") + .then(CommandManager.argument("player", EntityArgumentType.player()) + .then(CommandManager.argument("spell", SpellArgumentType.spell()) + .executes(ctx -> { + PlayerEntity player = EntityArgumentType.getPlayer(ctx, "player"); + Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); + + ItemStack stack = player.getMainHandStack(); + + if (stack.getItem() != SorceryCraft.SPELL_ITEM) { + throw NOT_HOLDING_SPELL_EXCEPTION.create(player); + } + + Map spellMap = SpellTag.getSpells(stack); + spellMap.remove(spell); + SpellTag.setSpells(stack, spellMap); + + ctx.getSource().sendFeedback(new TranslatableText("command.sorcerycraft.spell.removed_spell", SpellTag.getTranslatedSpell(spell, 0, false)), true); + return 1; + }) + ) + ) + ) ); } } diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/entity/SpellEntity.java b/src/main/java/com/thebrokenrail/sorcerycraft/entity/SpellEntity.java index dbe03bf..b88a7f9 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/entity/SpellEntity.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/entity/SpellEntity.java @@ -1,10 +1,10 @@ package com.thebrokenrail.sorcerycraft.entity; import com.thebrokenrail.sorcerycraft.SorceryCraft; -import com.thebrokenrail.sorcerycraft.spell.Spell; -import com.thebrokenrail.sorcerycraft.spell.SpellRegistry; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; -import com.thebrokenrail.sorcerycraft.spell.Spells; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; +import com.thebrokenrail.sorcerycraft.spell.registry.SpellRegistry; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.registry.Spells; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.entity.Entity; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/item/SpellItem.java b/src/main/java/com/thebrokenrail/sorcerycraft/item/SpellItem.java index 85e875d..b584516 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/item/SpellItem.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/item/SpellItem.java @@ -2,22 +2,18 @@ package com.thebrokenrail.sorcerycraft.item; import com.thebrokenrail.sorcerycraft.SorceryCraft; import com.thebrokenrail.sorcerycraft.entity.SpellEntity; -import com.thebrokenrail.sorcerycraft.spell.Spell; -import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity; -import com.thebrokenrail.sorcerycraft.spell.SpellRegistry; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; +import com.thebrokenrail.sorcerycraft.spell.registry.SpellRegistry; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; -import net.minecraft.text.LiteralText; import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; import net.minecraft.util.ActionResult; import net.minecraft.util.DefaultedList; -import net.minecraft.util.Formatting; import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.Rarity; @@ -63,7 +59,7 @@ public class SpellItem extends Item { public void appendTooltip(ItemStack itemStack, World world, List tooltip, TooltipContext tooltipContext) { Map spells = SpellTag.getSpells(itemStack); for (Map.Entry entry : spells.entrySet()) { - tooltip.add(SpellTag.getTranslatedSpell(entry.getKey(), entry.getValue())); + tooltip.add(SpellTag.getTranslatedSpell(entry.getKey(), entry.getValue(), true)); } } @@ -92,35 +88,9 @@ public class SpellItem extends Item { super.inventoryTick(stack, world, entity, slot, selected); if (!world.isClient() && entity instanceof PlayerEntity) { PlayerEntity player = (PlayerEntity) entity; - SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; - - Map playerSpells = spellPlayer.getSorceryCraftSpells(); Map itemSpells = SpellTag.getSpells(player.inventory.getInvStack(slot)); - boolean changed = false; - - for (Map.Entry entry : itemSpells.entrySet()) { - Spell spell = SpellRegistry.getSpell(entry.getKey(), entry.getValue()); - if (spell != null) { - if (spell.getLevel() >= spell.getMaxLevel()) { - spell = SpellRegistry.getSpell(entry.getKey(), spell.getMaxLevel() - 1); - } - assert spell != null; - if (!playerSpells.containsKey(spell.getID()) || playerSpells.get(spell.getID()) < spell.getLevel()) { - changed = true; - - playerSpells.put(spell.getID(), spell.getLevel()); - assert world.getServer() != null; - Text text = new LiteralText("[").append(SpellTag.getTranslatedSpell(spell.getID(), spell.getLevel()).getString()).append("]").formatted(Formatting.GREEN); - world.getServer().getPlayerManager().sendToAll(new TranslatableText("chat." + SorceryCraft.NAMESPACE + ".new_spell", player.getDisplayName(), text)); - } - } - } - - if (changed) { - SorceryCraft.playSpellSound(player); - spellPlayer.setSorceryCraftSpells(playerSpells); - } + SpellTag.learnSpells(player, itemSpells); } } } diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java index 0c94bc0..be5ff8d 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinPlayerEntity.java @@ -1,7 +1,7 @@ package com.thebrokenrail.sorcerycraft.mixin; -import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Identifier; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java index b3cc962..e30c039 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/mixin/MixinServerPlayerEntity.java @@ -1,8 +1,8 @@ package com.thebrokenrail.sorcerycraft.mixin; import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket; -import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.network.ServerPlayerEntity; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java b/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java index f3213ce..7da47f2 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/packet/UpdateKnownSpellsS2CPacket.java @@ -1,8 +1,8 @@ package com.thebrokenrail.sorcerycraft.packet; import com.thebrokenrail.sorcerycraft.SorceryCraft; -import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity; -import com.thebrokenrail.sorcerycraft.spell.SpellTag; +import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; +import com.thebrokenrail.sorcerycraft.spell.util.SpellTag; import io.netty.buffer.Unpooled; import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/DamageSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/DamageSpell.java index 98adafe..87c15d7 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/DamageSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/DamageSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffects; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/DissolveSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/DissolveSpell.java index 3328143..f878a6e 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/DissolveSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/DissolveSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/FlameSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/FlameSpell.java index 9c645c7..9de5414 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/FlameSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/FlameSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/HealSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/HealSpell.java index 1eda67f..86179e7 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/HealSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/HealSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffects; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/InwardSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/InwardSpell.java index 2b02314..2a6ee96 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/InwardSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/InwardSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/LevitateSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/LevitateSpell.java index ee76d98..64a5611 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/LevitateSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/LevitateSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffectInstance; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SteadfastSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/SteadfastSpell.java index 2e9c755..94321bc 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SteadfastSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/SteadfastSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/TeleportSpell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/TeleportSpell.java index bb67c7f..a935495 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/TeleportSpell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/TeleportSpell.java @@ -1,5 +1,6 @@ package com.thebrokenrail.sorcerycraft.spell; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/Spell.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/Spell.java similarity index 91% rename from src/main/java/com/thebrokenrail/sorcerycraft/spell/Spell.java rename to src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/Spell.java index fa7b3ce..bcbe6fd 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/Spell.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/Spell.java @@ -1,4 +1,4 @@ -package com.thebrokenrail.sorcerycraft.spell; +package com.thebrokenrail.sorcerycraft.spell.registry; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellRegistry.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/SpellRegistry.java similarity index 84% rename from src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellRegistry.java rename to src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/SpellRegistry.java index 216edfe..7b58ca0 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellRegistry.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/SpellRegistry.java @@ -1,4 +1,4 @@ -package com.thebrokenrail.sorcerycraft.spell; +package com.thebrokenrail.sorcerycraft.spell.registry; import net.minecraft.util.Identifier; @@ -11,6 +11,10 @@ import java.util.Map; public class SpellRegistry { private static final Map> spells = new HashMap<>(); + public static Spell getSpell(Map.Entry entry) { + return getSpell(entry.getKey(), entry.getValue()); + } + public static Spell getSpell(Identifier id, int level) { if (!spells.containsKey(id)) { return null; @@ -52,4 +56,8 @@ public class SpellRegistry { spells.put(id, spell); return id; } + + public static Identifier[] getSpellsID() { + return spells.keySet().toArray(new Identifier[0]); + } } diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/Spells.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/Spells.java similarity index 73% rename from src/main/java/com/thebrokenrail/sorcerycraft/spell/Spells.java rename to src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/Spells.java index adacc54..631c35f 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/Spells.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/registry/Spells.java @@ -1,6 +1,15 @@ -package com.thebrokenrail.sorcerycraft.spell; +package com.thebrokenrail.sorcerycraft.spell.registry; import com.thebrokenrail.sorcerycraft.SorceryCraft; +import com.thebrokenrail.sorcerycraft.spell.DamageSpell; +import com.thebrokenrail.sorcerycraft.spell.DissolveSpell; +import com.thebrokenrail.sorcerycraft.spell.FlameSpell; +import com.thebrokenrail.sorcerycraft.spell.HealSpell; +import com.thebrokenrail.sorcerycraft.spell.InwardSpell; +import com.thebrokenrail.sorcerycraft.spell.LevitateSpell; +import com.thebrokenrail.sorcerycraft.spell.SteadfastSpell; +import com.thebrokenrail.sorcerycraft.spell.TeleportSpell; +import com.thebrokenrail.sorcerycraft.spell.registry.SpellRegistry; import net.minecraft.util.Identifier; @SuppressWarnings("unused") diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/RandomSpellLootTableFunction.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/RandomSpellLootTableFunction.java similarity index 88% rename from src/main/java/com/thebrokenrail/sorcerycraft/spell/RandomSpellLootTableFunction.java rename to src/main/java/com/thebrokenrail/sorcerycraft/spell/util/RandomSpellLootTableFunction.java index 13cdbd4..0b8d1e7 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/RandomSpellLootTableFunction.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/RandomSpellLootTableFunction.java @@ -1,5 +1,7 @@ -package com.thebrokenrail.sorcerycraft.spell; +package com.thebrokenrail.sorcerycraft.spell.util; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; +import com.thebrokenrail.sorcerycraft.spell.registry.SpellRegistry; import net.minecraft.item.ItemStack; import net.minecraft.loot.condition.LootCondition; import net.minecraft.loot.context.LootContext; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellPlayerEntity.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellPlayerEntity.java similarity index 81% rename from src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellPlayerEntity.java rename to src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellPlayerEntity.java index c8d9b38..c453bb6 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellPlayerEntity.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellPlayerEntity.java @@ -1,4 +1,4 @@ -package com.thebrokenrail.sorcerycraft.spell; +package com.thebrokenrail.sorcerycraft.spell.util; import net.minecraft.util.Identifier; diff --git a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellTag.java b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellTag.java similarity index 58% rename from src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellTag.java rename to src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellTag.java index a751ac1..fc2e650 100644 --- a/src/main/java/com/thebrokenrail/sorcerycraft/spell/SpellTag.java +++ b/src/main/java/com/thebrokenrail/sorcerycraft/spell/util/SpellTag.java @@ -1,14 +1,19 @@ -package com.thebrokenrail.sorcerycraft.spell; +package com.thebrokenrail.sorcerycraft.spell.util; import com.thebrokenrail.sorcerycraft.SorceryCraft; +import com.thebrokenrail.sorcerycraft.spell.registry.Spell; +import com.thebrokenrail.sorcerycraft.spell.registry.SpellRegistry; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; +import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.world.World; import java.util.HashMap; import java.util.Map; @@ -81,12 +86,44 @@ public class SpellTag { return map; } - public static Text getTranslatedSpell(Identifier id, int level) { + public static Text getTranslatedSpell(Identifier id, int level, boolean allowNumber) { Text text = new TranslatableText("spell." + id.getNamespace() + '.' + id.getPath()); text.formatted(Formatting.GRAY); - if (level != 0 || SpellRegistry.getMaxLevel(id) != 1) { + if ((level != 0 || SpellRegistry.getMaxLevel(id) != 1) && allowNumber) { text.append(" ").append(new TranslatableText("enchantment.level." + (level + 1))); } return text; } + + public static void learnSpells(PlayerEntity player, Map itemSpells) { + SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; + World world = player.getEntityWorld(); + + Map playerSpells = spellPlayer.getSorceryCraftSpells(); + + boolean changed = false; + + for (Map.Entry entry : itemSpells.entrySet()) { + Spell spell = SpellRegistry.getSpell(entry.getKey(), entry.getValue()); + if (spell != null) { + if (spell.getLevel() >= spell.getMaxLevel()) { + spell = SpellRegistry.getSpell(entry.getKey(), spell.getMaxLevel() - 1); + } + assert spell != null; + if (!playerSpells.containsKey(spell.getID()) || playerSpells.get(spell.getID()) < spell.getLevel()) { + changed = true; + + playerSpells.put(spell.getID(), spell.getLevel()); + assert world.getServer() != null; + Text text = new LiteralText("[").append(SpellTag.getTranslatedSpell(spell.getID(), spell.getLevel(), true).getString()).append("]").formatted(Formatting.GREEN); + world.getServer().getPlayerManager().sendToAll(new TranslatableText("chat." + SorceryCraft.NAMESPACE + ".new_spell", player.getDisplayName(), text)); + } + } + } + + if (changed) { + SorceryCraft.playSpellSound(player); + spellPlayer.setSorceryCraftSpells(playerSpells); + } + } } diff --git a/src/main/resources/assets/sorcerycraft/lang/en_us.json b/src/main/resources/assets/sorcerycraft/lang/en_us.json index 9885440..e225255 100644 --- a/src/main/resources/assets/sorcerycraft/lang/en_us.json +++ b/src/main/resources/assets/sorcerycraft/lang/en_us.json @@ -8,6 +8,10 @@ "entity.sorcerycraft.spell": "Spell", "command.sorcerycraft.spell.cleared_spells": "All spells cleared from %s", "command.sorcerycraft.spell.listing_spells": "%s knows the following spells:", + "command.sorcerycraft.spell.unknown_spell": "Unknown spell: %s", + "command.sorcerycraft.spell.not_holding_spell": "%s is not holding a Spell", + "command.sorcerycraft.spell.applied_spell": "Applied Spell %s", + "command.sorcerycraft.spell.removed_spell": "Removed Spell %s", "spell.sorcerycraft.damage_spell": "Damage", "spell.sorcerycraft.heal_spell": "Heal", "spell.sorcerycraft.dissolve_spell": "Dissolve",