From f0752317e64b9bcd2485657897f426471c2d79d1 Mon Sep 17 00:00:00 2001
From: Electroblob77 <35599699+Electroblob77@users.noreply.github.com>
Date: Sat, 18 Apr 2020 21:45:01 +0100
Subject: [PATCH] Add spell quick access keys
---
.../wizardry/client/ClientProxy.java | 11 ++++
.../client/WizardryControlHandler.java | 28 ++++++++
.../wizardry/item/ISpellCastingItem.java | 10 +++
.../electroblob/wizardry/item/ItemWand.java | 5 ++
.../packet/PacketSpellQuickAccess.java | 66 +++++++++++++++++++
.../packet/WizardryPacketHandler.java | 37 ++++++-----
.../electroblob/wizardry/util/WandHelper.java | 20 ++++++
.../assets/ebwizardry/lang/en_gb.lang | 8 +++
.../assets/ebwizardry/lang/en_us.lang | 8 +++
9 files changed, 175 insertions(+), 18 deletions(-)
create mode 100644 src/main/java/electroblob/wizardry/packet/PacketSpellQuickAccess.java
diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java
index da53f756..d4d68860 100644
--- a/src/main/java/electroblob/wizardry/client/ClientProxy.java
+++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java
@@ -16,6 +16,7 @@ import electroblob.wizardry.client.particle.*;
import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory;
import electroblob.wizardry.client.renderer.*;
import electroblob.wizardry.command.SpellEmitter;
+import electroblob.wizardry.constants.Constants;
import electroblob.wizardry.data.DispenserCastingData;
import electroblob.wizardry.data.SpellEmitterData;
import electroblob.wizardry.data.SpellGlyphData;
@@ -72,6 +73,7 @@ import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.village.MerchantRecipeList;
import net.minecraft.world.World;
import net.minecraftforge.client.settings.KeyConflictContext;
+import net.minecraftforge.client.settings.KeyModifier;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.fml.client.config.GuiConfigEntries.NumberSliderEntry;
@@ -103,6 +105,14 @@ public class ClientProxy extends CommonProxy {
// Key Bindings
public static final KeyBinding NEXT_SPELL = new KeyBinding("key." + Wizardry.MODID + ".next_spell", KeyConflictContext.IN_GAME, Keyboard.KEY_N, "key.categories." + Wizardry.MODID);
public static final KeyBinding PREVIOUS_SPELL = new KeyBinding("key." + Wizardry.MODID + ".previous_spell", KeyConflictContext.IN_GAME, Keyboard.KEY_B, "key.categories." + Wizardry.MODID);
+ public static final KeyBinding[] SPELL_QUICK_ACCESS = new KeyBinding[ItemWand.BASE_SPELL_SLOTS + Constants.UPGRADE_STACK_LIMIT];
+
+ static {
+ for(int i = 0; i < SPELL_QUICK_ACCESS.length; i++){
+ SPELL_QUICK_ACCESS[i] = new KeyBinding("key." + Wizardry.MODID + ".spell_" + (i+1),
+ KeyConflictContext.IN_GAME, KeyModifier.ALT, Keyboard.KEY_1 + i, "key.categories." + Wizardry.MODID);
+ }
+ }
// Armour Model
public static final ModelBiped WIZARD_ARMOUR_MODEL = new ModelWizardArmour(0.75f);
@@ -122,6 +132,7 @@ public class ClientProxy extends CommonProxy {
public void registerKeyBindings(){
ClientRegistry.registerKeyBinding(NEXT_SPELL);
ClientRegistry.registerKeyBinding(PREVIOUS_SPELL);
+ for(KeyBinding key : SPELL_QUICK_ACCESS) ClientRegistry.registerKeyBinding(key);
}
@Override
diff --git a/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java b/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java
index 7b98aca0..377880a1 100644
--- a/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java
+++ b/src/main/java/electroblob/wizardry/client/WizardryControlHandler.java
@@ -4,6 +4,7 @@ import electroblob.wizardry.Wizardry;
import electroblob.wizardry.client.gui.GuiSpellDisplay;
import electroblob.wizardry.item.ISpellCastingItem;
import electroblob.wizardry.packet.PacketControlInput;
+import electroblob.wizardry.packet.PacketSpellQuickAccess;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.WizardrySounds;
import net.minecraft.client.Minecraft;
@@ -24,6 +25,7 @@ public class WizardryControlHandler {
static boolean NkeyPressed = false;
static boolean BkeyPressed = false;
+ static boolean[] quickAccessKeyPressed = new boolean[ClientProxy.SPELL_QUICK_ACCESS.length];
// Changed to a tick event to allow mouse button keybinds
// The 'lag' that happened previously was actually because the code only fired when a keyboard key was pressed!
@@ -59,6 +61,19 @@ public class WizardryControlHandler {
}else{
BkeyPressed = false;
}
+
+ for(int i = 0; i < ClientProxy.SPELL_QUICK_ACCESS.length; i++){
+ if(ClientProxy.SPELL_QUICK_ACCESS[i].isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){
+ if(!quickAccessKeyPressed[i]){
+ quickAccessKeyPressed[i] = true;
+ // Packet building
+ selectSpell(wand, i);
+ }
+ }else{
+ quickAccessKeyPressed[i] = false;
+ }
+ }
+
}
}
}
@@ -118,4 +133,17 @@ public class WizardryControlHandler {
GuiSpellDisplay.playSpellSwitchAnimation(false);
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.ITEM_WAND_SWITCH_SPELL, 1));
}
+
+ private static void selectSpell(ItemStack wand, int index){
+ // GUI switch animation
+ if(((ISpellCastingItem)wand.getItem()).selectSpell(wand, index)){ // Makes sure the spell is set immediately for the client
+ // Packet building (no point sending it unless the client-side spell selection succeeded
+ IMessage msg = new PacketSpellQuickAccess.Message(index);
+ WizardryPacketHandler.net.sendToServer(msg);
+
+ GuiSpellDisplay.playSpellSwitchAnimation(true); // This will do, it's only an animation
+ Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.ITEM_WAND_SWITCH_SPELL, 1));
+ }
+ }
+
}
diff --git a/src/main/java/electroblob/wizardry/item/ISpellCastingItem.java b/src/main/java/electroblob/wizardry/item/ISpellCastingItem.java
index 0d532200..2666a5bb 100644
--- a/src/main/java/electroblob/wizardry/item/ISpellCastingItem.java
+++ b/src/main/java/electroblob/wizardry/item/ISpellCastingItem.java
@@ -65,6 +65,16 @@ public interface ISpellCastingItem {
// Nothing here either
}
+ /**
+ * Selects the spell at the given index bound to the given itemstack. The given itemstack will be of this item.
+ * @param stack The itemstack to query.
+ * @param index The index to set.
+ * @return True if the operation succeeded, false if not.
+ */
+ default boolean selectSpell(ItemStack stack, int index){
+ return false;
+ }
+
/**
* Returns whether the spell HUD should be shown when a player is holding this item. Only called client-side.
* @param player The player holding the item.
diff --git a/src/main/java/electroblob/wizardry/item/ItemWand.java b/src/main/java/electroblob/wizardry/item/ItemWand.java
index 8272098a..8c80cb75 100644
--- a/src/main/java/electroblob/wizardry/item/ItemWand.java
+++ b/src/main/java/electroblob/wizardry/item/ItemWand.java
@@ -113,6 +113,11 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
WandHelper.selectPreviousSpell(stack);
}
+ @Override
+ public boolean selectSpell(ItemStack stack, int index){
+ return WandHelper.selectSpell(stack, index);
+ }
+
@Override
public boolean showSpellHUD(EntityPlayer player, ItemStack stack){
return true;
diff --git a/src/main/java/electroblob/wizardry/packet/PacketSpellQuickAccess.java b/src/main/java/electroblob/wizardry/packet/PacketSpellQuickAccess.java
new file mode 100644
index 00000000..4828216b
--- /dev/null
+++ b/src/main/java/electroblob/wizardry/packet/PacketSpellQuickAccess.java
@@ -0,0 +1,66 @@
+package electroblob.wizardry.packet;
+
+import electroblob.wizardry.item.ISpellCastingItem;
+import io.netty.buffer.ByteBuf;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
+import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
+
+/** [Client -> Server] This packet is for the spell quick access keys. */
+public class PacketSpellQuickAccess implements IMessageHandler {
+
+ @Override
+ public IMessage onMessage(Message message, MessageContext ctx){
+
+ // Just to make sure that the side is correct
+ if(ctx.side.isServer()){
+
+ final EntityPlayerMP player = ctx.getServerHandler().player;
+
+ player.getServerWorld().addScheduledTask(() -> {
+
+ ItemStack wand = player.getHeldItemMainhand();
+
+ if(!(wand.getItem() instanceof ISpellCastingItem)){
+ wand = player.getHeldItemOffhand();
+ }
+
+ if(wand.getItem() instanceof ISpellCastingItem){
+
+ ((ISpellCastingItem)wand.getItem()).selectSpell(wand, message.index);
+ // This line fixes the bug with continuous spells casting when they shouldn't be
+ player.stopActiveHand();
+ }
+
+ });
+ }
+
+ return null;
+ }
+
+ public static class Message implements IMessage {
+
+ private int index;
+
+ // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection)
+ public Message(){
+ }
+
+ public Message(int index){
+ this.index = index;
+ }
+
+ @Override
+ public void fromBytes(ByteBuf buf){
+ // The order is important
+ this.index = buf.readInt();
+ }
+
+ @Override
+ public void toBytes(ByteBuf buf){
+ buf.writeInt(index);
+ }
+ }
+}
diff --git a/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java b/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java
index 8feabd56..7d7133c2 100644
--- a/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java
+++ b/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java
@@ -13,25 +13,26 @@ public class WizardryPacketHandler {
public static void initPackets(){
net = NetworkRegistry.INSTANCE.newSimpleChannel(Wizardry.MODID.toUpperCase());
- registerMessage(PacketControlInput.class, PacketControlInput.Message.class);
- registerMessage(PacketCastSpell.class, PacketCastSpell.Message.class);
- registerMessage(PacketTransportation.class, PacketTransportation.Message.class);
- registerMessage(PacketPlayerSync.class, PacketPlayerSync.Message.class);
- registerMessage(PacketGlyphData.class, PacketGlyphData.Message.class);
- registerMessage(PacketCastContinuousSpell.class, PacketCastContinuousSpell.Message.class);
- registerMessage(PacketClairvoyance.class, PacketClairvoyance.Message.class);
- registerMessage(PacketSyncSettings.class, PacketSyncSettings.Message.class);
- registerMessage(PacketNPCCastSpell.class, PacketNPCCastSpell.Message.class);
- registerMessage(PacketDispenserCastSpell.class, PacketDispenserCastSpell.Message.class);
- registerMessage(PacketSpellProperties.class, PacketSpellProperties.Message.class);
- registerMessage(PacketSyncAdvancements.class, PacketSyncAdvancements.Message.class);
+ registerMessage(PacketControlInput.class, PacketControlInput.Message.class);
+ registerMessage(PacketCastSpell.class, PacketCastSpell.Message.class);
+ registerMessage(PacketTransportation.class, PacketTransportation.Message.class);
+ registerMessage(PacketPlayerSync.class, PacketPlayerSync.Message.class);
+ registerMessage(PacketGlyphData.class, PacketGlyphData.Message.class);
+ registerMessage(PacketCastContinuousSpell.class, PacketCastContinuousSpell.Message.class);
+ registerMessage(PacketClairvoyance.class, PacketClairvoyance.Message.class);
+ registerMessage(PacketSyncSettings.class, PacketSyncSettings.Message.class);
+ registerMessage(PacketNPCCastSpell.class, PacketNPCCastSpell.Message.class);
+ registerMessage(PacketDispenserCastSpell.class, PacketDispenserCastSpell.Message.class);
+ registerMessage(PacketSpellProperties.class, PacketSpellProperties.Message.class);
+ registerMessage(PacketSyncAdvancements.class, PacketSyncAdvancements.Message.class);
registerMessage(PacketRequestAdvancementSync.class, PacketRequestAdvancementSync.Message.class);
- registerMessage(PacketResurrection.class, PacketResurrection.Message.class);
- registerMessage(PacketCastSpellAtPos.class, PacketCastSpellAtPos.Message.class);
- registerMessage(PacketEmitterData.class, PacketEmitterData.Message.class);
- registerMessage(PacketPossession.class, PacketPossession.Message.class);
- registerMessage(PacketConquerShrine.class, PacketConquerShrine.Message.class);
- registerMessage(PacketLectern.class, PacketLectern.Message.class);
+ registerMessage(PacketResurrection.class, PacketResurrection.Message.class);
+ registerMessage(PacketCastSpellAtPos.class, PacketCastSpellAtPos.Message.class);
+ registerMessage(PacketEmitterData.class, PacketEmitterData.Message.class);
+ registerMessage(PacketPossession.class, PacketPossession.Message.class);
+ registerMessage(PacketConquerShrine.class, PacketConquerShrine.Message.class);
+ registerMessage(PacketLectern.class, PacketLectern.Message.class);
+ registerMessage(PacketSpellQuickAccess.class, PacketSpellQuickAccess.Message.class);
}
private static int nextPacketId = 0;
diff --git a/src/main/java/electroblob/wizardry/util/WandHelper.java b/src/main/java/electroblob/wizardry/util/WandHelper.java
index 677761a3..ca8fde07 100644
--- a/src/main/java/electroblob/wizardry/util/WandHelper.java
+++ b/src/main/java/electroblob/wizardry/util/WandHelper.java
@@ -170,6 +170,26 @@ public final class WandHelper {
wand.getTagCompound().setInteger(SELECTED_SPELL_KEY, getPreviousSpellIndex(wand));
}
}
+
+ /**
+ * Selects the spell at the given index in this wand's list of spells.
+ * @param wand The stack to set the spell of
+ * @param index The spell index to set the wand to
+ * @return False if the index was out-of-bounds, true otherwise
+ */
+ public static boolean selectSpell(ItemStack wand, int index){
+
+ if(index < 0 || index > getSpells(wand).length) return false; // Out-of-bounds
+
+ // 5 here because if the spell array doesn't exist, the wand can't possibly have attunement upgrades
+ if(getSpells(wand).length < 0) setSpells(wand, new Spell[ItemWand.BASE_SPELL_SLOTS]);
+
+ if(wand.getTagCompound() != null){
+ wand.getTagCompound().setInteger(SELECTED_SPELL_KEY, index);
+ }
+
+ return true;
+ }
private static int getNextSpellIndex(ItemStack wand){
diff --git a/src/main/resources/assets/ebwizardry/lang/en_gb.lang b/src/main/resources/assets/ebwizardry/lang/en_gb.lang
index 70f25949..ffc3116e 100644
--- a/src/main/resources/assets/ebwizardry/lang/en_gb.lang
+++ b/src/main/resources/assets/ebwizardry/lang/en_gb.lang
@@ -1076,6 +1076,14 @@ key.categories.ebwizardry=Wizardry
key.ebwizardry.next_spell=Next Spell
key.ebwizardry.previous_spell=Previous Spell
+key.ebwizardry.spell_1=Spell Slot 1
+key.ebwizardry.spell_2=Spell Slot 2
+key.ebwizardry.spell_3=Spell Slot 3
+key.ebwizardry.spell_4=Spell Slot 4
+key.ebwizardry.spell_5=Spell Slot 5
+key.ebwizardry.spell_6=Spell Slot 6
+key.ebwizardry.spell_7=Spell Slot 7
+key.ebwizardry.spell_8=Spell Slot 8
death.attack.wizardry_magic=%1$s was killed by %2$s using magic
death.attack.indirect_wizardry_magic=%1$s was killed by %2$s using magic
diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang
index d7b710a0..7b5d46f9 100644
--- a/src/main/resources/assets/ebwizardry/lang/en_us.lang
+++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang
@@ -1076,6 +1076,14 @@ key.categories.ebwizardry=Wizardry
key.ebwizardry.next_spell=Next Spell
key.ebwizardry.previous_spell=Previous Spell
+key.ebwizardry.spell_1=Spell Slot 1
+key.ebwizardry.spell_2=Spell Slot 2
+key.ebwizardry.spell_3=Spell Slot 3
+key.ebwizardry.spell_4=Spell Slot 4
+key.ebwizardry.spell_5=Spell Slot 5
+key.ebwizardry.spell_6=Spell Slot 6
+key.ebwizardry.spell_7=Spell Slot 7
+key.ebwizardry.spell_8=Spell Slot 8
death.attack.wizardry_magic=%1$s was killed by %2$s using magic
death.attack.indirect_wizardry_magic=%1$s was killed by %2$s using magic