Update Mappings Add Config Screen Clarify Terms
This commit is contained in:
parent
998e514cd9
commit
a3be3712d4
@ -1,5 +1,10 @@
|
||||
# Changelog
|
||||
|
||||
**1.1.12**
|
||||
* Update Mappings
|
||||
* Add Config Screen
|
||||
* Clarify Terms
|
||||
|
||||
**1.1.11**
|
||||
* Update Mappings
|
||||
* Add Lightning Spell
|
||||
|
20
README.md
20
README.md
@ -4,10 +4,10 @@ Cast Spells in Minecraft!
|
||||
This mod currently supports the Minecraft 1.16 snapshots.
|
||||
|
||||
## What are Spells?
|
||||
Spells are found throughout the world in chests. When you pick up a Spell you will learn it, one you learn a Spell you can apply it to a blank or existing Spell in the Casting Table. You can cast Spells by right-clicking. There is also a 30% chance the spell will rebound and hit you instead, unless the "Steadfast" Spell is applied.
|
||||
Spells are found throughout the world in chests. When you pick up a Spell you will "discover" it, once you "discover" a spell you can apply it to a blank or existing spell in the Casting Table. You can cast spells by right-clicking. There is also a 30% chance (by default) that the spell will rebound and hit you instead, unless the "Steadfast" spell is applied.
|
||||
|
||||
## What's a Casting Table?
|
||||
You can apply Spells to blank or existing Spells in the Casting Table. Doing so will require a certain amount of levels, and sometimes may require an item.
|
||||
You can apply Spells to blank or existing spells in the Casting Table. Doing so will require a certain amount of levels, and may require an item.
|
||||
|
||||
## Crafting
|
||||
#### Blank Spell
|
||||
@ -56,9 +56,9 @@ You can apply Spells to blank or existing Spells in the Casting Table. Doing so
|
||||
| Heal | 2 | Heals target. |
|
||||
| Dissolve | 1 | Removes target's status effects. |
|
||||
| Levitate | 2 | Gives target the Levitation effect. |
|
||||
| Steadfast | 1 | Prevents Spell from failing. This does nothing on its own. |
|
||||
| Teleport | 2 | Teleports target to random location. |
|
||||
| Inward | 1 | Causes the Spell to target the caster. If the Spell fails instead of rebounding, it will just do nothing. This does nothing on its own. |
|
||||
| Steadfast | 1 | Prevents the spell from failing. This spell does nothing on its own. |
|
||||
| Teleport | 2 | Teleports the target to a random location. |
|
||||
| Inward | 1 | Causes the spell to target the caster. If the spell fails instead of rebounding, it will just do nothing. This spell does nothing on its own. |
|
||||
| Cooling | 1 | Extinguish the target if they are on fire. |
|
||||
| Lightning | 1 | Strikes the target with lightning. |
|
||||
|
||||
@ -71,14 +71,14 @@ This command clears all known spells from the given player.
|
||||
#### ```/spell list <player>```
|
||||
This lists all the spells the given player knows.
|
||||
|
||||
#### ```/spell learn <player> <spell-id> <level>```
|
||||
This teaches the specified spell to the specified player.
|
||||
#### ```/spell discover <player> <spell-id> <level>```
|
||||
This adds the specified spell to the specified player's discovered spells list.
|
||||
|
||||
#### ```/spell add <player> <spell-id> <level>```
|
||||
This adds the specified spell to the item in the player's main hand.
|
||||
#### ```/spell apply <player> <spell-id> <level>```
|
||||
This adds the specified spell to the item in the specified player's main hand.
|
||||
|
||||
#### ```/spell remove <player> <spell-id>```
|
||||
This removes the specified spell from the item in the player's main hand.
|
||||
This removes the specified spell from the item in the specified player's main hand.
|
||||
|
||||
## API
|
||||
[View API](API.md)
|
||||
|
17
build.gradle
17
build.gradle
@ -15,11 +15,24 @@ group = project.maven_group as Object
|
||||
minecraft {
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://dl.bintray.com/shedaniel/autoconfig1u/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.fabric_loader_version}"
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
|
||||
|
||||
modImplementation "me.shedaniel.cloth:config-2:${project.cloth_config_version}"
|
||||
include "me.shedaniel.cloth:config-2:${project.cloth_config_version}"
|
||||
modImplementation "me.sargunvohra.mcmods:autoconfig1u:${project.auto_config_version}"
|
||||
include "me.sargunvohra.mcmods:autoconfig1u:${project.auto_config_version}"
|
||||
modImplementation "io.github.prospector:modmenu:${project.mod_menu_version}"
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -6,14 +6,17 @@ org.gradle.jvmargs = -Xmx1G
|
||||
minecraft_version = 20w11a
|
||||
curseforge_id = 365308
|
||||
simple_minecraft_version = 1.16-Snapshot
|
||||
yarn_mappings = 20w11a+build.6
|
||||
loader_version = 0.7.8+build.187
|
||||
yarn_mappings = 20w11a+build.7
|
||||
fabric_loader_version = 0.7.8+build.187
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 1.1.11
|
||||
mod_version = 1.1.12
|
||||
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.5.3+build.308-1.16
|
||||
fabric_api_version = 0.5.3+build.308-1.16
|
||||
cloth_config_version = 3.0.2-unstable.202003090708
|
||||
auto_config_version = 1.2.4
|
||||
mod_menu_version = 1.10.2+build.32
|
||||
|
32
src/main/java/com/thebrokenrail/sorcerycraft/ModConfig.java
Normal file
32
src/main/java/com/thebrokenrail/sorcerycraft/ModConfig.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.thebrokenrail.sorcerycraft;
|
||||
|
||||
import me.sargunvohra.mcmods.autoconfig1u.ConfigData;
|
||||
import me.sargunvohra.mcmods.autoconfig1u.annotation.Config;
|
||||
import me.sargunvohra.mcmods.autoconfig1u.annotation.ConfigEntry;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Config(name = SorceryCraft.NAMESPACE)
|
||||
public class ModConfig implements ConfigData {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
@interface UsePercentage {
|
||||
double min();
|
||||
|
||||
double max();
|
||||
}
|
||||
|
||||
@UsePercentage(min = 0, max = 1)
|
||||
public double failureChance = 0.3;
|
||||
|
||||
@ConfigEntry.Gui.CollapsibleObject(startExpanded = true)
|
||||
public LimitCastingTable limitCastingTable = new LimitCastingTable();
|
||||
|
||||
public static class LimitCastingTable {
|
||||
public boolean creative = false;
|
||||
public boolean survival = true;
|
||||
}
|
||||
}
|
@ -11,6 +11,11 @@ import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket;
|
||||
import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket;
|
||||
import com.thebrokenrail.sorcerycraft.spell.util.RandomSpellLootTableFunction;
|
||||
import com.thebrokenrail.sorcerycraft.spell.registry.Spells;
|
||||
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
||||
import me.sargunvohra.mcmods.autoconfig1u.gui.registry.GuiRegistry;
|
||||
import me.sargunvohra.mcmods.autoconfig1u.serializer.GsonConfigSerializer;
|
||||
import me.sargunvohra.mcmods.autoconfig1u.util.Utils;
|
||||
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
|
||||
@ -47,10 +52,12 @@ import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPointer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Position;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
||||
@ -72,10 +79,13 @@ public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
||||
LootTables.PILLAGER_OUTPOST_CHEST,
|
||||
LootTables.WOODLAND_MANSION_CHEST
|
||||
};
|
||||
public static final double SPELL_FAILURE_CHANCE = 0.3d;
|
||||
public static Identifier STAT_INTERACT_WITH_CASTING_TABLE;
|
||||
public static Identifier STAT_CAST_SPELL;
|
||||
|
||||
public static ModConfig getConfig() {
|
||||
return AutoConfig.getConfigHolder(ModConfig.class).getConfig();
|
||||
}
|
||||
|
||||
private boolean isSelectedLootTable(Identifier lootTable) {
|
||||
for (Identifier id : LOOT_TABLES) {
|
||||
if (id.equals(lootTable)) {
|
||||
@ -89,6 +99,13 @@ public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
||||
public void onInitialize() {
|
||||
new Spells();
|
||||
|
||||
AutoConfig.register(ModConfig.class, GsonConfigSerializer::new);
|
||||
GuiRegistry guiRegistry = AutoConfig.getGuiRegistry(ModConfig.class);
|
||||
guiRegistry.registerAnnotationProvider((s, field, config, defaults, guiRegistryAccess) -> {
|
||||
ModConfig.UsePercentage bounds = field.getAnnotation(ModConfig.UsePercentage.class);
|
||||
return Collections.singletonList(ConfigEntryBuilder.create().startIntSlider(s, MathHelper.ceil(Utils.getUnsafely(field, config, 0.0) * 100), MathHelper.ceil(bounds.min() * 100), MathHelper.ceil(bounds.max() * 100)).setDefaultValue(() -> MathHelper.ceil((double) Utils.getUnsafely(field, defaults) * 100)).setSaveConsumer((newValue) -> Utils.setUnsafely(field, config, newValue / 100d)).setTextGetter(integer -> String.format("%d%%", integer)).build());
|
||||
}, field -> field.getType() == Double.TYPE || field.getType() == Double.class, ModConfig.UsePercentage.class);
|
||||
|
||||
ITEM_GROUP = FabricItemGroupBuilder.create(
|
||||
new Identifier(NAMESPACE, "spells"))
|
||||
.icon(() -> new ItemStack(SPELL_ITEM))
|
||||
|
@ -0,0 +1,20 @@
|
||||
package com.thebrokenrail.sorcerycraft.client;
|
||||
|
||||
import com.thebrokenrail.sorcerycraft.ModConfig;
|
||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||
import io.github.prospector.modmenu.api.ConfigScreenFactory;
|
||||
import io.github.prospector.modmenu.api.ModMenuApi;
|
||||
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
public class ModMenu implements ModMenuApi {
|
||||
@Override
|
||||
public String getModId() {
|
||||
return SorceryCraft.NAMESPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||
return (ConfigScreenFactory<Screen>) screen -> AutoConfig.getConfigScreen(ModConfig.class, screen).get();
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ public class SpellCommand {
|
||||
PlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
|
||||
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.listing_spells", player.getDisplayName()), false);
|
||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||
Map<Identifier, Integer> spells = spellPlayer.getSorceryCraftSpells();
|
||||
Map<Identifier, Integer> spells = spellPlayer.getDiscoveredSpells();
|
||||
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
||||
ctx.getSource().sendFeedback(SpellTag.getTranslatedSpell(entry.getKey(), entry.getValue(), true).formatted(Formatting.YELLOW), false);
|
||||
}
|
||||
@ -43,13 +43,13 @@ public class SpellCommand {
|
||||
.executes(ctx -> {
|
||||
PlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
|
||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||
spellPlayer.setSorceryCraftSpells(new HashMap<>());
|
||||
spellPlayer.setDiscoveredSpells(new HashMap<>());
|
||||
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.cleared_spells", player.getDisplayName()), true);
|
||||
return 1;
|
||||
})
|
||||
)
|
||||
)
|
||||
.then(CommandManager.literal("learn")
|
||||
.then(CommandManager.literal("discover")
|
||||
.then(CommandManager.argument("player", EntityArgumentType.player())
|
||||
.then(CommandManager.argument("spell", SpellArgumentType.spell())
|
||||
.then(CommandManager.argument("level", IntegerArgumentType.integer())
|
||||
@ -66,7 +66,7 @@ public class SpellCommand {
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(CommandManager.literal("add")
|
||||
.then(CommandManager.literal("apply")
|
||||
.then(CommandManager.argument("player", EntityArgumentType.player())
|
||||
.then(CommandManager.argument("spell", SpellArgumentType.spell())
|
||||
.then(CommandManager.argument("level", IntegerArgumentType.integer())
|
||||
|
@ -42,7 +42,7 @@ public class SpellEntity extends ThrownItemEntity {
|
||||
}
|
||||
|
||||
private boolean didSpellSucceed(Map<Identifier, Integer> spells) {
|
||||
return Math.random() > SorceryCraft.SPELL_FAILURE_CHANCE || spells.containsKey(Spells.STEADFAST_SPELL);
|
||||
return Math.random() > SorceryCraft.getConfig().failureChance || spells.containsKey(Spells.STEADFAST_SPELL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,11 +43,9 @@ public class CastingTableScreenHandler extends ScreenHandler {
|
||||
context = blockContext;
|
||||
result = new CraftingResultInventory();
|
||||
|
||||
if (playerInventory.player.isCreative()) {
|
||||
spells = SpellRegistry.getSpells();
|
||||
} else {
|
||||
if (playerInventory.player.isCreative() ? SorceryCraft.getConfig().limitCastingTable.creative : SorceryCraft.getConfig().limitCastingTable.survival) {
|
||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) playerInventory.player;
|
||||
Map<Identifier, Integer> spellsMap = spellPlayer.getSorceryCraftSpells();
|
||||
Map<Identifier, Integer> spellsMap = spellPlayer.getDiscoveredSpells();
|
||||
List<Spell> spellsArray = new ArrayList<>();
|
||||
|
||||
Spell[] allSpells = SpellRegistry.getSpells();
|
||||
@ -57,6 +55,8 @@ public class CastingTableScreenHandler extends ScreenHandler {
|
||||
}
|
||||
}
|
||||
spells = spellsArray.toArray(new Spell[0]);
|
||||
} else {
|
||||
spells = SpellRegistry.getSpells();
|
||||
}
|
||||
|
||||
addSlot(new Slot(inventory, 0, 136, 37) {
|
||||
|
@ -16,25 +16,26 @@ import java.util.Map;
|
||||
@SuppressWarnings("unused")
|
||||
@Mixin(PlayerEntity.class)
|
||||
public class MixinPlayerEntity implements SpellPlayerEntity {
|
||||
private Map<Identifier, Integer> sorceryCraftSpells = new HashMap<>();
|
||||
// Namespace Fields
|
||||
private Map<Identifier, Integer> sorceryCraftDiscoveredSpells = new HashMap<>();
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "readCustomDataFromTag")
|
||||
public void readCustomDataFromTag(CompoundTag tag, CallbackInfo info) {
|
||||
sorceryCraftSpells = SpellTag.getSpells(tag);
|
||||
sorceryCraftDiscoveredSpells = SpellTag.getSpells(tag);
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "writeCustomDataToTag")
|
||||
public void writeCustomDataToTag(CompoundTag tag, CallbackInfo info) {
|
||||
tag.put(SpellTag.SPELL_TAG, SpellTag.createSpellsTag(sorceryCraftSpells));
|
||||
tag.put(SpellTag.SPELL_TAG, SpellTag.createSpellsTag(sorceryCraftDiscoveredSpells));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSorceryCraftSpells(Map<Identifier, Integer> spells) {
|
||||
this.sorceryCraftSpells = spells;
|
||||
public void setDiscoveredSpells(Map<Identifier, Integer> spells) {
|
||||
this.sorceryCraftDiscoveredSpells = spells;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Identifier, Integer> getSorceryCraftSpells() {
|
||||
return sorceryCraftSpells;
|
||||
public Map<Identifier, Integer> getDiscoveredSpells() {
|
||||
return sorceryCraftDiscoveredSpells;
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ public abstract class MixinServerPlayerEntity implements SpellPlayerEntity {
|
||||
SpellPlayerEntity oldSpellPlayer = (SpellPlayerEntity) oldPlayer;
|
||||
SpellPlayerEntity newSpellPlayer = this;
|
||||
|
||||
newSpellPlayer.setSorceryCraftSpells(oldSpellPlayer.getSorceryCraftSpells());
|
||||
newSpellPlayer.setDiscoveredSpells(oldSpellPlayer.getDiscoveredSpells());
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "playerTick")
|
||||
public void playerTick(CallbackInfo info) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.put(SpellTag.SPELL_TAG, SpellTag.createSpellsTag(getSorceryCraftSpells()));
|
||||
tag.put(SpellTag.SPELL_TAG, SpellTag.createSpellsTag(getDiscoveredSpells()));
|
||||
//noinspection ConstantConditions
|
||||
UpdateKnownSpellsS2CPacket.send((ServerPlayerEntity) (Object) this, tag);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class UpdateKnownSpellsS2CPacket {
|
||||
CompoundTag tag = bytes.readCompoundTag();
|
||||
if (context.getPlayer() != null) {
|
||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) context.getPlayer();
|
||||
spellPlayer.setSorceryCraftSpells(SpellTag.getSpells(tag));
|
||||
spellPlayer.setDiscoveredSpells(SpellTag.getSpells(tag));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import net.minecraft.util.Identifier;
|
||||
import java.util.Map;
|
||||
|
||||
public interface SpellPlayerEntity {
|
||||
void setSorceryCraftSpells(Map<Identifier, Integer> spells);
|
||||
void setDiscoveredSpells(Map<Identifier, Integer> spells);
|
||||
|
||||
Map<Identifier, Integer> getSorceryCraftSpells();
|
||||
Map<Identifier, Integer> getDiscoveredSpells();
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public class SpellTag {
|
||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||
World world = player.getEntityWorld();
|
||||
|
||||
Map<Identifier, Integer> playerSpells = spellPlayer.getSorceryCraftSpells();
|
||||
Map<Identifier, Integer> playerSpells = spellPlayer.getDiscoveredSpells();
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
@ -119,7 +119,7 @@ public class SpellTag {
|
||||
|
||||
if (changed) {
|
||||
SorceryCraft.playSpellSound(player);
|
||||
spellPlayer.setSorceryCraftSpells(playerSpells);
|
||||
spellPlayer.setDiscoveredSpells(playerSpells);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,16 +4,21 @@
|
||||
"itemGroup.sorcerycraft.spells": "SorceryCraft",
|
||||
"container.sorcerycraft.casting_table": "Casting Table",
|
||||
"container.sorcerycraft.spells": "Spells",
|
||||
"chat.sorcerycraft.new_spell": "%s has learned the spell %s",
|
||||
"chat.sorcerycraft.new_spell": "%s has discovered the spell %s",
|
||||
"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.cleared_spells": "All discovered spells cleared from %s",
|
||||
"command.sorcerycraft.spell.listing_spells": "%s has discovered 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.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",
|
||||
"stat.sorcerycraft.interact_with_casting_table": "Interactions with Casting Table",
|
||||
"stat.sorcerycraft.cast_spell": "Spells Cast",
|
||||
"text.autoconfig.sorcerycraft.title": "SorceryCraft Config",
|
||||
"text.autoconfig.sorcerycraft.option.failureChance": "Spell Failure Chance",
|
||||
"text.autoconfig.sorcerycraft.option.limitCastingTable": "Limit Casting Table to discovered spells",
|
||||
"text.autoconfig.sorcerycraft.option.limitCastingTable.creative": "Creative Mode",
|
||||
"text.autoconfig.sorcerycraft.option.limitCastingTable.survival": "Survival Mode",
|
||||
"spell.sorcerycraft.damage_spell": "Damage",
|
||||
"spell.sorcerycraft.heal_spell": "Heal",
|
||||
"spell.sorcerycraft.dissolve_spell": "Dissolve",
|
||||
|
@ -21,6 +21,9 @@
|
||||
],
|
||||
"client": [
|
||||
"com.thebrokenrail.sorcerycraft.SorceryCraft"
|
||||
],
|
||||
"modmenu": [
|
||||
"com.thebrokenrail.sorcerycraft.client.ModMenu"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
|
Reference in New Issue
Block a user