refactor: Extract object management from Area into ObjectContainer
Also optimize searching objects by tag and id.
This commit is contained in:
parent
06c9ec0513
commit
f26ed703fc
10 changed files with 160 additions and 116 deletions
|
@ -79,6 +79,7 @@ set(HEADERS
|
|||
src/game/object/spatial.h
|
||||
src/game/object/trigger.h
|
||||
src/game/object/waypoint.h
|
||||
src/game/objectcontainer.h
|
||||
src/game/room.h
|
||||
src/game/script/callbacks.h
|
||||
src/game/script/routines.h
|
||||
|
@ -197,6 +198,7 @@ set(SOURCES
|
|||
src/game/object/spatial.cpp
|
||||
src/game/object/trigger.cpp
|
||||
src/game/object/waypoint.cpp
|
||||
src/game/objectcontainer.cpp
|
||||
src/game/room.cpp
|
||||
src/game/script/routines.cpp
|
||||
src/game/script/routines_common.cpp
|
||||
|
|
|
@ -69,12 +69,6 @@ Area::Area(uint32_t id, GameVersion version, ObjectFactory *factory) :
|
|||
_navMesh(new NavMesh()) {
|
||||
|
||||
assert(_objectFactory);
|
||||
|
||||
_objects.insert(make_pair(ObjectType::Creature, ObjectList()));
|
||||
_objects.insert(make_pair(ObjectType::Door, ObjectList()));
|
||||
_objects.insert(make_pair(ObjectType::Placeable, ObjectList()));
|
||||
_objects.insert(make_pair(ObjectType::Waypoint, ObjectList()));
|
||||
_objects.insert(make_pair(ObjectType::Trigger, ObjectList()));
|
||||
}
|
||||
|
||||
void Area::load(const string &name, const GffStruct &are, const GffStruct &git) {
|
||||
|
@ -91,13 +85,13 @@ void Area::load(const string &name, const GffStruct &are, const GffStruct &git)
|
|||
creature->load(gffs);
|
||||
landObject(*creature);
|
||||
creature->setSynchronize(true);
|
||||
_objects[ObjectType::Creature].push_back(move(creature));
|
||||
add(creature);
|
||||
}
|
||||
for (auto &gffs : git.getList("Door List")) {
|
||||
shared_ptr<Door> door(_objectFactory->newDoor());
|
||||
door->load(gffs);
|
||||
door->setSynchronize(true);
|
||||
_objects[ObjectType::Door].push_back(move(door));
|
||||
add(door);
|
||||
}
|
||||
for (auto &gffs : git.getList("Placeable List")) {
|
||||
shared_ptr<Placeable> placeable(_objectFactory->newPlaceable());
|
||||
|
@ -105,17 +99,17 @@ void Area::load(const string &name, const GffStruct &are, const GffStruct &git)
|
|||
if (placeable->walkmesh()) {
|
||||
_navMesh->add(placeable->walkmesh(), placeable->transform());
|
||||
}
|
||||
_objects[ObjectType::Placeable].push_back(move(placeable));
|
||||
add(placeable);
|
||||
}
|
||||
for (auto &gffs : git.getList("WaypointList")) {
|
||||
shared_ptr<Waypoint> waypoint(_objectFactory->newWaypoint());
|
||||
waypoint->load(gffs);
|
||||
_objects[ObjectType::Waypoint].push_back(move(waypoint));
|
||||
add(waypoint);
|
||||
}
|
||||
for (auto &gffs : git.getList("TriggerList")) {
|
||||
shared_ptr<Trigger> trigger(_objectFactory->newTrigger());
|
||||
trigger->load(gffs);
|
||||
_objects[ObjectType::Trigger].push_back(move(trigger));
|
||||
add(trigger);
|
||||
}
|
||||
|
||||
TheJobExecutor.enqueue([this](const atomic_bool &cancel) {
|
||||
|
@ -126,7 +120,7 @@ void Area::load(const string &name, const GffStruct &are, const GffStruct &git)
|
|||
}
|
||||
|
||||
void Area::loadProperties(const GffStruct &gffs) {
|
||||
ResourceManager &resources = ResourceManager::instance();
|
||||
ResourceManager &resources = ResMan;
|
||||
shared_ptr<TwoDaTable> musicTable(resources.find2DA("ambientmusic"));
|
||||
|
||||
int musicIdx = gffs.getInt("MusicDay");
|
||||
|
@ -136,7 +130,7 @@ void Area::loadProperties(const GffStruct &gffs) {
|
|||
}
|
||||
|
||||
void Area::loadLayout() {
|
||||
ResourceManager &resources = ResourceManager::instance();
|
||||
ResourceManager &resources = ResMan;
|
||||
|
||||
LytFile lyt;
|
||||
lyt.load(wrap(resources.find(_name, ResourceType::AreaLayout)));
|
||||
|
@ -156,19 +150,15 @@ void Area::loadLayout() {
|
|||
}
|
||||
|
||||
void Area::loadVisibility() {
|
||||
ResourceManager &resources = ResourceManager::instance();
|
||||
|
||||
VisFile vis;
|
||||
vis.load(wrap(resources.find(_name, ResourceType::Vis)));
|
||||
vis.load(wrap(ResMan.find(_name, ResourceType::Vis)));
|
||||
|
||||
_visibility = make_unique<Visibility>(vis.visibility());
|
||||
}
|
||||
|
||||
void Area::loadCameraStyle(const GffStruct &are) {
|
||||
int styleIdx = are.getInt("CameraStyle");
|
||||
|
||||
ResourceManager &resources = ResourceManager::instance();
|
||||
shared_ptr<TwoDaTable> styleTable(resources.find2DA("camerastyle"));
|
||||
shared_ptr<TwoDaTable> styleTable(ResMan.find2DA("camerastyle"));
|
||||
|
||||
_cameraStyle.distance = styleTable->getFloat(styleIdx, "distance", 0.0f);
|
||||
_cameraStyle.pitch = styleTable->getFloat(styleIdx, "pitch", 0.0f);
|
||||
|
@ -193,9 +183,9 @@ void Area::landObject(SpatialObject &object) {
|
|||
void Area::loadParty(const PartyConfiguration &party, const glm::vec3 &position, float heading) {
|
||||
if (party.memberCount > 0) {
|
||||
shared_ptr<Creature> partyLeader(makeCharacter(party.leader, kPartyLeaderTag, position, heading));
|
||||
_objects[ObjectType::Creature].push_back(partyLeader);
|
||||
landObject(*partyLeader);
|
||||
partyLeader->setSynchronize(true);
|
||||
add(partyLeader);
|
||||
_player = partyLeader;
|
||||
_partyLeader = partyLeader;
|
||||
}
|
||||
|
@ -203,7 +193,7 @@ void Area::loadParty(const PartyConfiguration &party, const glm::vec3 &position,
|
|||
shared_ptr<Creature> partyMember(makeCharacter(party.member1, kPartyMember1Tag, position, heading));
|
||||
landObject(*partyMember);
|
||||
partyMember->setSynchronize(true);
|
||||
_objects[ObjectType::Creature].push_back(partyMember);
|
||||
add(partyMember);
|
||||
_partyMember1 = partyMember;
|
||||
|
||||
Creature::Action action(Creature::ActionType::Follow, _partyLeader, kPartyMemberFollowDistance);
|
||||
|
@ -213,7 +203,7 @@ void Area::loadParty(const PartyConfiguration &party, const glm::vec3 &position,
|
|||
shared_ptr<Creature> partyMember(makeCharacter(party.member2, kPartyMember2Tag, position, heading));
|
||||
landObject(*partyMember);
|
||||
partyMember->setSynchronize(true);
|
||||
_objects[ObjectType::Creature].push_back(partyMember);
|
||||
add(partyMember);
|
||||
_partyMember2 = partyMember;
|
||||
|
||||
Creature::Action action(Creature::ActionType::Follow, _partyLeader, kPartyMemberFollowDistance);
|
||||
|
@ -238,7 +228,7 @@ bool Area::handle(const SDL_Event &event) {
|
|||
void Area::update(const UpdateContext &updateCtx, GuiContext &guiCtx) {
|
||||
updateDelayedCommands();
|
||||
|
||||
for (auto &creature : _objects[ObjectType::Creature]) {
|
||||
for (auto &creature : _objectsByType[ObjectType::Creature]) {
|
||||
updateCreature(static_cast<Creature &>(*creature), updateCtx.deltaTime);
|
||||
}
|
||||
if (_partyLeader) {
|
||||
|
@ -256,29 +246,25 @@ void Area::update(const UpdateContext &updateCtx, GuiContext &guiCtx) {
|
|||
model->update(updateCtx.deltaTime);
|
||||
}
|
||||
}
|
||||
for (auto &list : _objects) {
|
||||
for (auto &object : list.second) {
|
||||
object->update(updateCtx);
|
||||
}
|
||||
for (auto &object : _objects) {
|
||||
object->update(updateCtx);
|
||||
}
|
||||
updateSceneGraph(updateCtx.cameraPosition);
|
||||
|
||||
if (_debugMode != DebugMode::None) {
|
||||
if (_debugMode == DebugMode::GameObjects) {
|
||||
guiCtx.debug.objects.clear();
|
||||
glm::vec4 viewport(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
|
||||
for (auto &list : _objects) {
|
||||
for (auto &object : list.second) {
|
||||
glm::vec3 position(object->position());
|
||||
if (glm::distance2(position, updateCtx.cameraPosition) > kDrawDebugDistance) continue;
|
||||
for (auto &object : _objects) {
|
||||
glm::vec3 position(object->position());
|
||||
if (glm::distance2(position, updateCtx.cameraPosition) > kDrawDebugDistance) continue;
|
||||
|
||||
DebugObject debugObj;
|
||||
debugObj.tag = object->tag();
|
||||
debugObj.text = object->tag();
|
||||
debugObj.screenCoords = glm::project(position, updateCtx.view, updateCtx.projection, viewport);
|
||||
DebugObject debugObj;
|
||||
debugObj.tag = object->tag();
|
||||
debugObj.text = object->tag();
|
||||
debugObj.screenCoords = glm::project(position, updateCtx.view, updateCtx.projection, viewport);
|
||||
|
||||
guiCtx.debug.objects.push_back(move(debugObj));
|
||||
}
|
||||
guiCtx.debug.objects.push_back(move(debugObj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +325,7 @@ void Area::updateTriggers(const Creature &creature) {
|
|||
glm::vec2 intersection;
|
||||
float distance;
|
||||
|
||||
for (auto &object : _objects[ObjectType::Trigger]) {
|
||||
for (auto &object : _objectsByType[ObjectType::Trigger]) {
|
||||
Trigger &trigger = static_cast<Trigger &>(*object);
|
||||
if (trigger.distanceTo(liftedPosition) > kMaxDistanceToTestCollision) continue;
|
||||
|
||||
|
@ -400,7 +386,7 @@ void Area::setDebugMode(DebugMode mode) {
|
|||
void Area::saveTo(GameState &state) const {
|
||||
AreaState areaState;
|
||||
|
||||
for (auto &list : _objects) {
|
||||
for (auto &list : _objectsByType) {
|
||||
if (list.first != ObjectType::Creature && list.first != ObjectType::Door) continue;
|
||||
|
||||
for (auto &object : list.second) {
|
||||
|
@ -417,7 +403,7 @@ void Area::loadState(const GameState &state) {
|
|||
|
||||
const AreaState &areaState = it->second;
|
||||
|
||||
for (auto &list : _objects) {
|
||||
for (auto &list : _objectsByType) {
|
||||
if (list.first != ObjectType::Creature && list.first != ObjectType::Door) continue;
|
||||
|
||||
for (auto &object : list.second) {
|
||||
|
@ -426,52 +412,10 @@ void Area::loadState(const GameState &state) {
|
|||
}
|
||||
}
|
||||
|
||||
shared_ptr<SpatialObject> Area::find(uint32_t id) const {
|
||||
shared_ptr<SpatialObject> object;
|
||||
for (auto &list : _objects) {
|
||||
object = find(id, list.first);
|
||||
if (object) return object;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<SpatialObject> Area::find(const string &tag, int nth) const {
|
||||
shared_ptr<SpatialObject> object;
|
||||
for (auto &list : _objects) {
|
||||
object = find(tag, list.first, nth);
|
||||
if (object) return object;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<SpatialObject> Area::find(uint32_t id, ObjectType type) const {
|
||||
const ObjectList &list = _objects.find(type)->second;
|
||||
|
||||
auto it = find_if(
|
||||
list.begin(),
|
||||
list.end(),
|
||||
[&id](const shared_ptr<SpatialObject> &object) { return object->id() == id; });
|
||||
|
||||
return it != list.end() ? *it : nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<SpatialObject> Area::find(const string &tag, ObjectType type, int nth) const {
|
||||
const ObjectList &list = _objects.find(type)->second;
|
||||
int idx = 0;
|
||||
|
||||
for (auto &object : list) {
|
||||
if (object->tag() == tag && idx++ == nth) return object;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Area::findObstacleByWalkmesh(const glm::vec3 &from, const glm::vec3 &to, int mask, glm::vec3 &intersection, SpatialObject **obstacle) const {
|
||||
vector<pair<SpatialObject *, float>> candidates;
|
||||
|
||||
for (auto &list : _objects) {
|
||||
for (auto &list : _objectsByType) {
|
||||
if (list.first != ObjectType::Door && list.first != ObjectType::Placeable) continue;
|
||||
if (list.first == ObjectType::Door && (mask & kObstacleDoor) == 0) continue;
|
||||
if (list.first == ObjectType::Placeable && (mask & kObstaclePlaceable) == 0) continue;
|
||||
|
@ -526,7 +470,7 @@ bool Area::findObstacleByWalkmesh(const glm::vec3 &from, const glm::vec3 &to, in
|
|||
bool Area::findObstacleByAABB(const glm::vec3 &from, const glm::vec3 &to, int mask, const SpatialObject *except, SpatialObject **obstacle) const {
|
||||
vector<pair<SpatialObject *, float>> candidates;
|
||||
|
||||
for (auto &list : _objects) {
|
||||
for (auto &list : _objectsByType) {
|
||||
if (list.first != ObjectType::Creature &&
|
||||
list.first != ObjectType::Door &&
|
||||
list.first != ObjectType::Placeable) continue;
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "../gui/types.h"
|
||||
#include "../net/types.h"
|
||||
|
@ -34,6 +33,7 @@
|
|||
#include "object/placeable.h"
|
||||
#include "object/trigger.h"
|
||||
#include "object/waypoint.h"
|
||||
#include "objectcontainer.h"
|
||||
#include "room.h"
|
||||
#include "types.h"
|
||||
|
||||
|
@ -45,7 +45,7 @@ typedef std::vector<std::shared_ptr<SpatialObject>> ObjectList;
|
|||
|
||||
class ObjectFactory;
|
||||
|
||||
class Area : public Object {
|
||||
class Area : public Object, public ObjectContainer {
|
||||
public:
|
||||
Area(uint32_t id, resources::GameVersion version, ObjectFactory *objectFactory);
|
||||
|
||||
|
@ -71,10 +71,6 @@ public:
|
|||
void loadState(const GameState &state);
|
||||
|
||||
// Object search
|
||||
std::shared_ptr<SpatialObject> find(uint32_t id) const;
|
||||
std::shared_ptr<SpatialObject> find(const std::string &tag, int nth = 0) const;
|
||||
std::shared_ptr<SpatialObject> find(uint32_t id, ObjectType type) const;
|
||||
std::shared_ptr<SpatialObject> find(const std::string &tag, ObjectType type, int nth = 0) const;
|
||||
bool findObstacleByWalkmesh(const glm::vec3 &from, const glm::vec3 &to, int mask, glm::vec3 &intersection, SpatialObject **obstacle) const;
|
||||
bool findObstacleByAABB(const glm::vec3 &from, const glm::vec3 &to, int mask, const SpatialObject *except, SpatialObject **obstacle) const;
|
||||
|
||||
|
@ -98,7 +94,6 @@ public:
|
|||
|
||||
protected:
|
||||
ObjectFactory *_objectFactory { nullptr };
|
||||
std::map<ObjectType, ObjectList> _objects;
|
||||
bool _scriptsEnabled { true };
|
||||
std::function<void()> _onPlayerChanged;
|
||||
|
||||
|
|
|
@ -35,10 +35,8 @@ void Area::initGL() {
|
|||
shared_ptr<ModelInstance> model(room->model());
|
||||
if (model) model->initGL();
|
||||
}
|
||||
for (auto &pair : _objects) {
|
||||
for (auto &object : pair.second) {
|
||||
object->initGL();
|
||||
}
|
||||
for (auto &object : _objects) {
|
||||
object->initGL();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,17 +50,15 @@ void Area::updateSceneGraph(const glm::vec3 &cameraPosition) {
|
|||
glm::mat4 transform(glm::translate(glm::mat4(1.0f), room->position()));
|
||||
model->fill(_sceneGraph, transform, _debugMode == DebugMode::ModelNodes);
|
||||
}
|
||||
for (auto &list : _objects) {
|
||||
for (auto &object : list.second) {
|
||||
shared_ptr<ModelInstance> model(object->model());
|
||||
if (!model) continue;
|
||||
for (auto &object : _objects) {
|
||||
shared_ptr<ModelInstance> model(object->model());
|
||||
if (!model) continue;
|
||||
|
||||
model->fill(_sceneGraph, object->transform(), _debugMode == DebugMode::ModelNodes);
|
||||
}
|
||||
model->fill(_sceneGraph, object->transform(), _debugMode == DebugMode::ModelNodes);
|
||||
}
|
||||
switch (_debugMode) {
|
||||
case DebugMode::GameObjects:
|
||||
for (auto &list : _objects) {
|
||||
for (auto &list : _objectsByType) {
|
||||
ObjectType type = list.first;
|
||||
if (type != ObjectType::Creature && type != ObjectType::Placeable && type != ObjectType::Door) continue;
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ void Game::loadDialogGui() {
|
|||
dialog->initGL();
|
||||
dialog->setPickReplyEnabled(_pickDialogReplyEnabled);
|
||||
dialog->setGetObjectIdByTagFunc([this](const string &tag) {
|
||||
shared_ptr<Object> object(_module->area().find(tag, ObjectType::Creature));
|
||||
shared_ptr<Object> object(_module->area().find(tag));
|
||||
return object ? object->id() : 0;
|
||||
});
|
||||
dialog->setOnReplyPicked(bind(&Game::onDialogReplyPicked, this, _1));
|
||||
|
@ -263,8 +263,8 @@ void Game::onDialogReplyPicked(uint32_t index) {
|
|||
void Game::onDialogSpeakerChanged(uint32_t from, uint32_t to) {
|
||||
shared_ptr<SpatialObject> player(_module->area().player());
|
||||
shared_ptr<SpatialObject> partyLeader(_module->area().partyLeader());
|
||||
shared_ptr<SpatialObject> prevSpeaker = from != 0 ? _module->area().find(from, ObjectType::Creature) : nullptr;
|
||||
shared_ptr<SpatialObject> speaker = to != 0 ? _module->area().find(to, ObjectType::Creature) : nullptr;
|
||||
shared_ptr<SpatialObject> prevSpeaker = from != 0 ? _module->area().find(from) : nullptr;
|
||||
shared_ptr<SpatialObject> speaker = to != 0 ? _module->area().find(to) : nullptr;
|
||||
if (speaker == partyLeader) return;
|
||||
|
||||
debug(boost::format("Game: dialog speaker: \"%s\"") % (speaker ? speaker->tag() : ""));
|
||||
|
@ -510,7 +510,7 @@ shared_ptr<Object> Game::getObjectByTag(const string &tag, int nth) {
|
|||
}
|
||||
|
||||
shared_ptr<Object> Game::getWaypointByTag(const string &tag) {
|
||||
return _module->area().find(tag, ObjectType::Waypoint);
|
||||
return _module->area().find(tag);
|
||||
}
|
||||
|
||||
shared_ptr<Object> Game::getPlayer() {
|
||||
|
|
|
@ -157,7 +157,7 @@ void Module::getEntryPoint(const string &waypoint, glm::vec3 &position, float &h
|
|||
heading = _info.entryHeading;
|
||||
|
||||
if (!waypoint.empty()) {
|
||||
shared_ptr<SpatialObject> object(_area->find(waypoint, ObjectType::Waypoint));
|
||||
shared_ptr<SpatialObject> object(_area->find(waypoint));
|
||||
if (object) {
|
||||
position = object->position();
|
||||
heading = object->heading();
|
||||
|
|
|
@ -105,7 +105,7 @@ void MultiplayerArea::executeLoadCreature(const Command &cmd) {
|
|||
}
|
||||
|
||||
landObject(*creature);
|
||||
_objects[ObjectType::Creature].push_back(move(creature));
|
||||
add(creature);
|
||||
}
|
||||
|
||||
void MultiplayerArea::executeSetPlayerRole(const Command &cmd) {
|
||||
|
@ -128,7 +128,7 @@ void MultiplayerArea::executeSetPlayerRole(const Command &cmd) {
|
|||
}
|
||||
|
||||
void MultiplayerArea::executeSetObjectTransform(const Command &cmd) {
|
||||
shared_ptr<SpatialObject> object(find(cmd.objectId(), ObjectType::Creature));
|
||||
shared_ptr<SpatialObject> object(find(cmd.objectId()));
|
||||
if (object) {
|
||||
object->setSynchronize(false);
|
||||
object->setPosition(cmd.position());
|
||||
|
@ -138,7 +138,7 @@ void MultiplayerArea::executeSetObjectTransform(const Command &cmd) {
|
|||
}
|
||||
|
||||
void MultiplayerArea::executeSetObjectAnimation(const Command &cmd) {
|
||||
shared_ptr<SpatialObject> object(find(cmd.objectId(), ObjectType::Creature));
|
||||
shared_ptr<SpatialObject> object(find(cmd.objectId()));
|
||||
if (object) {
|
||||
object->setSynchronize(false);
|
||||
object->animate(cmd.animation(), cmd.animationFlags());
|
||||
|
@ -147,7 +147,7 @@ void MultiplayerArea::executeSetObjectAnimation(const Command &cmd) {
|
|||
}
|
||||
|
||||
void MultiplayerArea::executeSetCreatureMovementType(const Command &cmd) {
|
||||
shared_ptr<SpatialObject> creature(find(cmd.objectId(), ObjectType::Creature));
|
||||
shared_ptr<SpatialObject> creature(find(cmd.objectId()));
|
||||
if (creature) {
|
||||
creature->setSynchronize(false);
|
||||
static_cast<Creature &>(*creature).setMovementType(cmd.movementType());
|
||||
|
@ -156,7 +156,7 @@ void MultiplayerArea::executeSetCreatureMovementType(const Command &cmd) {
|
|||
}
|
||||
|
||||
void MultiplayerArea::executeSetCreatureTalking(const Command &cmd) {
|
||||
shared_ptr<SpatialObject> creature(find(cmd.objectId(), ObjectType::Creature));
|
||||
shared_ptr<SpatialObject> creature(find(cmd.objectId()));
|
||||
if (creature) {
|
||||
creature->setSynchronize(false);
|
||||
static_cast<Creature &>(*creature).setTalking(cmd.talking());
|
||||
|
@ -165,7 +165,7 @@ void MultiplayerArea::executeSetCreatureTalking(const Command &cmd) {
|
|||
}
|
||||
|
||||
void MultiplayerArea::executeSetDoorOpen(const Command &cmd) {
|
||||
shared_ptr<Object> door(find(cmd.objectId(), ObjectType::Door));
|
||||
shared_ptr<Object> door(find(cmd.objectId()));
|
||||
shared_ptr<Object> trigerrer(find(cmd.triggerrer()));
|
||||
if (door) {
|
||||
door->setSynchronize(false);
|
||||
|
@ -175,7 +175,7 @@ void MultiplayerArea::executeSetDoorOpen(const Command &cmd) {
|
|||
}
|
||||
|
||||
const shared_ptr<Object> MultiplayerArea::findCreatureByClientTag(const string &clientTag) const {
|
||||
auto creatures = _objects.find(ObjectType::Creature)->second;
|
||||
auto creatures = _objectsByType.find(ObjectType::Creature)->second;
|
||||
auto it = find_if(
|
||||
creatures.begin(),
|
||||
creatures.end(),
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "../area.h"
|
||||
#include "../multiplayer/command.h"
|
||||
|
||||
#include "command.h"
|
||||
#include "creature.h"
|
||||
|
||||
namespace reone {
|
||||
|
|
57
src/game/objectcontainer.cpp
Normal file
57
src/game/objectcontainer.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright © 2020 Vsevolod Kremianskii
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "objectcontainer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
void ObjectContainer::clear() {
|
||||
_objects.clear();
|
||||
_objectsByType.clear();
|
||||
_objectById.clear();
|
||||
_objectsByTag.clear();
|
||||
}
|
||||
|
||||
void ObjectContainer::add(const shared_ptr<SpatialObject> &object) {
|
||||
_objects.push_back(object);
|
||||
_objectsByType[object->type()].push_back(object);
|
||||
_objectById.insert(make_pair(object->id(), object));
|
||||
_objectsByTag[object->tag()].push_back(object);
|
||||
}
|
||||
|
||||
shared_ptr<SpatialObject> ObjectContainer::find(uint32_t id) const {
|
||||
auto object = _objectById.find(id);
|
||||
if (object == _objectById.end()) return nullptr;
|
||||
|
||||
return object->second;
|
||||
}
|
||||
|
||||
shared_ptr<SpatialObject> ObjectContainer::find(const string &tag, int nth) const {
|
||||
auto objects = _objectsByTag.find(tag);
|
||||
if (objects == _objectsByTag.end()) return nullptr;
|
||||
if (nth >= objects->second.size()) return nullptr;
|
||||
|
||||
return objects->second[nth];
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
50
src/game/objectcontainer.h
Normal file
50
src/game/objectcontainer.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright © 2020 Vsevolod Kremianskii
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "object/spatial.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
typedef std::vector<std::shared_ptr<SpatialObject>> ObjectList;
|
||||
|
||||
class ObjectContainer {
|
||||
public:
|
||||
std::shared_ptr<SpatialObject> find(uint32_t id) const;
|
||||
std::shared_ptr<SpatialObject> find(const std::string &tag, int nth = 0) const;
|
||||
|
||||
protected:
|
||||
ObjectList _objects;
|
||||
std::map<ObjectType, ObjectList> _objectsByType;
|
||||
std::map<uint32_t, std::shared_ptr<SpatialObject>> _objectById;
|
||||
std::map<std::string, ObjectList> _objectsByTag;
|
||||
|
||||
void clear();
|
||||
void add(const std::shared_ptr<SpatialObject> &object);
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
Loading…
Reference in a new issue