Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c1ace69e19 | |||
| 5c404c572e | |||
| 878d502b8b | |||
| 2a1ee4acbf | |||
| 0e149acc62 | |||
| 63e4394583 | |||
| 7aeabf0d14 | |||
| 9d5a668045 | |||
| 894b53e760 | |||
| eff23352aa | |||
| fa4ccb6596 |
@@ -1,6 +1,6 @@
|
|||||||
## Outline
|
## Outline
|
||||||
|
|
||||||
Tortuga is a 2D multiplayer JRPG featuring permadeath, with an emphasis on multiplayer cooperation, exploration and customization. The game runs on customizable public and private servers.
|
Tortuga is a 2D MMORPG featuring permadeath, with an emphasis on multiplayer cooperation, exploration and customization. The game runs on customizable public and private servers.
|
||||||
|
|
||||||
This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), as well as more modern sandboxes amd MMOs (Minecraft, EVE Online). This project is currently independently created and funded, with the goal of creating a game that will engage the players and inspire a large community.
|
This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), as well as more modern sandboxes amd MMOs (Minecraft, EVE Online). This project is currently independently created and funded, with the goal of creating a game that will engage the players and inspire a large community.
|
||||||
|
|
||||||
|
|||||||
@@ -125,8 +125,16 @@ void World::Update() {
|
|||||||
it.second.Update();
|
it.second.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
//update the map
|
//update the map
|
||||||
UpdateMap();
|
UpdateMap();
|
||||||
|
}
|
||||||
|
catch(terminal_error& e) {
|
||||||
|
throw(e);
|
||||||
|
}
|
||||||
|
catch(std::exception& e) {
|
||||||
|
std::cerr << "UpdateMap Error: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//skip the rest without a local character
|
//skip the rest without a local character
|
||||||
if (!localCharacter) {
|
if (!localCharacter) {
|
||||||
@@ -162,6 +170,11 @@ void World::Render(SDL_Surface* const screen) {
|
|||||||
//draw the map
|
//draw the map
|
||||||
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
||||||
tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y);
|
tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y);
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
// std::ostringstream msg;
|
||||||
|
// msg << it->GetX() << ", " << it->GetY();
|
||||||
|
// font.DrawStringTo(msg.str(), screen, it->GetX() * tileSheet.GetImage()->GetClipW() - camera.x, it->GetY() * tileSheet.GetImage()->GetClipH() - camera.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw the entities
|
//draw the entities
|
||||||
|
|||||||
@@ -23,6 +23,24 @@
|
|||||||
|
|
||||||
#include "channels.hpp"
|
#include "channels.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//static functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
static int regionChecksum(Region* const region) {
|
||||||
|
int sum = 0;
|
||||||
|
for(int i = 0; i < REGION_WIDTH; i++) {
|
||||||
|
for (int j = 0; j < REGION_HEIGHT; j++) {
|
||||||
|
for (int k = 0; k < REGION_DEPTH; k++) {
|
||||||
|
sum += region->GetTile(i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//map management
|
//map management
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -40,6 +58,13 @@ void World::SendRegionRequest(int roomIndex, int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::hRegionContent(RegionPacket* const argPacket) {
|
void World::hRegionContent(RegionPacket* const argPacket) {
|
||||||
|
//checksum
|
||||||
|
if (regionChecksum(argPacket->region) == 0) {
|
||||||
|
std::ostringstream msg;
|
||||||
|
msg << "Received region checksum failed: " << argPacket->x << ", " << argPacket->y;
|
||||||
|
throw(std::runtime_error(msg.str()));
|
||||||
|
}
|
||||||
|
|
||||||
//replace existing regions
|
//replace existing regions
|
||||||
regionPager.UnloadIf([&](Region const& region) -> bool {
|
regionPager.UnloadIf([&](Region const& region) -> bool {
|
||||||
return region.GetX() == argPacket->x && region.GetY() == argPacket->y;
|
return region.GetX() == argPacket->x && region.GetY() == argPacket->y;
|
||||||
@@ -71,9 +96,23 @@ void World::UpdateMap() {
|
|||||||
//request empty regions within this zone
|
//request empty regions within this zone
|
||||||
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
|
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
|
||||||
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
|
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
|
||||||
if (!regionPager.FindRegion(i, j)) {
|
Region* region = regionPager.FindRegion(i, j);
|
||||||
|
if (!region) {
|
||||||
|
//request absent region
|
||||||
SendRegionRequest(roomIndex, i, j);
|
SendRegionRequest(roomIndex, i, j);
|
||||||
}
|
}
|
||||||
|
else if (regionChecksum(region) == 0) {
|
||||||
|
//checksum failed
|
||||||
|
//NOTE: this patches bug #45, but does not resolve it
|
||||||
|
regionPager.UnloadIf([region](Region const& ref) -> bool {
|
||||||
|
//remove the erroneous region
|
||||||
|
return region == &ref;
|
||||||
|
});
|
||||||
|
SendRegionRequest(roomIndex, i, j);
|
||||||
|
std::ostringstream msg;
|
||||||
|
msg << "Existing region checksum failed: " << roomIndex << ", " << i << ", " << j;
|
||||||
|
throw(std::runtime_error(msg.str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,6 +70,7 @@ Region* RegionPagerBase::FindRegion(int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Region* RegionPagerBase::PushRegion(Region* const ptr) {
|
Region* RegionPagerBase::PushRegion(Region* const ptr) {
|
||||||
|
//BUG: #45 Some regions are occasionally losing their tile data
|
||||||
regionList.push_front(*ptr);
|
regionList.push_front(*ptr);
|
||||||
return ®ionList.front();
|
return ®ionList.front();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ end
|
|||||||
|
|
||||||
--custom generation systems here
|
--custom generation systems here
|
||||||
function mapMaker.DebugIsland(r)
|
function mapMaker.DebugIsland(r)
|
||||||
|
--debug
|
||||||
|
io.write("map_maker:DebugIsland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n")
|
||||||
|
|
||||||
--basic distance check for each tile, placing an island around the world origin
|
--basic distance check for each tile, placing an island around the world origin
|
||||||
for i = 1, regionAPI.GetWidth(r) do
|
for i = 1, regionAPI.GetWidth(r) do
|
||||||
for j = 1, regionAPI.GetHeight(r) do
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
@@ -95,6 +98,9 @@ function mapMaker.DebugIsland(r)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function mapMaker.DebugGrassland(r)
|
function mapMaker.DebugGrassland(r)
|
||||||
|
--debug
|
||||||
|
io.write("map_maker:DebugGrassland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n")
|
||||||
|
|
||||||
--all dirt
|
--all dirt
|
||||||
for i = 1, regionAPI.GetWidth(r) do
|
for i = 1, regionAPI.GetWidth(r) do
|
||||||
for j = 1, regionAPI.GetHeight(r) do
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ local mapSaver = {}
|
|||||||
|
|
||||||
function mapSaver.Load(r)
|
function mapSaver.Load(r)
|
||||||
--empty
|
--empty
|
||||||
io.write("map_saver:Load(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
-- io.write("map_saver:Load(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
||||||
end
|
end
|
||||||
function mapSaver.Save(r)
|
function mapSaver.Save(r)
|
||||||
--empty
|
--empty
|
||||||
io.write("map_saver:Save(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
-- io.write("map_saver:Save(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
--TODO: (3) create a flexible saving & loading system
|
--TODO: (3) create a flexible saving & loading system
|
||||||
|
|||||||
@@ -31,6 +31,6 @@ local underworld, uidTwo = roomManagerAPI.CreateRoom("underworld", "overworld.bm
|
|||||||
roomAPI.Initialize(underworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugGrassland, mapSaver.Save)
|
roomAPI.Initialize(underworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugGrassland, mapSaver.Save)
|
||||||
|
|
||||||
--call the monstrosity
|
--call the monstrosity
|
||||||
doorUtility.createDoorPair("pair 1", overworld, 0, -64, underworld, 0, 0)
|
doorUtility.createDoorPair("pair 1", overworld, -64, -64, underworld, 64, 64)
|
||||||
|
|
||||||
print("Finished the lua script")
|
print("Finished the lua script")
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//TODO: (9) character collisions should be preformed client-side
|
||||||
void RoomData::RunFrame() {
|
void RoomData::RunFrame() {
|
||||||
//get the hook
|
//get the hook
|
||||||
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
//utility functions
|
//utility functions
|
||||||
#include "sql_tools.hpp"
|
#include "sql_tools.hpp"
|
||||||
#include "userdata.hpp"
|
|
||||||
|
|
||||||
//std & STL
|
//std & STL
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -79,11 +78,6 @@ void ServerApplication::Init(int argc, char* argv[]) {
|
|||||||
|
|
||||||
std::cout << "Initialized lua" << std::endl;
|
std::cout << "Initialized lua" << std::endl;
|
||||||
|
|
||||||
//create the userdata metatable
|
|
||||||
createUserdataMetatable(luaState);
|
|
||||||
|
|
||||||
std::cout << "\tCreated userdata metatable" << std::endl;
|
|
||||||
|
|
||||||
//append config["dir.scripts"] to the module path
|
//append config["dir.scripts"] to the module path
|
||||||
if (config["dir.scripts"].size() > 0) {
|
if (config["dir.scripts"].size() > 0) {
|
||||||
//get the original path
|
//get the original path
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
|
||||||
* including commercial applications, and to alter it and redistribute it
|
|
||||||
* freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
* claim that you wrote the original software. If you use this software
|
|
||||||
* in a product, an acknowledgment in the product documentation would be
|
|
||||||
* appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
* misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source
|
|
||||||
* distribution.
|
|
||||||
*/
|
|
||||||
#include "userdata.hpp"
|
|
||||||
|
|
||||||
#define METAMETA "__metameta"
|
|
||||||
|
|
||||||
static int index(lua_State* L) {
|
|
||||||
//get __metameta
|
|
||||||
lua_getmetatable(L, 1); //get the userdata metatable
|
|
||||||
lua_pushstring(L, METAMETA); //push the __metameta name
|
|
||||||
lua_gettable(L, -2); //get the __metameta field from the metatable
|
|
||||||
|
|
||||||
//get __metameta[userdata]
|
|
||||||
lua_pushvalue(L, 1); //copy of the userdata
|
|
||||||
lua_gettable(L, -2); //get the table at __metameta[userdata]
|
|
||||||
|
|
||||||
//table doesn't exist yet
|
|
||||||
if (lua_isnil(L, -1)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get the value at __metameta[userdata][key]
|
|
||||||
lua_pushvalue(L, 2); //copy the key
|
|
||||||
lua_gettable(L, -2); //get value from the deepest table
|
|
||||||
|
|
||||||
//return
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int newindex(lua_State* L) {
|
|
||||||
//get __metameta
|
|
||||||
lua_getmetatable(L, 1); //get the userdata metatable
|
|
||||||
lua_pushstring(L, METAMETA); //push the __metameta name
|
|
||||||
lua_gettable(L, -2); //get the __metameta field from the metatable
|
|
||||||
|
|
||||||
//get __metameta[userdata]
|
|
||||||
lua_pushvalue(L, 1); //copy of the userdata
|
|
||||||
lua_gettable(L, -2); //get the table at __metameta[userdata]
|
|
||||||
|
|
||||||
//if this table doesn't exist yet
|
|
||||||
if (lua_isnil(L, -1)) {
|
|
||||||
lua_pop(L, 1); //pop nil
|
|
||||||
|
|
||||||
lua_pushvalue(L, 1); //copy userdata (key)
|
|
||||||
lua_createtable(L, 0, 0); //new table (value)
|
|
||||||
lua_settable(L, -3); //create the new table in __metameta
|
|
||||||
|
|
||||||
lua_pushvalue(L, 1); //copy userdata (key)
|
|
||||||
lua_gettable(L, -2); //get the newly created table
|
|
||||||
}
|
|
||||||
|
|
||||||
//set the value at __metameta[userdata][key] = value
|
|
||||||
lua_pushvalue(L, 2); //copy the key
|
|
||||||
lua_pushvalue(L, 3); //copy the value
|
|
||||||
lua_settable(L, -3); //set value in the deepest table
|
|
||||||
|
|
||||||
//return
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static luaL_Reg metatable[] = {
|
|
||||||
{"__index", index},
|
|
||||||
{"__newindex", newindex},
|
|
||||||
{nullptr, nullptr}
|
|
||||||
};
|
|
||||||
|
|
||||||
int createUserdataMetatable(lua_State* L) {
|
|
||||||
//create the userdata metatable
|
|
||||||
lua_pushlightuserdata(L, nullptr); //anon userdata
|
|
||||||
lua_createtable(L, 0, 0); //table
|
|
||||||
|
|
||||||
//insert meta-metatable
|
|
||||||
lua_pushstring(L, METAMETA);
|
|
||||||
lua_createtable(L, 0, 0);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
|
|
||||||
//insert metatable blocker
|
|
||||||
lua_pushstring(L, "__metatable");
|
|
||||||
lua_createtable(L, 0, 0);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
|
|
||||||
//insert metamethods
|
|
||||||
for (luaL_Reg* it = metatable; it->name; it++) {
|
|
||||||
lua_pushstring(L, it->name);
|
|
||||||
lua_pushcfunction(L, it->func);
|
|
||||||
lua_settable(L, -3);
|
|
||||||
}
|
|
||||||
|
|
||||||
//set in the object & pop the anon userdata
|
|
||||||
lua_setmetatable(L, -2); //set the metatable for userdata
|
|
||||||
lua_pop(L, 1); //pop the anon userdata
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
|
||||||
* including commercial applications, and to alter it and redistribute it
|
|
||||||
* freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
* claim that you wrote the original software. If you use this software
|
|
||||||
* in a product, an acknowledgment in the product documentation would be
|
|
||||||
* appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
* misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source
|
|
||||||
* distribution.
|
|
||||||
*/
|
|
||||||
#ifndef METATABLES_HPP_
|
|
||||||
#define METATABLES_HPP_
|
|
||||||
|
|
||||||
#include "lua.hpp"
|
|
||||||
|
|
||||||
int createUserdataMetatable(lua_State* L);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user