My design followed from the premise that the definition of every action can be thought of as a triplet consisting of a subject, verb, and object. So for instance, Hand - pick up - item. So I defined three interfaces:
Action,
CanAct<type extends Action>,
CanBeActedUpon<type extends Action>.
Then what I would do would be to define a new action class, such as
Class PickUp implements Action{
PickUp(CanPickUp, CanBePickedUp){..}
}, with two interfaces CanPickUp extends CanAct<PickUp>and
CanBePickedUp extends CanBeActedUpon<PickUp>
The idea was that with this framework I could assign different components different CanAct interfaces, and then if an entity lost the component, for instance your hands are cut off, they would lose the ability to take actions, unless of course they had other components which also performed those actions. In addition, I could create menus of possible actions on the fly, since all I'd have to do was take the main entity, compile a list of all it's possible actions (for component in entity, if component instanceof CanAct, component.getType()), then look at it's surroundings for other entities with components that have CanBeActedUpon of that type. Meanwhile the action would provide it's own name, so the menu code could be completely oblivious.
The problem is that Java won't allow an object to inherit two interfaces from the same base interface. So for instance, if I add Hands, I want them to be able to PickUp, Equip, Attack, and Open. CanPickUp extends CanAct<PickUp>,CanEquip extends CanAct<Equip>. My Hands object can't implement both.
Additionally, it gets very messy for some reason. Because everything that handles these actions has to be type agnostic, I end up doing a lot of strange typecasting that I don't fully understand. For example:
public static CanAct<?> canActor(GameObject g, Class<? extends Action> actionType){
for(Part p : g.allParts){
if(p instanceof CanAct<?>){
CanAct<?> CA=(CanAct<?>)p;
if(CA.actionType()==actionType){
return CA;
}
}
}
return null;
}
Where for this code I should point out that both the CanAct and CanBeActedUpon interface have the function actionType() which returns a Class<? extends Action>, and then CanPickUp for instance would return PickUp.class . I haven't been able to figure out how to do this in a more elegant way... Not to mention having to iterate through all the parts in the Entity.
I suppose my question is, does anyone have any suggestions for me? Am I over engineering my problem? Is there an easier approach? Is there a pattern I've not tried here? Or am I on the right track, and if so, what is my work around for implementing two of the same interfaces with different types?






