Browse Source
- Added EntitySharedData which is for things like Position that almost all components need - Changed interfaces which didn't hold up to scrutiny - Fucked with Jamfiles/Jamrules to get Unreal working - Added Subject Observer, which I will likely refactor heavily, but gives an idea for what it will be likecombatComponentRefactor

25 changed files with 499 additions and 90 deletions
@ -1,2 +1,3 @@ |
|||
SubDir . ; |
|||
|
|||
SubInclude . src ; |
@ -1,15 +1,14 @@ |
|||
SubDir . src ; |
|||
|
|||
Library libGalavant : GalavantMain.cpp ; |
|||
|
|||
LinkLibraries libGalavant : libGalaThirdPartyWrapper ; |
|||
|
|||
MakeLocate libGalavant.a : lib ; |
|||
|
|||
SubInclude . src thirdPartyWrapper ; |
|||
SubInclude . src entityComponentSystem ; |
|||
SubInclude . src ai ; |
|||
SubInclude . src world ; |
|||
SubInclude . src game ; |
|||
|
|||
# Experiments and Testing (feel free to remove these if you don't want them built) |
|||
SubInclude . src experiments ; |
|||
|
@ -1,5 +1,7 @@ |
|||
SubDir . src ai ; |
|||
|
|||
Library libGalaAi : htn/HTNTasks.cpp htn/HTNPlanner.cpp ; |
|||
Library libGalaAi : htn/HTNTasks.cpp htn/HTNPlanner.cpp WorldState.cpp ; |
|||
|
|||
LinkLibraries LibGalaAi : LibGalaWorld ; |
|||
|
|||
MakeLocate libGalaAi.a : lib ; |
@ -0,0 +1,26 @@ |
|||
#include "WorldState.hpp" |
|||
|
|||
#include "../entityComponentSystem/EntitySharedData.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
WorldState WorldStateManager::GetWorldStateForAgent(Entity agent) |
|||
{ |
|||
EntityWorldStateMap::iterator findEnt = EntityWorldStates.find(agent); |
|||
|
|||
if (findEnt == EntityWorldStates.end()) |
|||
{ |
|||
WorldState worldState; |
|||
worldState.SourceAgent.SourceEntity = agent; |
|||
EntityWorldStates[agent] = worldState; |
|||
findEnt = EntityWorldStates.find(agent); |
|||
} |
|||
|
|||
WorldState& worldState = findEnt->second; |
|||
|
|||
// Positions are likely enough to change that we'll just always update it
|
|||
worldState.SourceAgent.position = (*EntityGetPosition(agent)); |
|||
|
|||
return worldState; |
|||
} |
|||
} |
@ -1,26 +1,43 @@ |
|||
#pragma once |
|||
|
|||
#include <map> |
|||
|
|||
#include "../world/Position.hpp" |
|||
#include "../entityComponentSystem/EntityTypes.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
struct AgentState |
|||
{ |
|||
Entity SourceEntity; |
|||
Position position; |
|||
Position TargetPosition; |
|||
}; |
|||
|
|||
/* --WorldState--
|
|||
WorldState represents a mutable, copyable reference to all AI-relevant data in the World. |
|||
Mutable: The data can be manipulated freely without repurcussion. Note that changing data in |
|||
WorldState is NOT expected to actually change the world - WorldState is like a mirror world |
|||
Copyable: The data can be copied without a significant amount of time. This means that in order |
|||
to support mutability, things like changelists might need to be implemented for large datasets |
|||
instead of actually copying the dataset |
|||
Copyable: The data can be copied without a significant performance impact. This means that in |
|||
order to support mutability, things like changelists might need to be implemented for large |
|||
datasets instead of actually copying the dataset |
|||
*/ |
|||
struct WorldState |
|||
{ |
|||
// Because an agent is almost always going to...well, maybe this shouldn't be here. For now it
|
|||
// will stay.
|
|||
AgentState SourceAgent; |
|||
|
|||
// This will be removed eventually
|
|||
int TestStateChange; |
|||
}; |
|||
|
|||
class WorldStateManager |
|||
{ |
|||
private: |
|||
typedef std::map<Entity, WorldState> EntityWorldStateMap; |
|||
EntityWorldStateMap EntityWorldStates; |
|||
public: |
|||
WorldState GetWorldStateForAgent(Entity agent); |
|||
}; |
|||
}; |
@ -0,0 +1,123 @@ |
|||
#include "EntitySharedData.hpp" |
|||
|
|||
#include <map> |
|||
#include <cassert> |
|||
|
|||
namespace gv |
|||
{ |
|||
typedef std::map<Entity, Position> EntityPositionMap; |
|||
typedef std::map<Entity, Position*> EntityPositionRefMap; |
|||
|
|||
struct EntitySharedData |
|||
{ |
|||
// Entity positions with no current owner
|
|||
EntityPositionMap UnownedEntityPositions; |
|||
|
|||
// Entity positions owned by an external module
|
|||
EntityPositionRefMap EntityPositionRefs; |
|||
}; |
|||
|
|||
static EntitySharedData s_Data; |
|||
|
|||
void EntityCreatePositions(const EntityList& entities, PositionRefList& positions) |
|||
{ |
|||
// Should have same number of positions to entities
|
|||
assert(entities.size() == positions.size()); |
|||
|
|||
for (unsigned int i = 0; i < entities.size(); i++) |
|||
{ |
|||
Entity currentEntity = entities[i]; |
|||
|
|||
// Ensure we aren't creating positions which have already been created
|
|||
{ |
|||
EntityPositionRefMap::iterator findPositionRef = |
|||
s_Data.EntityPositionRefs.find(currentEntity); |
|||
assert(findPositionRef == s_Data.EntityPositionRefs.end()); |
|||
} |
|||
|
|||
// Destroy the unowned position for the entity, if it exists
|
|||
{ |
|||
EntityPositionMap::iterator findPosition = s_Data.UnownedEntityPositions.find(currentEntity); |
|||
if (findPosition != s_Data.UnownedEntityPositions.end()) |
|||
s_Data.UnownedEntityPositions.erase(findPosition); |
|||
} |
|||
|
|||
s_Data.EntityPositionRefs[currentEntity] = positions[i]; |
|||
} |
|||
} |
|||
|
|||
void EntityDestroyPositions(const EntityList& entities) |
|||
{ |
|||
// TODO: This is bad :(
|
|||
for (EntityPositionRefMap::iterator it = s_Data.EntityPositionRefs.begin(); |
|||
it != s_Data.EntityPositionRefs.end();) |
|||
{ |
|||
bool foundEntity = false; |
|||
for (Entity currentEntity : entities) |
|||
{ |
|||
if (it->first == currentEntity) |
|||
{ |
|||
it = s_Data.EntityPositionRefs.erase(it); |
|||
foundEntity = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!foundEntity) |
|||
++it; |
|||
} |
|||
} |
|||
|
|||
void EntitySetPositions(const EntityList& entities, const PositionList& positions) |
|||
{ |
|||
// Should have same number of positions to entities
|
|||
assert(entities.size() == positions.size()); |
|||
|
|||
for (unsigned int i = 0; i < entities.size(); i++) |
|||
{ |
|||
Entity currentEntity = entities[i]; |
|||
Position currentPosition = positions[i]; |
|||
EntitySetPosition(currentEntity, currentPosition); |
|||
} |
|||
} |
|||
|
|||
// This sets the value of the position, not the reference (use EntityCreatePosition for that)
|
|||
void EntitySetPosition(const Entity& entity, const Position& position) |
|||
{ |
|||
EntityPositionRefMap::iterator findRef = s_Data.EntityPositionRefs.find(entity); |
|||
if (findRef != s_Data.EntityPositionRefs.end()) |
|||
(*findRef->second) = position; |
|||
else |
|||
s_Data.UnownedEntityPositions[entity] = position; |
|||
} |
|||
|
|||
void EntityGetPositions(const EntityList& entities, PositionRefList& positionsOut) |
|||
{ |
|||
for (unsigned int i = 0; i < entities.size(); i++) |
|||
{ |
|||
Entity currentEntity = entities[i]; |
|||
positionsOut[i] = EntityGetPosition(currentEntity); |
|||
} |
|||
} |
|||
|
|||
// If an entity doesn't have a position, it will be created at 0, 0, 0
|
|||
Position* EntityGetPosition(const Entity& entity) |
|||
{ |
|||
// Check if we have a reference to the entity's position (another module owns it)
|
|||
EntityPositionRefMap::iterator findRef = s_Data.EntityPositionRefs.find(entity); |
|||
if (findRef != s_Data.EntityPositionRefs.end()) |
|||
return findRef->second; |
|||
|
|||
// Check if we own the position
|
|||
EntityPositionMap::iterator findUnowned = s_Data.UnownedEntityPositions.find(entity); |
|||
if (findUnowned == s_Data.UnownedEntityPositions.end()) |
|||
{ |
|||
// We don't own the position; create it
|
|||
Position zeroPosition; |
|||
s_Data.UnownedEntityPositions[entity] = zeroPosition; |
|||
findUnowned = s_Data.UnownedEntityPositions.find(entity); |
|||
} |
|||
|
|||
return &findUnowned->second; |
|||
} |
|||
} |
@ -0,0 +1,23 @@ |
|||
#pragma once |
|||
|
|||
#include "EntityTypes.hpp" |
|||
#include "../world/Position.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
// TODO: Make it such that things can own the position and this module is used for lookup externally
|
|||
// only. If nothing owns the position this module will anonymously own it until someone steps up
|
|||
// This is so I can follow the principle that "That which changes the data, owns the data". It also
|
|||
// seems fucking awful to do a map lookup every time anyone wants to read or write a position
|
|||
|
|||
// TODO: Make it clear that we expect the given positions to hang around
|
|||
void EntityCreatePositions(const EntityList& entities, PositionRefList& positions); |
|||
void EntityDestroyPositions(const EntityList& entities); |
|||
|
|||
void EntitySetPositions(const EntityList& entities, const PositionList& positions); |
|||
void EntitySetPosition(const Entity& entity, const Position& position); |
|||
|
|||
void EntityGetPositions(const EntityList& entities, PositionRefList& positionsOut); |
|||
// If an entity doesn't have a position, it will be created at 0, 0, 0
|
|||
Position* EntityGetPosition(const Entity& entity); |
|||
}; |
@ -1,5 +1,6 @@ |
|||
SubDir . src entityComponentSystem ; |
|||
|
|||
Library libGalaEntityComponent : EntityTypes.cpp EntityComponentManager.cpp ComponentManager.cpp ; |
|||
Library libGalaEntityComponent : EntityTypes.cpp EntitySharedData.cpp EntityComponentManager.cpp ComponentManager.cpp ; |
|||
LinkLibraries libGalaEntityComponent : libGalaWorld ; |
|||
|
|||
MakeLocate libGalaEntityComponent.a : lib ; |
@ -0,0 +1,47 @@ |
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
|
|||
#include "entityComponentSystem/EntityTypes.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
template <class T> |
|||
class Observer |
|||
{ |
|||
public: |
|||
Observer() = default; |
|||
virtual ~Observer() = default; |
|||
|
|||
virtual void OnNotify(const T& event) = 0; |
|||
}; |
|||
|
|||
template <class T> |
|||
class Subject |
|||
{ |
|||
private: |
|||
std::vector<Observer<T>*> Observers; |
|||
|
|||
public: |
|||
Subject() = default; |
|||
~Subject() = default; |
|||
|
|||
void AddObserver(Observer<T>* observer) |
|||
{ |
|||
if (observer && std::find(Observers.begin(), Observers.end(), observer) == Observers.end()) |
|||
Observers.push_back(observer); |
|||
} |
|||
void RemoveObserver(Observer<T>* observer) |
|||
{ |
|||
typename std::vector<Observer<T>*>::iterator foundObserver = |
|||
std::find(Observers.begin(), Observers.end(), observer); |
|||
if (foundObserver != Observers.end()) |
|||
Observers.remove(foundObserver); |
|||
} |
|||
void Notify(const T& event) |
|||
{ |
|||
for (Observer<T>* currentObserver : Observers) |
|||
currentObserver->OnNotify(event); |
|||
} |
|||
}; |
|||
}; |
Loading…
Reference in new issue