Skip to content

Commit

Permalink
Create Key Binding API
Browse files Browse the repository at this point in the history
* Added annotation to the API that allows certain items to bypass KeyConflictContext activity checks, fixed an ItemStack null check, replaced a class check with a method call, and clarified a description.

* Added method to the API the returns C&B key bindings.

* 1) Added optional argument to the KeyBindingContext annotation that allows classes that use it to be added to ModConflictContext's active class collection; 2) Added an IMC that searches the class hierarchies of all classes of all of the sender's registered items for instances of the annotation that have this argument; 3) Refactored the active class collection to a hashset to avoid duplication.

* Optimized IMC annotation search.

* Remove nested type enum from ModKeyBinding and replaced the switch on its type with a switch on all its values not in ClientSide.
  • Loading branch information
Phylogeny authored and AlgorithmX2 committed Jan 5, 2017
1 parent 61df578 commit 718a8ff
Show file tree
Hide file tree
Showing 11 changed files with 447 additions and 5 deletions.
15 changes: 15 additions & 0 deletions src/main/java/mod/chiselsandbits/api/IChiselAndBitsAPI.java
Expand Up @@ -6,12 +6,15 @@
import mod.chiselsandbits.api.APIExceptions.InvalidBitItem;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandler;

/**
Expand Down Expand Up @@ -199,4 +202,16 @@ void addEquivilantMaterial(
Material target ); // this should be a material C&B understands,
// other wise you'll get stone anyway.

/**
* Get a C&B key binding.
*
* @param modKeyBinding
* the {@link ModKeyBinding} value that denotes the C&B key
* binding to return.
* @return a C&B {@link KeyBinding}.
*/
@SideOnly( Side.CLIENT )
KeyBinding getKeyBinding(
ModKeyBinding modKeyBinding );

}
2 changes: 1 addition & 1 deletion src/main/java/mod/chiselsandbits/api/IgnoreBlockLogic.java
Expand Up @@ -16,7 +16,7 @@
* Put this on the block, or use the IMC,
*
* FMLInterModComms.sendMessage( "chiselsandbits", "ignoreblocklogic",
* "myBlockName" );
* [myBlockName] );
*
* If you wish to make a single state compatible, or incompatible you must use
* "forcestatecompatibility" instead, if your entire block is intended to be
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/mod/chiselsandbits/api/KeyBindingContext.java
@@ -0,0 +1,81 @@
package mod.chiselsandbits.api;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* The key bindings for the following operations are only active when holding C&B items:
*
* - "chisel" - Setting the chisel mode
* - "postivepattern" - Setting the positive pattern mode
* - "tapemeasure" - Setting the tape measure mode
* - "rotateable" - Rotating blocks
* - "menuitem" - Opening the radial menu
*
* If you put this annotation on a class that extends Item, you can allow C&B to bypass
* the normal activity checks when holding an item that is an instance of that class. If
* you include and set true the optional applyToSubClasses argument in the annotation or
* use an IMC, this will apply not only to any item that is of that class, but also to
* any class that extends that class.
*
*
* If use any annotation with applyToSubClasses set to true, you need to send the
* following IMC (of any type - String type is used below) after you register your items
* to find/register/initialize those classes:
*
* FMLInterModComms.sendMessage( "chiselsandbits", "initkeybindingannotations", "" );
*
* Doing so will not only find and initialize classes of registered items, but also any
* base classes that registered items may extend, but are never directly instantiated.
*
*
*
* ~Example 1~
* Putting the following annotation on an item class will allow the key bindings for
* chisel modes to be active when holding an item of that class:
*
* @KeyBindingContext( chisel )
*
* The following two IMCs would do the same for item(s) of that class or of any subclass:
*
* FMLInterModComms.sendMessage( "chiselsandbits", "chisel", [myItemName] );
*
*
*
* ~Example 2~
* The following IMC and IMC/annotation set will both allow the key binding for chisel
* modes to be active when holding an item of that class or of any subclass:
*
* @KeyBindingContext( value = { "chisel", "menuitem" }, applyToSubClasses = true )
* AND
* FMLInterModComms.sendMessage( "chiselsandbits", "initkeybindingannotations", "" );
*
* OR
*
* FMLInterModComms.sendMessage( "chiselsandbits", "chisel", [myItemName] );
* FMLInterModComms.sendMessage( "chiselsandbits", "menuitem", [myItemName] );
*
*
*/
@Retention( RetentionPolicy.RUNTIME )
public @interface KeyBindingContext
{
/**
* A list of contexts that will allow all key bindings that use them to be active
* when holding an item of a class (or a subclass, if applyToSubClasses is true)
* with this annotation.
*
* @return a list of key bindings contexts
*/
String[] value ();

/**
* If true, the key binding context activity check will be bypassed not only for items
* of a class with this annotation, but also to items of any class that extends it.
*
* This argument is optional.
*
* @return whether or not this annotation applies to subclasses
*/
boolean applyToSubClasses() default false;
}
43 changes: 43 additions & 0 deletions src/main/java/mod/chiselsandbits/api/ModKeyBinding.java
@@ -0,0 +1,43 @@
package mod.chiselsandbits.api;

import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly( Side.CLIENT )
public enum ModKeyBinding
{
//Misc
ROTATE_CCW,
ROTATE_CW,
UNDO,
REDO,
MODE_MENU,
ADD_TO_CLIPBOARD,
PICK_BIT,

//Chisel Modes
SINGLE,
SNAP2,
SNAP4,
SNAP8,
LINE,
PLANE,
CONNECTED_PLANE,
CUBE_SMALL,
CUBE_MEDIUM,
CUBE_LARGE,
SAME_MATERIAL,
DRAWN_REGION,
CONNECTED_MATERIAL,

//Positive Pattern Modes
REPLACE,
ADDITIVE,
PLACEMENT,
IMPOSE,

//Tape Measure Modes
BIT,
BLOCK,
DISTANCE;
}
78 changes: 75 additions & 3 deletions src/main/java/mod/chiselsandbits/client/ModConflictContext.java
@@ -1,8 +1,15 @@
package mod.chiselsandbits.client;

import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;

import mod.chiselsandbits.api.KeyBindingContext;
import mod.chiselsandbits.core.ClientSide;
import mod.chiselsandbits.helpers.ChiselToolType;
import mod.chiselsandbits.helpers.ModUtil;
import mod.chiselsandbits.interfaces.IVoxelBlobItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraftforge.client.settings.IKeyConflictContext;
Expand All @@ -16,8 +23,13 @@ public enum ModConflictContext implements IKeyConflictContext
@Override
public boolean isActive()
{
if ( super.isActive() )
{
return true;
}

final ItemStack held = ClientSide.instance.getPlayer().getHeldItemMainhand();
return held != null && held.getItem() instanceof IVoxelBlobItem;
return !ModUtil.isEmpty( held ) && held.getItem() instanceof IVoxelBlobItem;
}

@Override
Expand All @@ -33,6 +45,11 @@ public boolean conflicts(
@Override
public boolean isActive()
{
if ( super.isActive() )
{
return true;
}

final ChiselToolType tool = ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND );
return tool != null && tool.hasMenu();
}
Expand All @@ -49,7 +66,7 @@ public boolean conflicts(
@Override
public boolean isActive()
{
return ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND ) == ChiselToolType.TAPEMEASURE;
return super.isActive() || ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND ) == ChiselToolType.TAPEMEASURE;
}

@Override
Expand All @@ -65,7 +82,7 @@ public boolean conflicts(
@Override
public boolean isActive()
{
return ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND ) == ChiselToolType.POSITIVEPATTERN;
return super.isActive() || ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND ) == ChiselToolType.POSITIVEPATTERN;
}

@Override
Expand All @@ -81,6 +98,11 @@ public boolean conflicts(
@Override
public boolean isActive()
{
if ( super.isActive() )
{
return true;
}

final ChiselToolType tool = ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND );
return tool != null && tool.isBitOrChisel();
}
Expand All @@ -93,4 +115,54 @@ public boolean conflicts(
}
};

private Set<Class<? extends Item>> activeItemClasses = new HashSet<Class<? extends Item>>();

public void setItemActive(
final Item item )
{
activeItemClasses.add( item.getClass() );
}

@Override
public boolean isActive()
{
final ItemStack held = ClientSide.instance.getPlayer().getHeldItemMainhand();

if ( ModUtil.isEmpty( held ) )
{
return false;
}

for ( Class<? extends Item> itemClass : activeItemClasses )
{
if ( itemClass.isInstance( held.getItem() ) )
{
return true;
}
}

if ( held.getItem().getClass().isAnnotationPresent( KeyBindingContext.class ) )
{
final Annotation annotation = held.getItem().getClass().getAnnotation( KeyBindingContext.class );

if ( annotation instanceof KeyBindingContext )
{
for ( String name : ( (KeyBindingContext) annotation ).value() )
{
if ( name.equals( getName() ) )
{
return true;
}
}
}
}

return false;
}

public String getName()
{
return toString().toLowerCase().replace( "holding_", "" );
}

}
23 changes: 23 additions & 0 deletions src/main/java/mod/chiselsandbits/core/ClientSide.java
Expand Up @@ -18,6 +18,7 @@
import mod.chiselsandbits.api.IBitAccess;
import mod.chiselsandbits.api.IBitBrush;
import mod.chiselsandbits.api.ItemType;
import mod.chiselsandbits.api.ModKeyBinding;
import mod.chiselsandbits.bittank.BlockBitTank;
import mod.chiselsandbits.bittank.TileEntityBitTank;
import mod.chiselsandbits.bittank.TileEntitySpecialRenderBitTank;
Expand Down Expand Up @@ -141,6 +142,28 @@ public class ClientSide

final public TapeMeasures tapeMeasures = new TapeMeasures();

public KeyBinding getKeyBinding(
ModKeyBinding modKeyBinding )
{
switch ( modKeyBinding )
{
case ROTATE_CCW:
return rotateCCW;
case ROTATE_CW:
return rotateCW;
case UNDO:
return undo;
case REDO:
return redo;
case ADD_TO_CLIPBOARD:
return addToClipboard;
case PICK_BIT:
return pickBit;
default:
return modeMenu;
}
}

public void preinit(
final ChiselsAndBits mod )
{
Expand Down

0 comments on commit 718a8ff

Please sign in to comment.