Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9936f6107 | |||
| 905af46731 | |||
| 8b0bc76a9f | |||
| fb2d49f1e0 | |||
| cc6981e35f | |||
| f9a5f60969 |
@@ -22,7 +22,7 @@
|
||||
#include "barrier_manager.hpp"
|
||||
|
||||
void BarrierManager::DrawTo(SDL_Renderer* const dest, Sint16 x, Sint16 y, double scaleX, double scaleY) {
|
||||
for (auto& it : barrierMap) {
|
||||
for (auto& it : elementMap) {
|
||||
it.second.DrawTo(dest, x, y);
|
||||
}
|
||||
}
|
||||
@@ -47,26 +47,38 @@ void BarrierManager::UnloadTemplateImages() {
|
||||
}
|
||||
|
||||
BaseBarrier* BarrierManager::Create(int index) {
|
||||
barrierMap.emplace(index, BaseBarrier(baseImage, templateImages));
|
||||
return &barrierMap[index];
|
||||
elementMap.emplace(index, BaseBarrier(baseImage, templateImages));
|
||||
return &elementMap[index];
|
||||
}
|
||||
|
||||
void BarrierManager::Unload(int i) {
|
||||
barrierMap.erase(i);
|
||||
elementMap.erase(i);
|
||||
}
|
||||
|
||||
void BarrierManager::UnloadAll() {
|
||||
barrierMap.clear();
|
||||
elementMap.clear();
|
||||
}
|
||||
|
||||
void BarrierManager::UnloadIf(std::function<bool(std::pair<const int, BaseBarrier const&>)> fn) {
|
||||
std::map<int, BaseBarrier>::iterator it = elementMap.begin();
|
||||
while (it != elementMap.end()) {
|
||||
if (fn(*it)) {
|
||||
it = elementMap.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BarrierManager::Size() {
|
||||
return barrierMap.size();
|
||||
return elementMap.size();
|
||||
}
|
||||
|
||||
BaseBarrier* BarrierManager::Find(int i) {
|
||||
std::map<int, BaseBarrier>::iterator it = barrierMap.find(i);
|
||||
std::map<int, BaseBarrier>::iterator it = elementMap.find(i);
|
||||
|
||||
if (it == barrierMap.end()) {
|
||||
if (it == elementMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -74,7 +86,7 @@ BaseBarrier* BarrierManager::Find(int i) {
|
||||
}
|
||||
|
||||
std::map<int, BaseBarrier>* BarrierManager::GetContainer() {
|
||||
return &barrierMap;
|
||||
return &elementMap;
|
||||
}
|
||||
|
||||
std::map<std::string, Image>* BarrierManager::GetTemplateContainer() {
|
||||
|
||||
@@ -42,6 +42,7 @@ public:
|
||||
BaseBarrier* Create(int index);
|
||||
void Unload(int i);
|
||||
void UnloadAll();
|
||||
void UnloadIf(std::function<bool(std::pair<const int, BaseBarrier const&>)> fn);
|
||||
|
||||
int Size();
|
||||
|
||||
@@ -52,5 +53,5 @@ public:
|
||||
private:
|
||||
Image baseImage;
|
||||
std::map<std::string, Image> templateImages;
|
||||
std::map<int, BaseBarrier> barrierMap;
|
||||
std::map<int, BaseBarrier> elementMap;
|
||||
};
|
||||
@@ -116,8 +116,8 @@ World::World(int* const argClientIndex, int* const argAccountIndex):
|
||||
"slot 7 red.png",
|
||||
"slot 8 red.png"
|
||||
};
|
||||
barrierMgr.LoadBaseImage(GetRenderer(), config["dir.sprites"] + "/barrier/base.png");
|
||||
barrierMgr.LoadTemplateImages(GetRenderer(), config["dir.sprites"] + "/barrier/", slotNames);
|
||||
barrierMgr.LoadBaseImage(GetRenderer(), config["dir.sprites"] + "barrier/base.png");
|
||||
barrierMgr.LoadTemplateImages(GetRenderer(), config["dir.sprites"] + "barrier/", slotNames);
|
||||
|
||||
std::cout << "Templates loaded: " << barrierMgr.GetTemplateContainer()->size() << std::endl;
|
||||
}
|
||||
@@ -185,7 +185,27 @@ void World::Update() {
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: (1) regular query interval
|
||||
//TODO: (0) regular query interval
|
||||
if (Clock::now() - queryTime > std::chrono::seconds(3)) {
|
||||
queryTime = Clock::now();
|
||||
//query the world state (room)
|
||||
CharacterPacket characterPacket;
|
||||
memset(&characterPacket, 0, MAX_PACKET_SIZE);
|
||||
characterPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||
characterPacket.roomIndex = roomIndex;
|
||||
network.SendTo(Channels::SERVER, &characterPacket);
|
||||
|
||||
CreaturePacket creaturePacket;
|
||||
creaturePacket.type = SerialPacketType::QUERY_CREATURE_EXISTS;
|
||||
creaturePacket.roomIndex = roomIndex;
|
||||
network.SendTo(Channels::SERVER, &creaturePacket);
|
||||
|
||||
BarrierPacket barrierPacket;
|
||||
barrierPacket.type = SerialPacketType::QUERY_BARRIER_EXISTS;
|
||||
barrierPacket.roomIndex = roomIndex;
|
||||
network.SendTo(Channels::SERVER, &barrierPacket);
|
||||
}
|
||||
|
||||
//cull creatures
|
||||
for (std::map<int, BaseCreature>::iterator it = creatureMap.begin(); it != creatureMap.end(); /* */) {
|
||||
if ( (localCharacter->GetOrigin() - it->second.GetOrigin()).Length() > INFLUENCE_RADIUS) {
|
||||
@@ -196,7 +216,10 @@ void World::Update() {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: cull barriers
|
||||
//cull barriers
|
||||
barrierMgr.UnloadIf([&](std::pair<const int, BaseBarrier const&> barrierIt) -> bool {
|
||||
return (localCharacter->GetOrigin() - barrierIt.second.GetOrigin()).Length() > INFLUENCE_RADIUS;
|
||||
});
|
||||
|
||||
//get the collidable boxes
|
||||
std::list<BoundingBox> boxList = GenerateCollisionGrid(localCharacter, tileSheet.GetTileW(), tileSheet.GetTileH());
|
||||
@@ -727,6 +750,9 @@ void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
||||
if (character->GetOwner() == accountIndex) {
|
||||
localCharacter = static_cast<LocalCharacter*>(character);
|
||||
|
||||
//reset queries
|
||||
queryTime = Clock::now() - std::chrono::seconds(4); //back 4 seconds to trigger automatically
|
||||
|
||||
//focus the camera on this character's sprite
|
||||
camera.marginX = (camera.width / 2 - localCharacter->GetSprite()->GetClipW() / 2);
|
||||
camera.marginY = (camera.height/ 2 - localCharacter->GetSprite()->GetClipH() / 2);
|
||||
@@ -734,26 +760,6 @@ void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
||||
//focus on this character's info
|
||||
characterIndex = argPacket->characterIndex;
|
||||
roomIndex = argPacket->roomIndex;
|
||||
|
||||
//query the world state (room)
|
||||
CharacterPacket characterPacket;
|
||||
memset(&characterPacket, 0, MAX_PACKET_SIZE);
|
||||
characterPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||
characterPacket.roomIndex = roomIndex;
|
||||
characterPacket.origin = localCharacter->GetOrigin();
|
||||
network.SendTo(Channels::SERVER, &characterPacket);
|
||||
|
||||
CreaturePacket creaturePacket;
|
||||
creaturePacket.type = SerialPacketType::QUERY_CREATURE_EXISTS;
|
||||
creaturePacket.roomIndex = roomIndex;
|
||||
creaturePacket.origin = localCharacter->GetOrigin();
|
||||
network.SendTo(Channels::SERVER, &creaturePacket);
|
||||
|
||||
BarrierPacket barrierPacket;
|
||||
barrierPacket.type = SerialPacketType::QUERY_BARRIER_EXISTS;
|
||||
barrierPacket.roomIndex = roomIndex;
|
||||
barrierPacket.origin = localCharacter->GetOrigin();
|
||||
network.SendTo(Channels::SERVER, &barrierPacket);
|
||||
}
|
||||
|
||||
//debug
|
||||
@@ -794,12 +800,12 @@ void World::hCharacterUnload(CharacterPacket* const argPacket) {
|
||||
void World::hQueryCharacterExists(CharacterPacket* const argPacket) {
|
||||
//prevent a double message about this player's character
|
||||
//TODO: why is this commented out?
|
||||
// if (argPacket->accountIndex == accountIndex) {
|
||||
// return;
|
||||
// }
|
||||
if (argPacket->accountIndex == accountIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
//ignore characters in a different room (sub-optimal)
|
||||
if (argPacket->roomIndex != roomIndex) {
|
||||
if (argPacket->roomIndex != roomIndex || (localCharacter->GetOrigin() - argPacket->origin).Length() > INFLUENCE_RADIUS) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -916,10 +922,12 @@ void World::hCreatureUnload(CreaturePacket* const argPacket) {
|
||||
}
|
||||
|
||||
void World::hQueryCreatureExists(CreaturePacket* const argPacket) {
|
||||
std::cout << "Creature Query" << std::endl;
|
||||
if (!localCharacter) {
|
||||
return;
|
||||
}
|
||||
|
||||
//ignore creatures in a different room (sub-optimal)
|
||||
if (argPacket->roomIndex != roomIndex) {
|
||||
if (argPacket->roomIndex != roomIndex || (localCharacter->GetOrigin() - argPacket->origin).Length() > INFLUENCE_RADIUS) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1024,10 +1032,12 @@ void World::hBarrierUnload(BarrierPacket* const argPacket) {
|
||||
}
|
||||
|
||||
void World::hQueryBarrierExists(BarrierPacket* const argPacket) {
|
||||
std::cout << "Barrier Query" << std::endl;
|
||||
if (!localCharacter) {
|
||||
return;
|
||||
}
|
||||
|
||||
//ignore barriers in a different room (sub-optimal)
|
||||
if (argPacket->roomIndex != roomIndex) {
|
||||
if (argPacket->roomIndex != roomIndex || (localCharacter->GetOrigin() - argPacket->origin).Length() > INFLUENCE_RADIUS) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ private:
|
||||
//TODO: (2) Heartbeat needs it's own utility
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
Clock::time_point lastBeat = Clock::now();
|
||||
Clock::time_point queryTime = Clock::now() - std::chrono::seconds(4); //back 4 seconds to trigger automatically
|
||||
int attemptedBeats = 0;
|
||||
|
||||
//ugly references; I hate this
|
||||
|
||||
|
Before Width: | Height: | Size: 680 B |
|
Before Width: | Height: | Size: 738 B After Width: | Height: | Size: 738 B |
|
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 763 B |
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 270 B |
|
Before Width: | Height: | Size: 305 B After Width: | Height: | Size: 305 B |
|
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 423 B After Width: | Height: | Size: 423 B |
|
Before Width: | Height: | Size: 422 B After Width: | Height: | Size: 422 B |
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 301 B |
|
Before Width: | Height: | Size: 299 B After Width: | Height: | Size: 299 B |
|
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
|
Before Width: | Height: | Size: 412 B After Width: | Height: | Size: 412 B |
|
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 431 B After Width: | Height: | Size: 431 B |
|
Before Width: | Height: | Size: 429 B After Width: | Height: | Size: 429 B |
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 407 B |
|
Before Width: | Height: | Size: 400 B After Width: | Height: | Size: 400 B |
|
Before Width: | Height: | Size: 656 B After Width: | Height: | Size: 656 B |
@@ -130,14 +130,14 @@ roomManagerAPI.SetOnCreate(function(room, index)
|
||||
--
|
||||
end)
|
||||
|
||||
creatureManagerAPI.Create(roomAPI.GetCreatureMgr(room), "anibunny.png", bunnySquare)
|
||||
|
||||
--creatureManager with SetOnCreate, SetOnUnload & create & unload
|
||||
barrierManagerAPI.SetOnCreate(roomAPI.GetBarrierMgr(room), function(barrier)
|
||||
barrierAPI.SetScript(barrier, barrierTick)
|
||||
end)
|
||||
|
||||
roomAPI.SetOnTick(room, function(room)
|
||||
ret = 0
|
||||
--placeholders
|
||||
roomAPI.ForEachCharacter(room, function(character)
|
||||
--
|
||||
end)
|
||||
@@ -146,7 +146,19 @@ roomManagerAPI.SetOnCreate(function(room, index)
|
||||
--
|
||||
end)
|
||||
|
||||
--TODO: for each barrier
|
||||
roomAPI.ForEachBarrier(room, function(creature)
|
||||
--
|
||||
end)
|
||||
|
||||
--respawn a new rabbit when needed
|
||||
if creatureManagerAPI.GetLoadedCount(roomAPI.GetCreatureMgr(room)) < 1 and
|
||||
barrierManagerAPI.GetLoadedCount(roomAPI.GetBarrierMgr(room)) < 2
|
||||
then
|
||||
--make a new creature
|
||||
creatureManagerAPI.Create(roomAPI.GetCreatureMgr(room), "anibunny.png", bunnySquare)
|
||||
ret = 1
|
||||
end
|
||||
return ret
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
#include "lua_utilities.hpp"
|
||||
|
||||
#include "barrier_defines.hpp"
|
||||
|
||||
BarrierManager::BarrierManager() {
|
||||
//EMPTY
|
||||
}
|
||||
@@ -34,57 +32,12 @@ BarrierManager::~BarrierManager() {
|
||||
}
|
||||
|
||||
//arg: a list of barriers to be updated in the clients
|
||||
void BarrierManager::Update(
|
||||
std::list<std::tuple<const int, BarrierData*, int>>* barrierList,
|
||||
std::list<std::tuple<const int, CreatureData*, int>>* creatureList,
|
||||
std::list<CharacterData*>* characterList
|
||||
)
|
||||
{
|
||||
//for each given creature, if a collision was detected, make a new barrier
|
||||
for (auto& it : *creatureList) {
|
||||
if (std::get<2>(it) & 2) {
|
||||
int index = Create(-1); //instance from creature index?
|
||||
BarrierData* barrierData = Find(index);
|
||||
barrierData->SetOrigin({
|
||||
(CREATURE_BOUNDS_WIDTH - BARRIER_BOUNDS_WIDTH) / 2 + std::get<1>(it)->GetOrigin().x,
|
||||
(CREATURE_BOUNDS_HEIGHT - BARRIER_BOUNDS_HEIGHT) / 2 + std::get<1>(it)->GetOrigin().y
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: merge barriers
|
||||
//TODO: absorb creatures into existing barriers
|
||||
|
||||
//update the barriers
|
||||
//TODO: how to delete the barriers?
|
||||
int ret; //0 = no action, ret&1 = update clients, ret&2 = collision detected
|
||||
void BarrierManager::Update(std::list<std::pair<const int, BarrierData*>>* barrierList, bool updateAll) {
|
||||
int ret;
|
||||
for (auto& it : elementMap) {
|
||||
//normal update
|
||||
ret = it.second.Update(lua) ? 1 : 0;
|
||||
|
||||
//check for collision with a character
|
||||
BoundingBox barrierBox = it.second.GetRealBounds();
|
||||
for (auto& it : *characterList) {
|
||||
if (barrierBox.CheckOverlap(it->GetRealBounds())) {
|
||||
//this will need updating
|
||||
ret |= 2;
|
||||
}
|
||||
|
||||
//TODO: absorb characters
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
//push to the return list
|
||||
barrierList->push_back(std::make_tuple(it.first, &it.second, ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BarrierManager::Cleanup(std::list<std::tuple<const int, BarrierData*, int>>* barrierList) {
|
||||
//unload the given barrier objects
|
||||
for (auto& it : *barrierList) {
|
||||
if (std::get<2>(it) & 4) {
|
||||
Unload(std::get<0>(it));
|
||||
ret = it.second.Update(lua);
|
||||
if (ret || updateAll) {
|
||||
barrierList->push_back(std::pair<const int, BarrierData*>(it.first, &it.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "barrier_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "creature_data.hpp"
|
||||
|
||||
#include "lua.hpp"
|
||||
#include "sqlite3.h"
|
||||
@@ -31,7 +29,6 @@
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
|
||||
class BarrierManager {
|
||||
public:
|
||||
@@ -39,12 +36,7 @@ public:
|
||||
~BarrierManager();
|
||||
|
||||
//common public methods
|
||||
void Update(
|
||||
std::list<std::tuple<const int, BarrierData*, int>>* barrierList,
|
||||
std::list<std::tuple<const int, CreatureData*, int>>* creatureList,
|
||||
std::list<CharacterData*>* characterList
|
||||
);
|
||||
void Cleanup(std::list<std::tuple<const int, BarrierData*, int>>* barrierList);
|
||||
void Update(std::list<std::pair<const int, BarrierData*>>* barrierList, bool updateAll);
|
||||
|
||||
int Create(int instanceIndex);
|
||||
void Unload(int uid);
|
||||
|
||||
@@ -32,39 +32,12 @@ CreatureManager::~CreatureManager() {
|
||||
}
|
||||
|
||||
//arg: a list of creatures to be updated in the clients
|
||||
void CreatureManager::Update(
|
||||
std::list<std::tuple<const int, CreatureData*, int>>* creatureList,
|
||||
std::list<CharacterData*>* characterList
|
||||
)
|
||||
{
|
||||
//for each creature
|
||||
int ret; //0 = no action, ret&1 = update clients, ret&2 = collision detected
|
||||
void CreatureManager::Update(std::list<std::pair<const int, CreatureData*>>* creatureList, bool updateAll) {
|
||||
int ret;
|
||||
for (auto& it : elementMap) {
|
||||
//normal update
|
||||
ret = it.second.Update(lua) ? 1 : 0;
|
||||
|
||||
//check for collision with a character
|
||||
BoundingBox creatureBox = it.second.GetRealBounds();
|
||||
for (auto& it : *characterList) {
|
||||
if (creatureBox.CheckOverlap(it->GetRealBounds())) {
|
||||
//this will need updating
|
||||
ret |= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
//push to the return list
|
||||
creatureList->push_back(std::make_tuple(it.first, &it.second, ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureManager::Cleanup(std::list<std::tuple<const int, CreatureData*, int>>* creatureList) {
|
||||
//unload the given creature objects
|
||||
for (auto& it : *creatureList) {
|
||||
if (std::get<2>(it) & 2) {
|
||||
Unload(std::get<0>(it));
|
||||
ret = it.second.Update(lua);
|
||||
if (ret || updateAll) {
|
||||
creatureList->push_back(std::pair<const int, CreatureData*>(it.first, &it.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "character_data.hpp"
|
||||
#include "creature_data.hpp"
|
||||
|
||||
#include "lua.hpp"
|
||||
@@ -31,7 +30,6 @@
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
class CreatureManager {
|
||||
public:
|
||||
@@ -39,11 +37,7 @@ public:
|
||||
~CreatureManager();
|
||||
|
||||
//common public methods
|
||||
void Update(
|
||||
std::list<std::tuple<const int, CreatureData*, int>>* creatureList,
|
||||
std::list<CharacterData*>* characterList
|
||||
);
|
||||
void Cleanup(std::list<std::tuple<const int, CreatureData*, int>>* creatureList);
|
||||
void Update(std::list<std::pair<const int, CreatureData*>>* creatureList, bool updateAll);
|
||||
|
||||
int Create(std::string avatar, int scriptRef);
|
||||
void Unload(int uid);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../characters ../entities ../../common/gameplay ../../common/utilities
|
||||
INCLUDES+=. .. ../entities ../../common/gameplay ../../common/utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
|
||||
@@ -63,10 +63,6 @@ BoundingBox Entity::GetBounds() const {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
BoundingBox Entity::GetRealBounds() const {
|
||||
return bounds + origin;
|
||||
}
|
||||
|
||||
const char* Entity::GetType() const {
|
||||
return type;
|
||||
}
|
||||
@@ -41,7 +41,6 @@ public:
|
||||
Vector2 GetOrigin() const;
|
||||
Vector2 GetMotion() const;
|
||||
BoundingBox GetBounds() const;
|
||||
BoundingBox GetRealBounds() const;
|
||||
|
||||
const char* GetType() const;
|
||||
|
||||
|
||||
@@ -109,6 +109,24 @@ static int forEachCreature(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int forEachBarrier(lua_State* L) {
|
||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
BarrierManager* barrierMgr = room->GetBarrierMgr();
|
||||
//pass each barrier to the given function
|
||||
for (auto& it : *barrierMgr->GetContainer()) {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushlightuserdata(L, static_cast<void*>(&it.second));
|
||||
//call each iteration, throwing an exception if something happened
|
||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||
std::ostringstream os;
|
||||
os << "Lua error: ";
|
||||
os << lua_tostring(L, -1);
|
||||
throw(std::runtime_error(os.str()));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setOnTick(lua_State* L) {
|
||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, room->GetTickReference());
|
||||
@@ -122,6 +140,19 @@ static int getOnTick(lua_State* L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//TODO: autogen docs
|
||||
static int setTag(lua_State* L) {
|
||||
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
room->SetTag(lua_tostring(L, 2), lua_tostring(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getTag(lua_State* L) {
|
||||
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
lua_pushstring(L, room->GetTag(lua_tostring(L, 2)).c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int initialize(lua_State* L) {
|
||||
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
|
||||
@@ -148,10 +179,14 @@ static const luaL_Reg roomLib[] = {
|
||||
|
||||
{"ForEachCharacter", forEachCharacter},
|
||||
{"ForEachCreature", forEachCreature},
|
||||
{"ForEachBarrier", forEachBarrier},
|
||||
|
||||
{"SetOnTick", setOnTick},
|
||||
{"GetOnTick", getOnTick},
|
||||
|
||||
{"SetTag", setTag},
|
||||
{"GetTag", getTag},
|
||||
|
||||
{"Initialize", initialize},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
@@ -30,70 +30,42 @@
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
|
||||
//TODO: (9) character collisions should be preformed client-side
|
||||
void RoomData::RunFrame() {
|
||||
//get the hook
|
||||
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
|
||||
|
||||
//returning 1 means pump all
|
||||
bool updateAll = false;
|
||||
if (!lua_isnil(lua, -1)) {
|
||||
//call the tick function, with this as a parameter
|
||||
lua_pushlightuserdata(lua, this);
|
||||
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
|
||||
if (lua_pcall(lua, 1, 1, 0) != LUA_OK) {
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||
}
|
||||
|
||||
//pump creatures & barriers
|
||||
if (lua_tonumber(lua, -1)) {
|
||||
updateAll = true;
|
||||
}
|
||||
|
||||
lua_pop(lua, 1);
|
||||
}
|
||||
else {
|
||||
lua_pop(lua, 1);
|
||||
}
|
||||
|
||||
//lists of non-character entities that need updating client-side
|
||||
//types are index, ptr, action (0 = update, 1 = unload)
|
||||
std::list<std::tuple<const int, CreatureData*, int>> creatureList;
|
||||
std::list<std::tuple<const int, BarrierData*, int>> barrierList;
|
||||
std::list<std::pair<const int, CreatureData*>> creatureList;
|
||||
std::list<std::pair<const int, BarrierData*>> barrierList;
|
||||
|
||||
//update the entities in the room
|
||||
for (auto& it : characterList) {
|
||||
it->Update();
|
||||
}
|
||||
creatureMgr.Update(&creatureList, &characterList);
|
||||
barrierMgr.Update(&barrierList, &creatureList, &characterList);
|
||||
|
||||
//send the creature updates
|
||||
for (auto& it : creatureList) {
|
||||
CreaturePacket packet;
|
||||
copyCreatureToPacket(&packet, std::get<1>(it), std::get<0>(it));
|
||||
|
||||
//interpret the event
|
||||
if (std::get<2>(it) & 1) {
|
||||
packet.type = SerialPacketType::CREATURE_UPDATE;
|
||||
}
|
||||
if (std::get<2>(it) & 2) {
|
||||
packet.type = SerialPacketType::CREATURE_UNLOAD;
|
||||
}
|
||||
|
||||
packet.roomIndex = roomIndex;
|
||||
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, std::get<1>(it)->GetOrigin(), INFLUENCE_RADIUS);
|
||||
}
|
||||
|
||||
//send the barrier updates
|
||||
for (auto& it : barrierList) {
|
||||
BarrierPacket packet;
|
||||
copyBarrierToPacket(&packet, std::get<1>(it), std::get<0>(it));
|
||||
|
||||
//interpret the event
|
||||
if (std::get<2>(it) & 1 || std::get<2>(it) & 2) {
|
||||
packet.type = SerialPacketType::BARRIER_UPDATE;
|
||||
}
|
||||
|
||||
packet.roomIndex = roomIndex;
|
||||
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, std::get<1>(it)->GetOrigin(), INFLUENCE_RADIUS);
|
||||
}
|
||||
|
||||
//cleanup the lists
|
||||
creatureMgr.Cleanup(&creatureList);
|
||||
barrierMgr.Cleanup(&barrierList);
|
||||
creatureMgr.Update(&creatureList, updateAll);
|
||||
barrierMgr.Update(&barrierList, updateAll);
|
||||
|
||||
//build a list of entities for use with the triggers
|
||||
std::stack<Entity*> entityStack;
|
||||
@@ -103,6 +75,67 @@ void RoomData::RunFrame() {
|
||||
|
||||
//Compare the triggers to the entities, using their real hitboxes
|
||||
triggerMgr.Compare(entityStack);
|
||||
|
||||
//Creature/character collisions, O(m*n)
|
||||
for (auto characterIt : characterList) {
|
||||
BoundingBox characterBox = characterIt->GetBounds() + characterIt->GetOrigin();
|
||||
|
||||
std::list<int> creatureUnloadList;
|
||||
|
||||
for (auto creatureIt : *creatureMgr.GetContainer()) {
|
||||
BoundingBox creatureBox = creatureIt.second.GetBounds() + creatureIt.second.GetOrigin();
|
||||
|
||||
if (characterBox.CheckOverlap(creatureBox)) {
|
||||
int barrierIndex = barrierMgr.Create(-1);
|
||||
BarrierData* barrierData = barrierMgr.Find(barrierIndex);
|
||||
barrierData->SetRoomIndex(roomIndex);
|
||||
barrierData->SetOrigin({
|
||||
(CREATURE_BOUNDS_WIDTH - BARRIER_BOUNDS_WIDTH) / 2 + creatureBox.x,
|
||||
(CREATURE_BOUNDS_HEIGHT - BARRIER_BOUNDS_HEIGHT) / 2 + creatureBox.y,
|
||||
});
|
||||
|
||||
BarrierPacket barrierPacket;
|
||||
barrierPacket.type = SerialPacketType::BARRIER_CREATE;
|
||||
copyBarrierToPacket(&barrierPacket, barrierData, barrierIndex);
|
||||
|
||||
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&barrierPacket), roomIndex, characterIt->GetOrigin(), INFLUENCE_RADIUS);
|
||||
|
||||
//delete this creature
|
||||
creatureUnloadList.push_back(creatureIt.first);
|
||||
}
|
||||
}
|
||||
|
||||
//actually unload these creatures
|
||||
for (auto& it : creatureUnloadList) {
|
||||
CreatureData* creatureData = creatureMgr.Find(it);
|
||||
|
||||
CreaturePacket creaturePacket;
|
||||
creaturePacket.type = SerialPacketType::CREATURE_UNLOAD;
|
||||
copyCreatureToPacket(&creaturePacket, creatureData, it);
|
||||
|
||||
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&creaturePacket), roomIndex, creatureData->GetOrigin(), INFLUENCE_RADIUS);
|
||||
|
||||
creatureMgr.Unload(it);
|
||||
}
|
||||
}
|
||||
|
||||
//send the creature updates
|
||||
for (auto& it : creatureList) {
|
||||
CreaturePacket packet;
|
||||
copyCreatureToPacket(&packet, it.second, it.first);
|
||||
packet.type = SerialPacketType::CREATURE_UPDATE;
|
||||
packet.roomIndex = roomIndex;
|
||||
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, it.second->GetOrigin(), INFLUENCE_RADIUS);
|
||||
}
|
||||
|
||||
//send the barrier updates
|
||||
for (auto& it : barrierList) {
|
||||
BarrierPacket packet;
|
||||
copyBarrierToPacket(&packet, it.second, it.first);
|
||||
packet.type = SerialPacketType::BARRIER_UPDATE;
|
||||
packet.roomIndex = roomIndex;
|
||||
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, it.second->GetOrigin(), INFLUENCE_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
std::string RoomData::SetName(std::string s) {
|
||||
@@ -178,4 +211,12 @@ int RoomData::SetTickReference(int i) {
|
||||
|
||||
int RoomData::GetTickReference() {
|
||||
return tickRef;
|
||||
}
|
||||
|
||||
std::string RoomData::SetTag(std::string key, std::string value) {
|
||||
return tags[key] = value;
|
||||
}
|
||||
|
||||
std::string RoomData::GetTag(std::string key) {
|
||||
return tags[key];
|
||||
}
|
||||
@@ -70,6 +70,9 @@ public:
|
||||
int GetTickReference();
|
||||
//TODO: other triggers like player entry & exit, etc.
|
||||
|
||||
std::string SetTag(std::string key, std::string value);
|
||||
std::string GetTag(std::string key);
|
||||
|
||||
private:
|
||||
//metadata
|
||||
std::string roomName;
|
||||
@@ -79,7 +82,7 @@ private:
|
||||
int roomIndex = 0;
|
||||
BarrierManager barrierMgr;
|
||||
std::list<CharacterData*> characterList;
|
||||
CombatInstanceManager combatInstanceMgr;
|
||||
CombatInstanceManager CombatInstanceMgr;
|
||||
CreatureManager creatureMgr;
|
||||
RegionPagerLua pager;
|
||||
TriggerManager triggerMgr;
|
||||
@@ -90,4 +93,5 @@ private:
|
||||
|
||||
//hooks
|
||||
int tickRef = LUA_NOREF;
|
||||
std::map<std::string, std::string> tags;
|
||||
};
|
||||
|
||||