Components and systems know nothing about each other.
I can understand components not knowing about systems, but I don't see why you would have systems not know about components. It is the whole point of systems to handle the processing of components relevant to those systems. Some people might argue that making things event driven in this way is better, but I'm not a big fan of event systems used in this way.
In my opinion systems will 'update' the components they are responsible for updating directly, though if you prefer your update event can accomplish the same thing. An InputSystem will update all the known InputComponents. That might include PlayerInput components(possible multiple for local multiplayer), and AIInput if you implement your AI to function through the same control interface. Each instance of PlayerInput will know about what keys/controllers are relevant to that particular player and interpret it accordingly.
There isn't really a single correct way to implement all you describe. There are a bunch of different approaches that may have pros and cons. I'll try to explain an alternative component implementation that I feel makes more sense.
Your motion appears to be implemented in full tile increments, but even in that situation I would design the component system with an implementation that is more appropriate to being used if you were using incremental motion, with a real collision system. The tile increment motion can be hidden away inside the implementation details.
For example.
PhysicsSystem - knows about and updates PhysicsComponents, resolves all physics based on velocities/forces applied to the PhysicsComponents
PhysicsSystemTile - specific implementation for your full tile locomotion, moves each object the most appropriate direction to their velocity a full tile size
PhysicsComponent - simply holds the velocity/force accumulations to be applied by the physics system and resolved with others.
PlayerInput - interprets control input and sets velocity
The benefit is of course that not only are you future proofing for the flexibility of doing a proper say box2d physics version of the game, but you are reducing the component cross chatter.
If one types 'w', the input fires event "moveUp"; the fired event is sent to a the entity with the PlayerComponent
This event is unnecessary. The specifics of which keys to interpret as which actions should be properties of the specific Input component instance. Again this reduces component chatter and leaves the game open to multiple player instances each deriving input from separate sources, ie local multiplayer.
The entity passes the "moveUp" event to all the components.
Again this is unnecessary chatter. Event broadcasting IMO is a dirty temptation of event systems. If the component knows which buttons map to which actions, it can speak to the relevant components directly.
TilePositionComponent receives it, and sends an event "updatePosition(currentX, currentY, currentX, currentY-1)" to TileLevelSystem.
TileLevelSystem sends event "isPassable" to an entity in the new position (if there is one); if the event returns true, the player moves to the new position and the "updatePosition" event returns true. Then the TilePositionComponent's currentX and currentY gets updated.
Then everything gets rendered.
These details are highly specific to your specific motion model, and would need to be wholly replaced with the introduction of a physics system. It may even be problematic to implement simple animation/lerping the entities to the center of each tile.
If instead we adopted the PhysicsSystem approach, The PlayerInput would interpret the input keys into a velocity, The PhysicsSystemTile would take that velocity and for example use the most significant direction to animate/lerp the PhysicsComponent it processes to the next valid tile in that direction. For managing crossable and uncrossable tiles, do that the same as you would if you were using a physics system. Collision masks. The PhysicsSystemTile is now the only place that has to know or care about the fact that your game operates at the tile level in terms of locomotion, and if you want to change that system in the future it becomes very simple. The most important short term win though is the reduction in component cross talk and the dependencies that introduces. The relationship between Input, Physics, and motion I think is one of the easiest aspects of a component system to keep pretty separated. Certain input ultimately gets mapped to velocity. Other input gets mapped to actions, probably on the PlayerComponent or possibly a more general CharacterComponent if you want the AI to function through the same interface. Many games, and all bots for FPS games operate like this. The AI ultimately feeds 'button presses' that maps to specific action into the game so the AI can operate through much the same code path as players. The analog in a component system might be that the AIComponent ultimately sets 'action' flags on the CharacterComponent, the same as a PlayerComponent.
character->SetAction( true, FL_ATTACK );
For item picking, I would probably again utilize some knowledge about how it would likely be implemented in a game with a physics sytem. Pickupable items would probably have PhysicsComponents that utilize a non collidable pickup trigger mask. This would make it the responsibility of the PhysicsSystem when it is updating entities based on their motion, to maintain a list of items the character entity is 'touching'. In a fleshed out game, the knowledge that a player is touching a pickable item might be reflected in rendering button prompts on the GUI. The PlayerComponent would probably have some specific knowledge about what to do/present whenever his physics component is touching pickable items.
Maybe something like this
PlayerComponent::Update()
{
PhysicsComponent * physics = GetEntity()->GetPhysics();
Entity * pickable = GetFirstPickable( physics->GetTouchedEntities() ); // local function that gets the first pickable in the list(may be multiple), distinguished by collision mask or presence of certain dependent component
if ( pickable )
{
EnablePickupGui( pickable ); // shows a gui for the current pickable
if ( GetInput( IN_PICKUP ) )
{
DisablePickupGui();
PickupItem( pickable );
}
}
else
DisablePickupGui();
}