1.1.12
SorceryCraft/pipeline/head This commit looks good Details

Update Mappings
Add Config Screen
Clarify Terms
This commit is contained in:
TheBrokenRail 2020-03-16 11:21:06 -04:00
parent 998e514cd9
commit a3be3712d4
17 changed files with 143 additions and 44 deletions

View File

@ -1,5 +1,10 @@
# Changelog
**1.1.12**
* Update Mappings
* Add Config Screen
* Clarify Terms
**1.1.11**
* Update Mappings
* Add Lightning Spell

View File

@ -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)

View File

@ -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 {

View File

@ -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

View 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;
}
}

View File

@ -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))

View File

@ -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();
}
}

View File

@ -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())

View File

@ -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

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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();
}

View File

@ -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);
}
}
}

View File

@ -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",

View File

@ -21,6 +21,9 @@
],
"client": [
"com.thebrokenrail.sorcerycraft.SorceryCraft"
],
"modmenu": [
"com.thebrokenrail.sorcerycraft.client.ModMenu"
]
},
"mixins": [