Add spell quick access keys

This commit is contained in:
Electroblob77
2020-04-18 21:45:01 +01:00
parent ed63704184
commit f0752317e6
9 changed files with 175 additions and 18 deletions
@@ -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
@@ -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));
}
}
}
@@ -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.
@@ -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;
@@ -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;
/** <b>[Client -> Server]</b> This packet is for the spell quick access keys. */
public class PacketSpellQuickAccess implements IMessageHandler<PacketSpellQuickAccess.Message, IMessage> {
@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);
}
}
}
@@ -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;
@@ -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){