Compare commits

..

224 Commits

Author SHA1 Message Date
Kayne Ruse 93c41bb19c Merge branch 'develop'; major refactoring complete (read more)
Streamlined the build process, including:
* Restructured the common directory
* Moved the client's scenes up one level
* Removed the unused DEBUG flag, added the GRAPHICS flag
* Moved the server's data structures to the common/gameplay directory
* Data structures are now shared by the client and server

Other changes include:
* Created the StatisticData structure
* Removed the server's static variables
* Some progress on basic combat system framework
* CharacterData now has methods (derived from the delete PlayerCharacter)
* Client-side tables are now shared between the scenes
* Refactored UDPNetworkUtility, tying it to SerialPacket
* Added new structures to SerialPacket, and serialization
* Renamed and rearranged the SQL tables
* Solved a few other TODO tags
* Updated the license headers
2014-05-29 00:28:55 +10:00
Kayne Ruse bf922ec598 Updated the license headers
It only took me 5 months.
2014-05-29 00:16:49 +10:00
Kayne Ruse de902d2d3d Bumped the network version 2014-05-28 23:39:31 +10:00
Kayne Ruse 7b3bf24e5d Refactored UDPNetworkUtility, and tied it to SerialPacket 2014-05-28 23:22:00 +10:00
Kayne Ruse de7da81102 Solved a few items on the TODO list 2014-05-28 22:16:36 +10:00
Kayne Ruse 6428b02d85 Refactored some code from InWorld into methods in CharacterData 2014-05-28 21:25:52 +10:00
Kayne Ruse 519b8a1e36 Entire project is building cleanly again, but characters are static 2014-05-28 00:50:14 +10:00
Kayne Ruse 967f0653a1 Threaded the tables through the scenes 2014-05-27 23:59:42 +10:00
Kayne Ruse b86d393571 Moved the scenes up one directory level, subdirs no longer needed 2014-05-27 23:28:29 +10:00
Kayne Ruse 6b38501c27 Added the GRAPHICS flag, to simplify the gameplay structures 2014-05-27 23:25:07 +10:00
Kayne Ruse 5893342ad8 Removed the shared parameters structure (read more)
I've also stopped using a separate branch for sharing the CharacterData
structre. This commit won't build, mostly because I need to refactor
InWorld to handle the loss of the PlayerCharacter class.

I should probably rename SQL's tables too.
2014-05-27 22:27:30 +10:00
Kayne Ruse ac4a264f12 Merge branch 'dev-charshare' into develop (read more)
Using several branches never really works out well for me. I'm merging
these changes back into develop, because I want to undo the shared
parameters change, but that's tied up with something else. It's just
easier if I do this.
2014-05-27 21:44:55 +10:00
Kayne Ruse 43895a462a Merge branch 'dev-charshare' (early part) into develop (read more)
Moved the server's containers into the common directories, and removed the
server's static members.

This commit does build, but the next commit in 'dev-charshare' won't so
I'm merging this while I can.
2014-05-26 18:38:21 +10:00
Kayne Ruse 1bde0ed3f7 Began unifying the server and client side character classes
This commit won't build
2014-05-26 18:36:09 +10:00
Kayne Ruse d903c0df30 Removed the UID counters from the data containers 2014-05-26 17:42:55 +10:00
Kayne Ruse 9620826d65 Moved the server's data containers into common/gameplay 2014-05-26 17:29:15 +10:00
Kayne Ruse 0a71f43ef3 Implemented SharedParameters system in the client (read more)
Here are more tweaks:
* InWorld's quit event now exits to the main menu, bypassing a relayed disconnect message
* InWorld's disconnect hander no longer throws exceptions (dropped creation packet bugfix)
* CombatData's internals now point to std::pair objects
* Enemies are stored in a global list
2014-05-26 17:11:26 +10:00
Kayne Ruse a47e76845f Removed common/ from the build process, and the DEBUG flag
The common/ directory is empty, only containing more directories to be
built, and the DEBUG flag isn't being used.
2014-05-26 02:21:56 +10:00
Kayne Ruse c2eb08bd5e Restructured the common/ directory, and simplified the build process 2014-05-26 02:10:12 +10:00
Kayne Ruse 7b76e07231 Hooked up the new serial code, nothing broke 2014-05-26 01:08:10 +10:00
Kayne Ruse 1dd8042d3d Added some structures to SerialPacket, and serial.cpp
I've also created the Statistics structure for simplicity.
2014-05-26 00:49:31 +10:00
Kayne Ruse c575ee9ce1 Committing todo.txt 2014-05-24 01:48:35 +10:00
Kayne Ruse 1befc76b70 Merge branch 'develop' (read more)
Deleted in the merge:
* combat_management.cpp
* todo.txt

Amended in the merge:
* server/enemy_factory_interface.hpp
* server/server_application.hpp
* server/server_internals.cpp

That version of combat_management.cpp was not what I was looking for. I'll
try again, this time by working my way down from SerialPacket. It's worked
in the past as far as establishing a standard goes.

todo.txt was deleted in this commit, but will be carried over into the
next develop branch.

I'll release a new demo build without changing the version number, since
there are no functional changes.
2014-05-24 01:24:57 +10:00
Kayne Ruse 6a6e7f7125 Adjusted the README and tweaked some notes 2014-05-19 20:04:17 +10:00
Kayne Ruse bb6e248583 Implemented EnemyFactory, still empty 2014-05-18 03:45:36 +10:00
Kayne Ruse f7df4fba6c Wrote some basic combat management code 2014-05-18 01:48:22 +10:00
Kayne Ruse e7403be508 Minor tweak to CombatInstance 2014-05-17 02:33:02 +10:00
Kayne Ruse 873715b28c Added the "speed" statistic 2014-05-16 17:56:40 +10:00
Kayne Ruse b1d6e5a314 Mostly planning 2014-05-16 02:05:52 +10:00
Kayne Ruse f0453375c4 Stating to implement the combat system 2014-05-16 00:01:05 +10:00
Kayne Ruse e5a98efd7d Merge branch 'develop' (bugfix, read more)
Found an error in the SQL save statements; fixed.

Character positions are now saved between logins.
2014-05-13 04:37:33 +10:00
Kayne Ruse 14b330009b BUGFIX: Found an error in SQL save statements
The character's positions are now persistent between logins.
2014-05-13 04:36:59 +10:00
Kayne Ruse 288b62d3f8 Merge branch 'develop' 2014-05-13 03:26:13 +10:00
Kayne Ruse c5e8f1b3af Added account and character saving on shutdown 2014-05-13 03:25:50 +10:00
Kayne Ruse 980717f9fd Merge branch 'develop' 2014-05-13 03:01:26 +10:00
Kayne Ruse 68475eee0f Created PumpCharacterUnload 2014-05-13 02:51:50 +10:00
Kayne Ruse eeb2400e79 Rearranged the server-side object hierarchy (read more)
This has been a long-running problem for days, but I've finally
implemented a correctly working hierarchy between the ClientData,
AccountData and CharacterData objects:

CharacterData -> AccountData -> ClientData

There doesn't seem to be any issues with it right now, touch wood.
2014-05-13 02:09:00 +10:00
Kayne Ruse 01244005e9 Minor file renaming and tweaks 2014-05-13 00:23:04 +10:00
Kayne Ruse c5005b9b07 Merge branch 'develop' 2014-05-12 22:40:21 +10:00
Kayne Ruse 80a26341b1 Finished the character management, but it needs testing. 2014-05-11 20:13:27 +10:00
Kayne Ruse b7877962f1 Implemented CreateCharacter() and LoadCharacter() (read more)
There are issues with the indexes. That is, the accounts and the
characters need each other's indexes upon creation. I'll need to rectify
this now.
2014-05-10 20:30:33 +10:00
Kayne Ruse 688d064085 Merge branch 'database'
Conflicts:
	todo.txt

Merging todo.txt into the master branch, despite trying to keep it
separate.
2014-05-07 21:12:22 +10:00
Kayne Ruse 1c4d53e3ef Updated TODO, might as well merge this into the master 2014-05-07 21:07:42 +10:00
Kayne Ruse a53a134163 Merge branch 'account'
Added the "accountIndex" variable to the SerialPacket.
2014-05-07 20:55:43 +10:00
Kayne Ruse 4d12788c53 Finished the server-side modifications (read more)
* There seems to be something iffy with this branch
* The size of SerialPacket may have changed

I've implemented the accountIndex variable as best I can, but I really
shouldn't code at night. I'll need to go over the changes again before
merging this.
2014-05-07 20:55:09 +10:00
Kayne Ruse 1beb7cbd5d Began adding basic authentication 2014-05-06 21:35:07 +10:00
Kayne Ruse 8358d72a98 Merge branch 'database' (read more)
* Implemented user accounts.
* Other minor tweaks

I think the general "clientIndex" variable needs to be changed to
"accountIndex", since this will allow for much easier authentication.
2014-05-06 19:21:52 +10:00
Kayne Ruse 4ebff4a25a Minor tweaks, prepping for a merge 2014-05-06 19:18:53 +10:00
Kayne Ruse 0ff787abda Added Unloading and Deletion of user accounts 2014-05-06 18:57:49 +10:00
Kayne Ruse 9b5b48a8ab Implemented saving of user accounts (read more)
To modify an existing user account, change the in memory copy and then
call the function SaveUserAccount(uid), where uid is the index of the
modified account. If the save function is not called immediately, then the
behaviour of the server is undefined.
2014-05-06 18:33:20 +10:00
Kayne Ruse 5dd0fb9e23 BUGFIX: Signal when a duplicate account is being loaded
If a duplicate account is being created or loaded then the functions
return -1. The higher code can take it from there.
2014-05-06 16:41:08 +10:00
Kayne Ruse 7c210e04a5 Switched to using a wildcard symbol 2014-05-06 00:17:50 +10:00
Kayne Ruse 9236e02101 Merge branch 'master' into database (read more)
Conflicts:
	todo.txt (kept)

Just merging the editor's deletion into this branch, nothing else major.
2014-05-06 00:08:06 +10:00
Kayne Ruse 8f4ebf20da Removed the editor, since it isn't currently needed 2014-05-06 00:07:02 +10:00
Kayne Ruse 910e51f637 Began to implement user accounts using the database
I'm mostly just testing the waters at this stage, and i've left some debug
code in. There's no way to unload, delete, etc. the accounts, but that
comes later.
2014-05-05 23:57:07 +10:00
Kayne Ruse 92fc9b4e25 Adjusted the lua's map API, requiring a large rewrite
One the whole nothing major has changed, but I think this makes things
more logical. I just hope its stable, since I'm releasing a new tag.
2014-04-29 15:53:04 +10:00
Kayne Ruse 2b8e7241c9 Merge branch 'tweaks'; nothing major 2014-04-29 13:12:39 +10:00
Kayne Ruse 124cb3ad13 Did some renaming and comment tweaks 2014-04-29 06:34:23 +10:00
Kayne Ruse 6d3400d948 Merge branch 'network' (read more)
I've refactored the network layout. Here is a brief list of changes:

* The new player object is created server-side rather than client-side
* serial.cpp now uses macros to prevent hard-to-find logic errors
* A few method definitions have been re-ordered
* SerialPacket's internals have been slightly changed
* SerialPacket now carries a datestamp defining the network protocol
* server_application.cpp has been split into two separate files
* HandleJoinRequest() has been modified to create the new player object
2014-04-29 02:14:25 +10:00
Kayne Ruse 5031352fe3 Fixed the bug (read more)
The bug was being caused by a lack of a new player object being sent to
some clients. Fixed this by adding in the sending code, and preventing the
new entries being "registered" until the end of the HandleJoinRequest()
method.

Hopefully I can simply abstract away some of this code soon.
2014-04-29 01:47:01 +10:00
Kayne Ruse 624369f147 Discovered a bug 2014-04-27 22:46:19 +10:00
Kayne Ruse 9a7f7b8684 Rewrote the TODO list 2014-04-27 03:55:44 +10:00
Kayne Ruse fa9487c2f2 Fixed the previous bug (read more)
The bug was being caused by not assigning default values to the player
objects' internals. I've added a quick fix to these structs, but I think
it's best to expand them into proper classes now.
2014-04-27 02:37:20 +10:00
Kayne Ruse 9ec1ddab99 Exceptions are being thrown; retiring for the night
I don't know what's causing these issues, so I'm leaving it for tonight.
2014-04-26 02:48:15 +10:00
Kayne Ruse 6f1c2d0555 Merge branch 'fragmented-server' into network (read more)
I've divided the server's source into several different files. This should hopefully make it a bit easier to manage.

Please note that I do know there's an exception being thrown by the client
in this build.
2014-04-26 02:34:17 +10:00
Kayne Ruse 01b50d5590 I guess it was easier to compile the fragmented server than I thought 2014-04-26 02:31:48 +10:00
Kayne Ruse 9c673928e6 Began segmenting the server's code
I've created a separate branch for this because it's gonna be a bitch to
get compiled, and then I'll still have to ensure that the client & server
are work together correctly.

This build does not compile.
2014-04-26 02:09:32 +10:00
Kayne Ruse d55dfb90e4 Worked the new protocol into the client (read more)
I've added the handle and avatar fields back into the PlayerInfo section
in the network code, because I need to be able to load a specific file
when a new player is created. This wasn't forseen, but it's fine. i'm
leaving the fields in ClientInfo as well, because LobbyMenu is using them
to login to the server.

PlayerIndex is now a shared parameter.

I've shifted some code around in InWorld, however the overall logic is the
same.

This build (as well as the last) does not compile.
2014-04-26 01:05:31 +10:00
Kayne Ruse 235a05d006 Rearranged the SerialPacket and serialization code
The serialization code is now using macros to simplify each line, and to
prevent errors. It should be noted that, apart from the region content,
the serialization and deserialization code is essentially identical.
2014-04-25 23:50:19 +10:00
Kayne Ruse dabb7b3b2e Compiled a list of tasks
The list in todo.txt are a list of tasks that will be needed to complete
the login/user accounts overhaul, and will hopefully make the server a
persistent system.

Once the server is persistent (via the database) I can start on the combat
system.
2014-04-22 01:55:09 +10:00
Kayne Ruse e756289c2b Adjusted a few comments 2014-04-22 01:54:26 +10:00
Kayne Ruse c534158c2e Merge branch 'login' (read more)
This branch was originally intended to rewrite the login system, but I've discovered some serious problems that could not wait. See the previous commit for more information. Hopefully I can get back to this soon.

I believe this version deserves a new release tag.
2014-04-21 04:00:37 +10:00
Kayne Ruse b47191a0c1 Fixed a horrible region coordinate bug
Coordinates are supposed to be stored by their x & y, but the sizes of the
tile sheets were getting mixed in as well. When trying to store a region
at (0, 20), it was being stored at (0, 260).

Another visual bug inside the tile sheet's rendering function masked this
issue until now.

Another thing to note is that I've removed an incredibly complex system
for updating the client's map. The new system may seem complex at first,
but it is straight forward compared to what it replaced.

I've also fixed a few logarithmic lagging points in the code.
2014-04-21 03:56:48 +10:00
Kayne Ruse 6c6a025f2a Adjusted a few comments 2014-04-21 02:13:00 +10:00
Kayne Ruse 60edc97ea5 Added rejections for incompatible servers 2014-04-21 01:38:28 +10:00
Kayne Ruse a5b209d9e0 Merge branch 'login' (read more)
Made a few tweaks to the code, but the build still works, so I'm merging it into master.
2014-04-21 01:02:38 +10:00
Kayne Ruse fd673a415f Removed singleton pattern 2014-04-21 01:01:00 +10:00
Kayne Ruse 4270765146 Renamed NetworkPacket to SerialPacket, updated build 2014-04-20 23:54:59 +10:00
Kayne Ruse f56cb58dfb Revised SQL setup script, and the script function 2014-04-20 23:11:46 +10:00
Kayne Ruse f315f4bf35 Merge branch 'map' (read more)
After refactoring the map system, this new build uses the preprocessor macros to define the sizes of each region object. These macros, which are defined in region.hpp, were being used anyway; these modifications simply speed up the process by cutting out a lot of the fat.
2014-04-20 05:41:49 +10:00
Kayne Ruse 69765de433 Removed the TODO file; I think it's fairly stable again 2014-04-20 05:34:15 +10:00
Kayne Ruse 35d463d4ba Removed some annoying debugging messages 2014-04-20 05:30:08 +10:00
Kayne Ruse 894b46c5db Found the error in the format functor
I shouldn't automatically guess where an error is, since this project is
so complex.
2014-04-20 05:14:25 +10:00
Kayne Ruse eb0b18af6f Brought the programs into line, (BUG, read more)
It seems that the serialization code has a bug in it. I was expecting
something like this. When the server tries to send the region content, it
exits. I'll try and find the cause of the error, but I'm committing my
changes anyway.
2014-04-20 04:41:06 +10:00
Kayne Ruse fba183fa27 Brought the common/ directory up to date with the region's preprocessors
I really hope the serialization code still works.
2014-04-20 04:02:26 +10:00
Kayne Ruse c5a627004a Refactored the map system (read more)
The region's width, height and depth are all defined by preprocessor
macros. The rest of the map system has been updated to match. The
programs proper need to be updated as well. It would be a good idea to
include the macros' values as part of the initial communication protocols,
so that the clients don't connect to a server that is using the wrong
sized regions.
2014-04-20 03:41:08 +10:00
Kayne Ruse ac27fb0ca7 Found a list of TODO comments 2014-04-20 02:40:06 +10:00
Kayne Ruse be4a8311d5 Adjusted a few comments 2014-04-20 02:39:29 +10:00
Kayne Ruse 6d32d44fa3 Reverted some of the changes, stable 2014-04-15 23:23:15 +10:00
Kayne Ruse 9bacfb1424 Merge branch 'entity' (early part) (read more)
I've had some issues with the entity system I created, so I'm trying to
revert it right now, while also retaining the other few tweaks I've made.
2014-04-15 22:40:07 +10:00
Kayne Ruse c3464be589 The server is working correctly, using the entity system 2014-04-13 22:20:30 +10:00
Kayne Ruse 7fe71c60d0 This will not build; working on refactoring 2014-04-13 03:49:35 +10:00
Kayne Ruse 0c6537fb36 Began work on the server's generic entity system 2014-04-13 03:02:26 +10:00
Kayne Ruse 854dc0eb45 Added a link to the stable build 2014-04-08 21:24:49 +10:00
Kayne Ruse e90afb7e4a Merge branch 'net-map' 2014-04-08 21:13:17 +10:00
Kayne Ruse 0453f6becf The map paging is functional 2014-04-07 02:56:48 +10:00
Kayne Ruse c8a58ab515 Wrote a potentially buggy algorithm
This algorithm is designed to find the distance of a certain region,
however it may have been better to do a quick check, rather than worrying
how many regions were loaded at once.
2014-04-07 01:24:05 +10:00
Kayne Ruse 553f8dbfa5 Fixed some framerate issues 2014-04-06 20:53:51 +10:00
Kayne Ruse 2bacdcdab7 The basic server map is being displayed in the client 2014-04-06 03:38:58 +10:00
Kayne Ruse 99aecbfdbb The client->server->client region protocol is working 2014-04-06 02:48:43 +11:00
Kayne Ruse 27bda5dc28 Working on the client side map code (read more)
I've also added in some debug code to the map classes, because I was
hunting down a std::bad_alloc beingthrown. Turns out I forgot to set the
map sizes in the client's InWorld constructor. I'm committing the fix, and
the debug code.
2014-04-06 02:25:55 +11:00
Kayne Ruse 962f3f5dd0 Added "camera" 2014-04-05 01:56:05 +11:00
Kayne Ruse 41077b43b3 Merge branch 'network-map' 2014-03-31 21:54:22 +11:00
Kayne Ruse 4410ab892f Finished the region serial code 2014-03-31 21:40:50 +11:00
Kayne Ruse 60000cb0cf Minor tweak 2014-03-31 03:38:05 +11:00
Kayne Ruse 66b00255d5 Merge branch 'lua-api' into network-map 2014-03-31 01:32:39 +11:00
Kayne Ruse a5b68cf1fd Expaneded the lua API for Regions
I've added lua hooks for both pager functor classes. Hopefully, I haven't
missed any corner cases, because it took me a while to hunt everything
down. One issue is that the map's save directory needs to be set in the
Format class, but it'll do for now. I'll review this again when I've got
more than one map running at one time.

There should be enough here for a lua-driven map generator to be
implemented, even if it's a bit rough. I think I'll test this out in the
editor eventually, but getting the base branch's network map code going
comes first.

The current process is extremely convulted, so I need to document
everything that I've done so far, including C++ and lua functions.
2014-03-31 01:30:11 +11:00
Kayne Ruse 4cff57fe71 Established a connection between the Region objects and lua 2014-03-28 04:11:34 +11:00
Kayne Ruse 38b603fc8f Began working on the lua API for the map
The basic framework is done.
2014-03-28 03:24:14 +11:00
Kayne Ruse 47684380a9 I'm having trouble with the sequence of events 2014-03-26 00:30:10 +11:00
Kayne Ruse e4bfbfb906 Minor code tweaks, this needs a lot of forethought 2014-03-16 00:28:19 +11:00
Kayne Ruse 9db86c19f6 Implemented a macro for the serial buffer size 2014-03-15 23:36:31 +11:00
Kayne Ruse d5b551cec3 Reduced the footprint of the tiles
Also prepping for serializing the regions.
2014-03-15 23:02:21 +11:00
Kayne Ruse 7e500027e3 Loosened the requirements for constructing a MapPager
This is so that I can configure the size of the pages in the config.cfg
file.
2014-03-15 19:16:42 +11:00
Kayne Ruse dd786ba579 Merge branch 'server' (read more)
The only different between this commit and the currently stable branch is the
serialization code and a slight tweak to the server's startup sequence. I tried
to refactor the server, by moving the clientMap and playerMap into their own
wrapper classes, but that failed miserably. I need to stop getting so worked up
all the time, I've wasted way too much time already.
2014-03-11 19:04:32 +11:00
Kayne Ruse 5a57888305 Fixed the crash bug 2014-03-11 18:54:06 +11:00
Kayne Ruse 706aa5e1d7 Another worthless tweak 2014-03-10 23:56:47 +11:00
Kayne Ruse 19c1b1197d Added a brand new bug, I hate this branch 2014-03-10 23:15:57 +11:00
Kayne Ruse 5cf62f5517 Nothing special, just commiting minor changes 2014-03-09 01:51:17 +11:00
Kayne Ruse 56d02ad8d4 Working on reimplementing the player characters
I've also added EraseIf() to the manager classes.
2014-03-07 22:09:50 +11:00
Kayne Ruse 006a72174f Merge branch 'master' into server 2014-03-07 21:05:09 +11:00
Kayne Ruse 0cbc9dd9db Merge branch 'serial' into server (read more)
Conflicts:
	server/server_application.cpp (resolved)

After completing the serialization code, I'm merging it into the server's
development branch. This means that although the connection and
disconnection functionality work, I still need to test the player systems
from the new server with the new serialization code.

Immediately following this commit, I'll be merging the minor tweaks to the
editor from the master branch into this one.
2014-03-07 20:58:37 +11:00
Kayne Ruse 60c31ff56d Slight code tweak 2014-03-07 20:27:34 +11:00
Kayne Ruse 6a204643f6 Serialization is finally functional 2014-03-07 20:17:11 +11:00
Kayne Ruse 59285d1630 This isn't fucking working 2014-03-07 04:49:16 +11:00
Kayne Ruse a850d6b1af Added dummy serialization functions 2014-03-06 00:20:31 +11:00
Kayne Ruse f17fa0f345 Added lua, added db connection to PlayerManager
I've also revised the startup process a bit.
2014-03-05 00:27:21 +11:00
Kayne Ruse 756d4e770d Connection and disconnection are working correctly
I've dummied out the player code, so only the client connection code is
working. Otherwise the protocol hasn't changed.

I've also made a few other tweaks as I went along, but nothing really
major.
2014-03-04 02:48:47 +11:00
Kayne Ruse 7bb5e8ce0d Moving client and player data into manager classes
Remember: anything with "manager" in its name organizes a number of other
objects, as far as I'm concerned.

I'll eventually have a database connection in the PlayerManager class;
this'll make it easier to manage the database.
2014-03-02 23:20:37 +11:00
Kayne Ruse 975533afba Minor tweak to the editor's menu bar 2014-03-01 23:58:06 +11:00
Kayne Ruse 19749f7c87 Added grey highlighting to the debug text 2014-03-01 03:31:46 +11:00
Kayne Ruse 7703c4b0ad Merge branch 'master' into stable
Even though some parts of the new map system are a stub, I feel confident
enough to merge this branch back onto the stable branch.

On the whole, I've reduced the complexity of the system, while also allowing
acceptable restrictions.

The RegionPager class works correctly. The Update() member is empty, but it's
still usable.

I've removed TileSheetManager, so the maps can only have one tileset each;
that's fine.

The tiles are voxel integers.

The editor needs an entire overhaul. I think some of the GUI components
are too complex. The sooner I can implement the map in the main
client/server system the better.
2014-03-01 00:48:19 +11:00
Kayne Ruse dc8f594eec Tested RegionPager, removed trace statements, fixed logic errors 2014-03-01 00:39:39 +11:00
Kayne Ruse 4629b7302b Fixed Region's internals 2014-02-28 23:14:22 +11:00
Kayne Ruse 02d83d1f16 BUG: Region's memory isn't being zeroed by the looks of it 2014-02-28 03:41:03 +11:00
Kayne Ruse 91c9cef56d Working on the TileSheet class 2014-02-28 03:40:18 +11:00
Kayne Ruse f7d4912942 Merge branch 'stable' 2014-02-24 01:41:40 +11:00
Kayne Ruse eb8674b84f Moved the technical document 2014-02-24 01:41:21 +11:00
Kayne Ruse ff44e4d916 Merge branch 'stable' 2014-02-24 01:14:16 +11:00
Kayne Ruse e66540f114 Updated README 2014-02-24 01:12:42 +11:00
Kayne Ruse 639c0c70e3 RegionPager can now be instanciated with template parameters
* Fixed Region::GetX() and Region::GetY()
* Replaced calls to std::find_if with regular for loops
* Changed typing of RegionPager::regionList
** regionList now holds pointers rather than the objects themselves
* Added vestigial classes MapFileFormat and MapGenerator
** MapGenerator creates and destroys the region objects
* I'm leaving in the debugging code for now
** This includes trace statements and a basterdized main() function in
/editor/main.cpp
2014-02-24 00:34:02 +11:00
Kayne Ruse 37b02352e2 Fleshed out inherited functions
TODO:
* RegionPagerBase::Update() is a stub
* MapFileFormat
* MapGenerator
* Can replace the calls to std::find_if() with a utility function
2014-02-23 03:08:37 +11:00
Kayne Ruse 31c8bd7fd2 Split the pager class into two
I've also made the base class abstract, and the derived class a template.
Hopefully this'll let me work on different parts of the class without
major issues.

This code compiles, but since it's incomplete, I can't test it properly.
2014-02-21 03:42:02 +11:00
Kayne Ruse 808fe570a3 Added empty RegionPager 2014-02-18 01:18:04 +11:00
Kayne Ruse e706cc9d13 Completed a simple region class 2014-02-15 20:06:20 +11:00
Kayne Ruse eb02cc4b6a Removed the old map system from the editor 2014-02-11 21:56:45 +11:00
Kayne Ruse 31cca61d1c Added position data to player objects 2013-12-31 02:25:16 +11:00
Kayne Ruse 071e0d9021 I'm sick of multithreading.
I'm also sick of bastards on the internet.
2013-12-30 14:11:44 +11:00
Kayne Ruse a494bfbb38 Fixed horrible naming convention 2013-12-25 22:09:59 +11:00
Kayne Ruse baadf554cd BUGFIX: Solved server failure
Cause:

server/server_application.cpp: line 93

The last argument to std::pair was simply a call to WorldRoom's
contructor. This created a temporary object that fufilled this line, but
after the new std::pair object was added to worldRoomMap, this WorldRoom
object went out of scope.

server/server_application.cpp: line 96

When OpenRoom() was called using an object that was out of scope, the
entire server simply failed.

Solution:

Changed worldRoomMap to hold a pointer to a WorldRoom object, rather than the
object itself. The new and delete operators should be used to create and
delete WorldRoom objects respectfully.
2013-12-14 00:23:20 +11:00
Kayne Ruse 9df16fede0 WARNING: Server fails on startup
For some reason, when trying to initiate the room thread, the entire
server simply fails. There is no crash, no error message, or anything. I
have no idea what's wrong.
2013-12-11 22:22:01 +11:00
Kayne Ruse dd0ad31ac6 Tweaked README.md 2013-12-11 18:54:51 +11:00
Kayne Ruse be26c9d103 Started working on multithreaded rooms 2013-12-08 15:55:49 +11:00
Kayne Ruse a448c8fb68 Added the nightly build link to the readme 2013-12-07 03:28:41 +11:00
Kayne Ruse de1a6a050f Fixed jittery lag and client closing issues 2013-12-07 03:24:39 +11:00
Kayne Ruse 49c9abe91b Added controls, it's now MP capable 2013-12-07 02:36:48 +11:00
Kayne Ruse 3b05476689 Connections and disconnections are working across different clients 2013-12-07 01:33:27 +11:00
Kayne Ruse 1c032bfc47 Implemented client-side player creation; incomplete 2013-12-06 23:03:46 +11:00
Kayne Ruse 1a7457f650 Imported and refactored PlayerCharacter from the old branch 2013-12-06 21:00:35 +11:00
Kayne Ruse e640eda771 Moved client scenes to a sub directory, reworked build process 2013-12-06 20:22:55 +11:00
Kayne Ruse fc2b67608f Added new graphics stuff, adjusted build process 2013-12-06 18:29:55 +11:00
Kayne Ruse a3a990cc01 Added player support to the server
This code is essentially copied from the old branch, since the two
branches are now functionally identical. How much time have I wasted
rewriting this?
2013-12-06 17:47:03 +11:00
Kayne Ruse f6a4674a2f Moved networking code into high cohesion functions 2013-12-02 17:54:47 +11:00
Kayne Ruse 865620b4a8 Renamed some things, and removed Client::index 2013-12-01 18:36:18 +11:00
Kayne Ruse 1e0ed350fc Removed Multithreading, simplifying the server
Networking and multithreading working at the same time is really fucking
hard. It's better to just have the one thread, and not worry about speed
at this stage.
2013-12-01 15:21:00 +11:00
Kayne Ruse 6ccc874583 Implemented the log on and log off systems
This is a pretty straight forward port of the old version, including the
incredibly hacky server list. But I just need to remember that this is a
prototype.
2013-11-23 17:53:36 +11:00
Kayne Ruse ca86dc5fb8 Added a delay, to give the machine a rest 2013-11-23 01:25:49 +11:00
Kayne Ruse e3605e4dc5 The client is receiving the list of servers 2013-11-22 23:19:29 +11:00
Kayne Ruse cb9aef95ec Reworked NetworkQueue as a template class 2013-11-22 19:57:24 +11:00
Kayne Ruse 09f97de0e6 Added HandlePacket() to the lobby 2013-11-22 19:56:15 +11:00
Kayne Ruse f5466b9982 Added config based directories 2013-11-17 00:13:16 +11:00
Kayne Ruse e176a60d28 client to server contact 2013-11-16 23:46:59 +11:00
Kayne Ruse dc24d1b059 Committing the empty WorldRoom class 2013-11-13 02:03:25 +11:00
Kayne Ruse fa3fc18ddf Imported and updated ConfigUtility 2013-11-09 21:13:00 +11:00
Kayne Ruse c2941cd3e8 Moved the thread out of the NetworkQueue class 2013-11-09 20:04:06 +11:00
Kayne Ruse bf15a5d957 Minor tweak 2013-11-09 16:32:35 +11:00
Kayne Ruse f01463bab3 Added and tested the network queue in the server
This is a reimplementation of the old network queue, but using a class.
This still uses a separate thread, so that packets can wait if there's any
lag. Really, thinking about it, I wonder how necessary this was.

On the upside, no singletons this time. Which means that you can have
several instances of UDPNetworkManager. That's unintentional, but good to
know.
2013-11-03 00:22:41 +11:00
Kayne Ruse 54cd26b76f Removed a lot of rubbish from the server 2013-11-02 19:00:08 +11:00
Kayne Ruse 2bd8adaf69 Added an empty navigation shell to the client 2013-10-27 22:00:09 +11:00
Kayne Ruse 26eba2def6 Moved some common/* files into directories 2013-10-27 20:17:37 +11:00
Kayne Ruse 43852ce755 Hooked the two scenes together
What the hell am I doing?
2013-10-27 00:43:37 +11:00
Kayne Ruse 81fab06e3b Dummied out the load & save functions 2013-10-22 20:22:35 +11:00
Kayne Ruse 77a90f9c0c Slight refactoring 2013-10-22 20:19:09 +11:00
Kayne Ruse bc32f2a2f0 The editor scene now works correctly with the TileSheetManager 2013-10-22 19:43:20 +11:00
Kayne Ruse 76bfecd466 RegionPager now uses a reference to TileSheetManager 2013-10-22 19:35:24 +11:00
Kayne Ruse d4eb1e7b8d Checking in the test scene and test tilesets 2013-10-22 19:22:18 +11:00
Kayne Ruse 2ec307510d Revised TileSheet & TileSheetManager 2013-10-22 19:18:35 +11:00
Kayne Ruse 0b4e6003d6 Created the TileSheetManager class
This class will manage the large(ish) number of tile sheets for a specific
map.
2013-10-21 23:53:36 +11:00
Kayne Ruse 7e603ffa89 Moved the map systems into their own directory 2013-10-17 23:33:02 +11:00
Kayne Ruse 6fc8570cf4 Added the saving function 2013-10-17 23:10:43 +11:00
Kayne Ruse 0bfd916df4 Fixed inverted camera, and added RegionPager::Prune() 2013-10-17 22:18:42 +11:00
Kayne Ruse 88aee0f4f5 Created the loadGameMap() function, still incomplete
Although the overall logic of this function is finished, I still need to
write the callbacks for RegionPager's onNew and onDelete.

I've also tested this using a hand written save/index file. I've written
up a map file format by hand, and I'll be implementing it over the next
few commits.
2013-10-14 21:12:09 +11:00
Kayne Ruse 0d3c3243a0 Added a debug display 2013-10-11 20:07:57 +11:00
Kayne Ruse 871b1136c2 Pager and menu bar working together without interfering with each other 2013-10-11 01:14:02 +11:00
Kayne Ruse f64c935ffe Imported revamped GUI classes, moved map classes 2013-10-11 00:30:31 +11:00
Kayne Ruse 600ec6789b Removed debug code from the editor 2013-10-07 02:32:36 +11:00
Kayne Ruse 65a3937592 Imported the rsc/ folder from the old branch 2013-10-07 01:32:29 +11:00
Kayne Ruse 719c8f49a6 Added region highlighting 2013-10-06 19:22:26 +11:00
Kayne Ruse 29928c0b92 Added a draw function to the pager
I'm also committing some simple debugging code in the scene.
2013-10-04 02:18:10 +10:00
Kayne Ruse a88a1f7cf7 Systems are working correctly, but needs cleaning 2013-10-04 00:34:57 +10:00
Kayne Ruse 46efbfbe9a Forgot to add the license 2013-10-03 23:20:04 +10:00
Kayne Ruse 26ff8dcc8f Created RegionPager 2013-10-03 23:04:16 +10:00
Kayne Ruse 9c91e9d5fd Decoupled the TileSheet class from the Map class
I moved the rangeEnd variable into the TileSheet class, making it static.
I also tweaked the return types for a few functions in Region, and removed
the sheetIndex member from Tile.
2013-10-03 21:29:11 +10:00
Kayne Ruse 3628d3c1fd Finished the delcaration of the Map class
This is actually a lot harder than I was expecting. When I program, I
approach from the angle of "What do I need to do?" rather than "how do I do
this?" At least this is finally done, so I can get to the implementation
stage. But, as I progress, I'll need to keep in mind what I need for the
index file.

Actually, I just realized that I didn't write the index functions. Well,
it should be interesting, at least.
2013-10-01 23:02:46 +10:00
Kayne Ruse 6c9406147a Added width & height members to Tile, moved local functions to utility.*pp
I've added more members to the Tile structure, namely the width & height
of the tile. This is to fix a circular logic problem, which is too
abstract for this commit message ;)

I've also moved the local/static/inline/etc. utility functions to their
own module in the common directory, because this is just cleaner that
redefining the same code a dozen times.

The map's logic is still the same, but I need to keep moving; I've been
procrastinating far too much.
2013-10-01 21:46:34 +10:00
Kayne Ruse aae244de39 Code tweak 2013-09-25 21:27:00 +10:00
Kayne Ruse d5b14c2679 Created the TileSheet class
This is incomplete on it's own, but used as part of the whole map system,
it should work well. This class keeps track of various, seemingly
unrelated states, which are used as part of the larger map system.

Also, fixed Region's members being public.
2013-09-25 20:39:59 +10:00
Kayne Ruse a54fbfb9e9 Added static linking 2013-09-21 16:26:01 +10:00
Kayne Ruse 9cbbfe77b7 After some testing Region seems OK 2013-09-19 22:52:26 +10:00
Kayne Ruse 9b64c67068 Finished a prototype of Region, needs testing 2013-09-19 16:52:15 +10:00
Kayne Ruse de0227a1cf Demonstration of Tile & Region classes 2013-09-19 01:22:52 +10:00
Kayne Ruse 1dfeabf195 SDL_net is working 2013-09-09 12:15:26 +10:00
Kayne Ruse 6c5197f3f2 The server runs the setup scripts on startup 2013-09-05 23:02:48 +10:00
Kayne Ruse 09453cc24e Added lua and SQL, but removed lsqlite3.c
lsqlite3.c looked like a good idea for connnecting SQL and lua, but I
couldn't get it to work and rather than struggle on this, I'll write my
own library later on.
2013-09-05 20:08:50 +10:00
Kayne Ruse 4b62310158 Revised build process to include the common/ directory 2013-09-04 20:49:55 +10:00
Kayne Ruse 43f2190c3e Created the database setup script 2013-09-04 19:17:16 +10:00
Kayne Ruse 3225da6b13 Added client scenes 2013-08-31 03:27:11 +10:00
Kayne Ruse 0c233b8764 Added readme.md 2013-08-29 21:55:09 +10:00
Kayne Ruse 027d0125ef Boilerplate, boilerplate, boilerplate!!!
I've created a project for client & editor programs, by simply copying one
to the other. Right now, the client still has the editor scene, but I'll
switch that out soon.

I've also added a license header to the server's source. I don't remember
what else I did, but at this point it should theoretically build out of
the box.
2013-08-29 21:17:43 +10:00
Kayne Ruse e4884c3e18 Added more placeholder files 2013-08-29 20:35:02 +10:00
Kayne Ruse b675f516e7 Beginning to create the placeholder classes 2013-08-29 19:57:25 +10:00
Kayne Ruse d5f7363c33 Minor rename 2013-08-25 13:59:13 +10:00
Kayne Ruse 7458962ad4 Rearranged the logic 2013-08-24 23:20:43 +10:00
Kayne Ruse 0a0b61287e Started working on the room system 2013-08-11 20:39:08 +10:00
104 changed files with 5342 additions and 2125 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
#Editor generated files
#*.sln
#*.vcproj
*.sln
*.vcproj
*.suo
*.ncb
*.user
+16 -11
View File
@@ -1,23 +1,28 @@
_This project is currently in it's early prototype stage. You can see other versions in various branches or tagged as prototype-X._
The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
Tortuga is a 2D multiplayer role playing game set in a large archipelago occupied by warring pirate clans. The emphasis of this game is on multiplayer cooperation, competition, and server customization. The game runs on highly customizable server software that can support up to 150 simultaneous players or more. The player characters are tied to the server where they are created and are susceptible to permadeath: deletion of a character upon death.
Tortuga is a 2D multiplayer JRPG featuring permadeath (deletion of a character upon death). The emphasis of this game is on multiplayer cooperation, exploration and customization. The game runs on customizable server software that can support up to 150 simultaneous players or more.
## Dependencies
This game is inspired by classic 2D RPGs, as well as more modern sandbox MMOs. This project is currently independently created and funded, with the goal of creating a game that will engage user's imagination and inspire a large modding community.
* [SDL](http://www.libsdl.org/) - Simple DirectMedia Layer API
* [SDL_net](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
## Documentation
## Instructions
Tortuga's full documentation can be found in a separate branch, see [Tortuga/docs](https://github.com/Ratstail91/Tortuga/tree/docs).
For Tortuga's primary documentation, please read the [Tortuga Game Design Document](https://github.com/Ratstail91/Tortuga/blob/docs/Tortuga%20Game%20Design%20Document.docx?raw=true).
* This project uses C++11, which is available via GNU (or MinGW) 4.7, or Visual Studio 2012. Personally, I'm using MinGW 4.7.2.
* I'm trying to keep this as IDE agnostic as possible, so if you use an IDE, please add it's files to .gitignore.
* You can read more details on the Tortuga wiki [here](https://github.com/Ratstail91/Tortuga/wiki).
## External Dependencies
* [SDL 1.2](http://www.libsdl.org/) - Simple DirectMedia Layer API
* [SDL_net 1.2](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
* [lua 5.2](http://www.lua.org/) - The lua programming language
* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine
## Copyright
(Future versions (to be determined) may be released under a modified version of the [Uplink Developer's License](http://www.introversion.co.uk/uplink/developer/license.html).)
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
Copyright (c) 2013 Kayne Ruse
Copyright (c) 2013, 2014 Kayne Ruse
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.
@@ -25,4 +30,4 @@ Permission is granted to anyone to use this software for any purpose, including
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.
3. This notice may not be removed or altered from any source distribution.
+2 -2
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -34,7 +34,7 @@ SDL_Surface* BaseScene::screen = nullptr;
//-------------------------
BaseScene::BaseScene() {
nextScene = SceneList::CONTINUE;
//
}
BaseScene::~BaseScene() {
+6 -6
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -28,18 +28,18 @@
class BaseScene {
public:
/* Public access members */
//Public access members
BaseScene();
virtual ~BaseScene();
/* Program control */
//Program control
static SDL_Surface* SetScreen(int w, int h, int bpp = 0, Uint32 flags = SDL_HWSURFACE|SDL_DOUBLEBUF);
static SDL_Surface* GetScreen();
SceneList SetNextScene(SceneList sceneIndex);
SceneList GetNextScene() const;
/* Frame loop */
//Frame loop
virtual void RunFrame(double delta);
virtual void RenderFrame();
@@ -50,7 +50,7 @@ protected:
virtual void FrameEnd() {}
virtual void Render(SDL_Surface* const screen) {}
/* Event handlers */
//Event handlers
virtual void QuitEvent() { SetNextScene(SceneList::QUIT); }
virtual void MouseMotion(SDL_MouseMotionEvent const&) {}
virtual void MouseButtonDown(SDL_MouseButtonEvent const&) {}
@@ -68,7 +68,7 @@ protected:
private:
static SDL_Surface* screen;
SceneList nextScene;
SceneList nextScene = SceneList::CONTINUE;
};
#endif
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,10 +19,11 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef FRAMERATE_HPP_
#define FRAMERATE_HPP_
#ifndef CHANNELS_HPP_
#define CHANNELS_HPP_
int clockFrameRate();
int getFrameRate();
enum Channels {
SERVER = 0
};
#endif
+39 -83
View File
@@ -1,11 +1,11 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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
* including commercial ClientApplications, 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
@@ -21,6 +21,8 @@
*/
#include "client_application.hpp"
#include "serial.hpp"
#include <stdexcept>
#include <chrono>
@@ -29,76 +31,41 @@
//-------------------------
//Add the custom scene headers here
#include "in_combat.hpp"
#include "in_world.hpp"
#include "lobby.hpp"
#include "main_menu.hpp"
#include "option_screen.hpp"
#include "splash_screen.hpp"
#include "main_menu.hpp"
#include "options_menu.hpp"
#include "lobby_menu.hpp"
#include "in_world.hpp"
#include "in_combat.hpp"
//-------------------------
//Public access members
//-------------------------
ClientApplication::ClientApplication() {
//
}
void ClientApplication::Init(int argc, char** argv) {
//load the prerequisites
config.Load("rsc\\config.cfg");
ClientApplication::~ClientApplication() {
UnloadScene();
}
/* ClientApplication::Init()
* This function initializes the entire program. There are a number of things
* that could go wrong here, which is why there is such an unusual order of
* operations.
* Important things to note:
* The APIs are initiated here.
* The global objects are initialized here.
* The game's screen is created here, based on information loaded from the config file.
* The ConfigUtility's call to Load() also ensures that the "rsc\" folder is in the directory. It's easy to forget it.
*/
void ClientApplication::Init() {
//load the config file
try {
configUtil->Load("rsc/config.cfg");
}
catch(std::runtime_error& e) {
std::string s = e.what();
s += "; Ensure that the \"rsc\" directory is present";
throw(std::runtime_error(s));
}
//initialize the APIs
//initialize SDL
if (SDL_Init(SDL_INIT_VIDEO)) {
throw(std::runtime_error("Failed to initialize SDL"));
}
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"), 0, (config.Bool("screen.f")) ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
//initialize SDL_net
if (SDLNet_Init()) {
throw(std::runtime_error("Failed to initialize SDL_net"));
}
//create the screen
Uint32 flags = SDL_HWSURFACE | SDL_DOUBLEBUF;
flags |= configUtil->Bool("screen.f") ? SDL_FULLSCREEN : 0;
BaseScene::SetScreen(
configUtil->Int("screen.w"),
configUtil->Int("screen.h"),
SDL_GetVideoInfo()->vfmt->BitsPerPixel,
flags);
//initiate the remaining singletons
netUtil->Open(0, sizeof(Packet));
network.Open(0);
}
void ClientApplication::Proc() {
LoadScene(SceneList::FIRST);
//prepare the time system
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::steady_clock Clock;
Clock::duration delta(5 * Clock::duration::period::den / std::milli::den);
std::chrono::duration<int, std::milli> delta(16);
Clock::time_point simTime = Clock::now();
Clock::time_point realTime;
@@ -110,15 +77,13 @@ void ClientApplication::Proc() {
continue;
}
//update the current time & give the computer as much of a break as possible
while ((realTime = Clock::now()) < simTime) {
SDL_Delay(1);
}
//update the current time
realTime = Clock::now();
//simulate game time
while (simTime < realTime) {
//call each user defined function
activeScene->RunFrame(double(delta.count()) / Clock::duration::period::den);
activeScene->RunFrame(double(delta.count()) / std::chrono::duration<int, std::milli>::period::den);
simTime += delta;
}
@@ -130,14 +95,7 @@ void ClientApplication::Proc() {
}
void ClientApplication::Quit() {
//clean up the singletons
netUtil->Close();
surfaceMgr->FreeAll();
//clean up the scene
UnloadScene();
//deinitialize the APIs
network.Close();
SDLNet_Quit();
SDL_Quit();
}
@@ -148,29 +106,27 @@ void ClientApplication::Quit() {
void ClientApplication::LoadScene(SceneList sceneIndex) {
UnloadScene();
switch(sceneIndex) {
//add scene creation calls here
case SceneList::INCOMBAT:
activeScene = new InCombat();
break;
case SceneList::INWORLD:
activeScene = new InWorld();
break;
case SceneList::LOBBY:
activeScene = new Lobby();
break;
case SceneList::MAINMENU:
activeScene = new MainMenu();
break;
case SceneList::OPTIONSCREEN:
activeScene = new OptionScreen();
break;
case SceneList::FIRST:
case SceneList::SPLASHSCREEN:
activeScene = new SplashScreen();
activeScene = new SplashScreen(&config);
break;
case SceneList::MAINMENU:
activeScene = new MainMenu(&config);
break;
case SceneList::OPTIONSMENU:
activeScene = new OptionsMenu(&config);
break;
case SceneList::LOBBYMENU:
activeScene = new LobbyMenu(&config, &network, &clientIndex, &accountIndex, &characterIndex);
break;
case SceneList::INWORLD:
activeScene = new InWorld(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap);
break;
case SceneList::INCOMBAT:
activeScene = new InCombat(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap, &enemyMap);
break;
default:
throw(std::logic_error("Failed to recognize the scene index"));
}
+19 -17
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -24,39 +24,41 @@
#include "scene_list.hpp"
#include "base_scene.hpp"
#include "singleton.hpp"
#include "packet.hpp"
#include "information_manager.hpp"
#include "config_utility.hpp"
#include "surface_manager.hpp"
#include "udp_network_utility.hpp"
#include "character_data.hpp"
#include "combat_data.hpp"
#include "enemy_data.hpp"
#include "SDL/SDL.h"
#include <map>
class ClientApplication {
public:
/* Public access members */
ClientApplication();
~ClientApplication();
ClientApplication() = default;
~ClientApplication() = default;
void Init();
void Init(int argc, char** argv);
void Proc();
void Quit();
ClientApplication(ClientApplication const&) = delete;
ClientApplication(ClientApplication const&&) = delete;
private:
/* Private access members */
//Private access members
void LoadScene(SceneList sceneIndex);
void UnloadScene();
BaseScene* activeScene = nullptr;
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
InformationManager* infoMgr = Singleton<InformationManager>::Get();
//shared parameters
ConfigUtility config;
UDPNetworkUtility network;
int clientIndex = -1;
int accountIndex = -1;
int characterIndex = -1;
std::map<int, CombatData> combatMap;
std::map<int, CharacterData> characterMap;
std::map<int, EnemyData> enemyMap;
};
#endif
+47 -12
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,24 +21,34 @@
*/
#include "in_combat.hpp"
#include <iostream>
using namespace std;
//-------------------------
//Public access members
//-------------------------
InCombat::InCombat() {
#ifdef DEBUG
cout << "entering InCombat" << endl;
#endif
InCombat::InCombat(
ConfigUtility* const argConfig,
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
std::map<int, CombatData>* argCombatMap,
std::map<int, CharacterData>* argCharacterMap,
std::map<int, EnemyData>* argEnemyMap
):
config(*argConfig),
network(*argNetwork),
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex),
characterIndex(*argCharacterIndex),
combatMap(*argCombatMap),
characterMap(*argCharacterMap),
enemyMap(*argEnemyMap)
{
//
}
InCombat::~InCombat() {
#ifdef DEBUG
cout << "leaving InCombat" << endl;
#endif
//
}
//-------------------------
@@ -57,6 +67,13 @@ void InCombat::FrameEnd() {
//
}
void InCombat::RenderFrame() {
SDL_FillRect(GetScreen(), 0, 0);
Render(GetScreen());
SDL_Flip(GetScreen());
fps.Calculate();
}
void InCombat::Render(SDL_Surface* const screen) {
//
}
@@ -65,6 +82,12 @@ void InCombat::Render(SDL_Surface* const screen) {
//Event handlers
//-------------------------
void InCombat::QuitEvent() {
//exit the game AND the server
// RequestDisconnect();
SetNextScene(SceneList::MAINMENU);
}
void InCombat::MouseMotion(SDL_MouseMotionEvent const& motion) {
//
}
@@ -88,3 +111,15 @@ void InCombat::KeyDown(SDL_KeyboardEvent const& key) {
void InCombat::KeyUp(SDL_KeyboardEvent const& key) {
//
}
//-------------------------
//Network handlers
//-------------------------
//TODO: network handlers
//-------------------------
//Server control
//-------------------------
//TODO: server control
+61 -5
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,27 +22,83 @@
#ifndef INCOMBAT_HPP_
#define INCOMBAT_HPP_
//network
#include "udp_network_utility.hpp"
//graphics
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
//common
#include "config_utility.hpp"
#include "frame_rate.hpp"
#include "combat_data.hpp"
#include "character_data.hpp"
#include "enemy_data.hpp"
//client
#include "base_scene.hpp"
class InCombat : public BaseScene {
public:
/* Public access members */
InCombat();
//Public access members
InCombat(
ConfigUtility* const argConfig,
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
std::map<int, CombatData>* argCombatMap,
std::map<int, CharacterData>* argCharacterMap,
std::map<int, EnemyData>* argEnemyMap
);
~InCombat();
protected:
/* Frame loop */
//Frame loop
void FrameStart();
void Update(double delta);
void FrameEnd();
void RenderFrame();
void Render(SDL_Surface* const);
/* Event handlers */
//Event handlers
void QuitEvent();
void MouseMotion(SDL_MouseMotionEvent const&);
void MouseButtonDown(SDL_MouseButtonEvent const&);
void MouseButtonUp(SDL_MouseButtonEvent const&);
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
//Network handlers
void HandlePacket(SerialPacket);
void HandleDisconnect(SerialPacket);
//TODO: more
//Server control
void SendPlayerUpdate();
void RequestDisconnect();
void RequestShutdown();
//TODO: more
//shared parameters
ConfigUtility& config;
UDPNetworkUtility& network;
int& clientIndex;
int& accountIndex;
int& characterIndex;
std::map<int, CombatData>& combatMap;
std::map<int, CharacterData>& characterMap;
std::map<int, EnemyData>& enemyMap;
//graphics
//TODO: graphics
//UI
//TODO: UI
FrameRate fps;
};
#endif
+343 -217
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,55 +21,67 @@
*/
#include "in_world.hpp"
#include <iostream>
#include "channels.hpp"
using namespace std;
//-------------------------
//Quick and dirty
//-------------------------
static std::string itos(int i) {
char buffer[20];
snprintf(buffer, 20, "%d", i);
return std::string(buffer);
}
#include <algorithm>
#include <cmath>
#include <stdexcept>
//-------------------------
//Public access members
//-------------------------
InWorld::InWorld() {
#ifdef DEBUG
cout << "entering InWorld" << endl;
#endif
cout << "Client Index: " << infoMgr->GetClientIndex() << endl;
font.SetSurface(surfaceMgr->Get("font"));
InWorld::InWorld(
ConfigUtility* const argConfig,
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
std::map<int, CombatData>* argCombatMap,
std::map<int, CharacterData>* argCharacterMap
):
config(*argConfig),
network(*argNetwork),
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex),
characterIndex(*argCharacterIndex),
combatMap(*argCombatMap),
characterMap(*argCharacterMap)
{
//setup the utility objects
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
buttonImage.SetClipH(buttonImage.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//debugging
Packet p;
p.meta.type = Packet::Type::PLAYER_NEW;
p.meta.clientIndex = infoMgr->GetClientIndex();
//pass the utility objects
disconnectButton.SetImage(&buttonImage);
disconnectButton.SetFont(&font);
shutDownButton.SetImage(&buttonImage);
shutDownButton.SetFont(&font);
snprintf(p.playerInfo.handle, PACKET_STRING_SIZE, "%s", configUtil->CString("handle"));
snprintf(p.playerInfo.avatar, PACKET_STRING_SIZE, "%s", configUtil->CString("avatar"));
p.playerInfo.position.x = 50;
p.playerInfo.position.y = 50;
p.playerInfo.motion.x = 0;
p.playerInfo.motion.y = 0;
//set the button positions
disconnectButton.SetX(50);
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
shutDownButton.SetX(50);
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
//set the button texts
disconnectButton.SetText("Disconnect");
shutDownButton.SetText("Shut Down");
//load the tilesheet
//TODO: add the tilesheet to the map system?
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
//request a sync
p.meta.type = Packet::Type::SYNCHRONIZE;
p.meta.clientIndex = infoMgr->GetClientIndex();
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
RequestSynchronize();
//debug
// RequestRegion(0, 0);
}
InWorld::~InWorld() {
#ifdef DEBUG
cout << "leaving InWorld" << endl;
#endif
//
}
//-------------------------
@@ -81,27 +93,55 @@ void InWorld::FrameStart() {
}
void InWorld::Update(double delta) {
while(HandlePacket(popNetworkPacket()));
SerialPacket packet;
for (auto& it : playerCharacters) {
//suck in all waiting packets
while(network.Receive(&packet)) {
HandlePacket(packet);
}
//update the characters
for (auto& it : characterMap) {
it.second.Update(delta);
}
//update the camera
if(localCharacter) {
camera.x = localCharacter->position.x - camera.marginX;
camera.y = localCharacter->position.y - camera.marginY;
}
//check the map
UpdateMap();
}
void InWorld::FrameEnd() {
//
}
void InWorld::Render(SDL_Surface* const screen) {
clockFrameRate();
void InWorld::RenderFrame() {
// SDL_FillRect(GetScreen(), 0, 0);
Render(GetScreen());
SDL_Flip(GetScreen());
fps.Calculate();
}
for (auto& it : playerCharacters) {
it.second.DrawTo(screen);
void InWorld::Render(SDL_Surface* const screen) {
//draw the map
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y);
}
//since we're using this twice, make a tmp var
string fps = itos(getFrameRate());
font.DrawStringTo(fps, screen, screen->w - fps.size() * font.GetCharW(), 0);
//draw characters
for (auto& it : characterMap) {
//TODO: drawing order according to Y position
it.second.DrawTo(screen, camera.x, camera.y);
}
//draw UI
disconnectButton.DrawTo(screen);
shutDownButton.DrawTo(screen);
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
}
//-------------------------
@@ -109,218 +149,304 @@ void InWorld::Render(SDL_Surface* const screen) {
//-------------------------
void InWorld::QuitEvent() {
//ensure that the client is disconnected properly
ExitGame();
SetNextScene(SceneList::QUIT);
//exit the game AND the server
RequestDisconnect();
SetNextScene(SceneList::MAINMENU);
}
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
//
disconnectButton.MouseMotion(motion);
shutDownButton.MouseMotion(motion);
}
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
//
disconnectButton.MouseButtonDown(button);
shutDownButton.MouseButtonDown(button);
}
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
//
if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER) {
RequestDisconnect();
}
if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER) {
RequestShutDown();
}
}
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
//general
switch(key.keysym.sym) {
case SDLK_ESCAPE:
ExitGame();
case SDLK_ESCAPE: {
QuitEvent();
}
break;
}
//player movement
if (infoMgr->GetPlayerIndex() == -1) {
return;
}
//player movement
case SDLK_LEFT:
if (localCharacter) {
localCharacter->motion.x -= CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
switch(key.keysym.sym) {
case SDLK_w:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::NORTH);
SendState();
case SDLK_RIGHT:
if (localCharacter) {
localCharacter->motion.x += CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
case SDLK_s:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::SOUTH);
SendState();
case SDLK_UP:
if (localCharacter) {
localCharacter->motion.y -= CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
case SDLK_a:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::WEST);
SendState();
break;
case SDLK_d:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::EAST);
SendState();
case SDLK_DOWN:
if (localCharacter) {
localCharacter->motion.y += CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
}
}
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
//player movement reversed
switch(key.keysym.sym) {
case SDLK_w:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::SOUTH);
SendState();
//player movement
case SDLK_LEFT:
if (localCharacter) {
localCharacter->motion.x += CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
case SDLK_s:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::NORTH);
SendState();
case SDLK_RIGHT:
if (localCharacter) {
localCharacter->motion.x -= CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
case SDLK_a:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::EAST);
SendState();
case SDLK_UP:
if (localCharacter) {
localCharacter->motion.y += CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
case SDLK_d:
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::WEST);
SendState();
case SDLK_DOWN:
if (localCharacter) {
localCharacter->motion.y -= CHARACTER_WALKING_SPEED;
SendPlayerUpdate();
}
break;
}
}
//-------------------------
//Network handlers
//-------------------------
void InWorld::HandlePacket(SerialPacket packet) {
switch(packet.meta.type) {
case SerialPacket::Type::DISCONNECT:
HandleDisconnect(packet);
break;
case SerialPacket::Type::REGION_CONTENT:
HandleRegionContent(packet);
break;
case SerialPacket::Type::CHARACTER_UPDATE:
HandleCharacterUpdate(packet);
break;
case SerialPacket::Type::CHARACTER_NEW:
HandleCharacterNew(packet);
break;
case SerialPacket::Type::CHARACTER_DELETE:
HandleCharacterDelete(packet);
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in InWorld: " + to_string_custom(int(packet.meta.type))));
break;
}
}
void InWorld::HandleDisconnect(SerialPacket packet) {
network.Unbind(Channels::SERVER);
clientIndex = -1;
accountIndex = -1;
characterIndex = -1;
SetNextScene(SceneList::MAINMENU);
}
void InWorld::HandleRegionContent(SerialPacket packet) {
//replace existing regions
regionPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y);
regionPager.PushRegion(packet.regionInfo.region);
packet.regionInfo.region = nullptr;
}
void InWorld::HandleCharacterUpdate(SerialPacket packet) {
if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) {
HandleCharacterNew(packet);
return;
}
//update only if the message didn't originate from here
if (packet.characterInfo.clientIndex != clientIndex) {
characterMap[packet.characterInfo.characterIndex].position = packet.characterInfo.position;
characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion;
}
characterMap[packet.characterInfo.characterIndex].CorrectSprite();
}
void InWorld::HandleCharacterNew(SerialPacket packet) {
if (characterMap.find(packet.characterInfo.characterIndex) != characterMap.end()) {
throw(std::runtime_error("Cannot create duplicate characters"));
}
//create the character object
CharacterData& character = characterMap[packet.characterInfo.characterIndex];
//set the members
character.handle = packet.characterInfo.handle;
character.avatar = packet.characterInfo.avatar;
character.sprite.LoadSurface(config["dir.sprites"] + character.avatar, 4, 4);
character.mapIndex = packet.characterInfo.mapIndex;
character.position = packet.characterInfo.position;
character.motion = packet.characterInfo.motion;
character.stats = packet.characterInfo.stats;
character.CorrectSprite();
//catch this client's player object
if (packet.characterInfo.characterIndex == characterIndex && !localCharacter) {
localCharacter = &character;
//setup the camera
//TODO: can't change the screen size?
camera.width = GetScreen()->w;
camera.height = GetScreen()->h;
//center on the player's character
camera.marginX = (GetScreen()->w / 2 - localCharacter->sprite.GetImage()->GetClipW() / 2);
camera.marginY = (GetScreen()->h / 2 - localCharacter->sprite.GetImage()->GetClipH() / 2);
}
}
void InWorld::HandleCharacterDelete(SerialPacket packet) {
//TODO: authenticate when own character is being deleted (linked to a TODO in the server)
//catch this client's player object
if (packet.characterInfo.characterIndex == characterIndex) {
characterIndex = -1;
localCharacter = nullptr;
}
characterMap.erase(packet.characterInfo.characterIndex);
}
//-------------------------
//Server control
//-------------------------
void InWorld::RequestSynchronize() {
SerialPacket packet;
//request a sync
packet.meta.type = SerialPacket::Type::SYNCHRONIZE;
packet.clientInfo.clientIndex = clientIndex;
packet.clientInfo.accountIndex = accountIndex;
packet.clientInfo.characterIndex = characterIndex;
network.SendTo(Channels::SERVER, &packet);
}
void InWorld::SendPlayerUpdate() {
SerialPacket packet;
//pack the packet
packet.meta.type = SerialPacket::Type::CHARACTER_UPDATE;
packet.characterInfo.clientIndex = clientIndex;
packet.characterInfo.accountIndex = accountIndex;
packet.characterInfo.characterIndex = characterIndex;
packet.characterInfo.position = localCharacter->position;
packet.characterInfo.motion = localCharacter->motion;
network.SendTo(Channels::SERVER, &packet);
}
void InWorld::RequestDisconnect() {
SerialPacket packet;
//send a disconnect request
packet.meta.type = SerialPacket::Type::DISCONNECT;
packet.clientInfo.clientIndex = clientIndex;
packet.clientInfo.accountIndex = accountIndex;
packet.clientInfo.characterIndex = characterIndex;
network.SendTo(Channels::SERVER, &packet);
}
void InWorld::RequestShutDown() {
SerialPacket packet;
//send a shutdown request
packet.meta.type = SerialPacket::Type::SHUTDOWN;
packet.clientInfo.clientIndex = clientIndex;
packet.clientInfo.accountIndex = accountIndex;
packet.clientInfo.characterIndex = characterIndex;
network.SendTo(Channels::SERVER, &packet);
}
void InWorld::RequestRegion(int mapIndex, int x, int y) {
SerialPacket packet;
//pack the region's data
packet.meta.type = SerialPacket::Type::REGION_REQUEST;
packet.regionInfo.mapIndex = mapIndex;
packet.regionInfo.x = x;
packet.regionInfo.y = y;
network.SendTo(Channels::SERVER, &packet);
}
//-------------------------
//Utilities
//-------------------------
int InWorld::HandlePacket(Packet p) {
switch(p.meta.type) {
case Packet::Type::NONE:
//DO NOTHING
return 0;
break;
case Packet::Type::PING:
//quick pong
p.meta.type = Packet::Type::PONG;
p.meta.clientIndex = infoMgr->GetClientIndex();
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
break;
case Packet::Type::PONG:
//
break;
// case Packet::Type::BROADCAST_REQUEST:
// //
// break;
// case Packet::Type::BROADCAST_RESPONSE:
// //
// break;
// case Packet::Type::JOIN_REQUEST:
// //
// break;
// case Packet::Type::JOIN_RESPONSE:
// //
// break;
case Packet::Type::DISCONNECT:
HandleDisconnection(p);
break;
// case Packet::Type::SYNCHRONIZE:
// //
// break;
case Packet::Type::PLAYER_NEW:
AddPlayer(p);
break;
case Packet::Type::PLAYER_DELETE:
RemovePlayer(p);
break;
case Packet::Type::PLAYER_UPDATE:
UpdatePlayer(p);
break;
default:
throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type))));
}
return 1;
}
//TODO: convert this into a more generic function?; using parameters for the bounds
void InWorld::UpdateMap() {
//these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1)
int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH;
int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH;
void InWorld::Disconnect() {
Packet p;
int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT;
int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT;
//delete the player
p.meta.type = Packet::Type::PLAYER_DELETE;
p.meta.clientIndex = infoMgr->GetClientIndex();
p.playerInfo.index = infoMgr->GetPlayerIndex();
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
//prune distant regions
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) {
//check if the region is outside off this area
if ((*it)->GetX() < xStart || (*it)->GetX() > xEnd || (*it)->GetY() < yStart || (*it)->GetY() > yEnd) {
//disconnect
p.meta.type = Packet::Type::DISCONNECT;
p.meta.clientIndex = infoMgr->GetClientIndex();
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
//clunky, but the alternative was time consuming
int tmpX = (*it)->GetX();
int tmpY = (*it)->GetY();
++it;
netUtil->Unbind(GAME_CHANNEL);
//reset the client
infoMgr->ResetClientIndex();
infoMgr->ResetPlayerIndex();
}
void InWorld::ExitGame() {
Disconnect();
SetNextScene(SceneList::MAINMENU);
endQueueThread();
cout << "The game session has ended" << endl;
}
void InWorld::HandleDisconnection(Packet& disconnect) {
Disconnect();
SetNextScene(SceneList::MAINMENU);
endQueueThread();
cout << "You have been disconnected" << endl;
}
void InWorld::AddPlayer(Packet& p) {
if (playerCharacters.find(p.playerInfo.index) != playerCharacters.end()) {
throw(runtime_error("Duplicate players detected"));
regionPager.UnloadRegion(tmpX, tmpY);
continue;
}
++it;
}
//position
playerCharacters[p.playerInfo.index].SetPosition(p.playerInfo.position);
playerCharacters[p.playerInfo.index].SetMotion(p.playerInfo.motion);
//sprite
playerCharacters[p.playerInfo.index].GetSprite()->SetSurface(surfaceMgr->Get(p.playerInfo.avatar), 32, 48);
playerCharacters[p.playerInfo.index].FaceDirection();
//is it this player?
if (p.meta.clientIndex == infoMgr->GetClientIndex()) {
infoMgr->SetPlayerIndex(p.playerInfo.index);
//request empty regions within this zone
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
if (!regionPager.FindRegion(i, j)) {
RequestRegion(0, i, j);
}
}
}
//debugging
cout << "New player, index " << p.playerInfo.index << endl;
}
void InWorld::RemovePlayer(Packet& p) {
if (playerCharacters.find(p.playerInfo.index) == playerCharacters.end()) {
throw(runtime_error("Player to delete not found"));
}
playerCharacters.erase(p.playerInfo.index);
}
void InWorld::UpdatePlayer(Packet& p) {
if (playerCharacters.find(p.playerInfo.index) == playerCharacters.end()) {
AddPlayer(p);
return;
}
playerCharacters[p.playerInfo.index].SetPosition(p.playerInfo.position);
playerCharacters[p.playerInfo.index].SetMotion(p.playerInfo.motion);
playerCharacters[p.playerInfo.index].FaceDirection();
}
void InWorld::SendState() {
//send the state of this player's character
if (infoMgr->GetPlayerIndex() == -1) {
return;
}
Packet p;
p.meta.type = Packet::Type::PLAYER_UPDATE;
p.meta.clientIndex = infoMgr->GetClientIndex();
p.playerInfo.index = infoMgr->GetPlayerIndex();
p.playerInfo.position = playerCharacters[infoMgr->GetPlayerIndex()].GetPosition();
p.playerInfo.motion = playerCharacters[infoMgr->GetPlayerIndex()].GetMotion();
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
}
+74 -30
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,28 +22,45 @@
#ifndef INWORLD_HPP_
#define INWORLD_HPP_
#include "base_scene.hpp"
//maps
#include "map_allocator.hpp"
#include "map_file_format.hpp"
#include "region_pager.hpp"
#include "defines.hpp"
#include "singleton.hpp"
#include "packet.hpp"
#include "network_queue.hpp"
#include "information_manager.hpp"
#include "player_character.hpp"
#include "config_utility.hpp"
#include "surface_manager.hpp"
//networking
#include "udp_network_utility.hpp"
#include "button.hpp"
//graphics
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
#include "tile_sheet.hpp"
//common
#include "config_utility.hpp"
#include "frame_rate.hpp"
#include "combat_data.hpp"
#include "character_data.hpp"
//client
#include "base_scene.hpp"
//STL
#include <map>
class InWorld : public BaseScene {
public:
//Public access members
InWorld();
InWorld(
ConfigUtility* const argConfig,
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
std::map<int, CombatData>* argCombatMap,
std::map<int, CharacterData>* argCharacterMap
);
~InWorld();
protected:
@@ -51,6 +68,7 @@ protected:
void FrameStart();
void Update(double delta);
void FrameEnd();
void RenderFrame();
void Render(SDL_Surface* const);
//Event handlers
@@ -61,28 +79,54 @@ protected:
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
//Utilities
int HandlePacket(Packet);
void Disconnect();
void ExitGame();
//Network handlers
void HandlePacket(SerialPacket);
void HandleDisconnect(SerialPacket);
void HandleCharacterNew(SerialPacket);
void HandleCharacterDelete(SerialPacket);
void HandleCharacterUpdate(SerialPacket);
void HandleRegionContent(SerialPacket);
void HandleDisconnection(Packet&);
//Server control
void RequestSynchronize();
void SendPlayerUpdate();
void RequestDisconnect();
void RequestShutDown();
void RequestRegion(int mapIndex, int x, int y);
void AddPlayer(Packet&);
void RemovePlayer(Packet&);
void UpdatePlayer(Packet&);
//utilities
void UpdateMap();
void SendState();
//shared parameters
ConfigUtility& config;
UDPNetworkUtility& network;
int& clientIndex;
int& accountIndex;
int& characterIndex;
std::map<int, CombatData>& combatMap;
std::map<int, CharacterData>& characterMap;
//services
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
InformationManager* infoMgr = Singleton<InformationManager>::Get();
//members
//graphics
Image buttonImage;
RasterFont font;
std::map<int, PlayerCharacter> playerCharacters;
TileSheet tileSheet;
//map
RegionPager<BlankAllocator, DummyFormat> regionPager;
//UI
Button disconnectButton;
Button shutDownButton;
//TODO: Review the camera
struct {
int x = 0, y = 0;
int width = 0, height = 0;
int marginX = 0, marginY = 0;
} camera;
FrameRate fps;
//game
CharacterData* localCharacter = nullptr;
};
#endif
-244
View File
@@ -1,244 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 "lobby.hpp"
#include <iostream>
using namespace std;
//-------------------------
//Quick and dirty
//-------------------------
static std::string itos(int i) {
char buffer[20];
snprintf(buffer, 20, "%d", i);
return std::string(buffer);
}
//-------------------------
//Public access members
//-------------------------
Lobby::Lobby() {
#ifdef DEBUG
cout << "entering Lobby" << endl;
#endif
refreshButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Refresh");
joinButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Join");
backButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3 * 2, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Back");
font.SetSurface(surfaceMgr->Get("font"));
listBox.x = 280;
listBox.y = 50;
listBox.w = GetScreen()->w - listBox.x - 50;
listBox.h = font.GetCharH();
serverList.push_back({"foo",{0,0}});
serverList.push_back({"bar",{0,0}});
serverList.push_back({"foobar",{0,0}});
flushNetworkQueue();
beginQueueThread();
BroadcastNetwork();
}
Lobby::~Lobby() {
#ifdef DEBUG
cout << "leaving Lobby" << endl;
#endif
}
//-------------------------
//Frame loop
//-------------------------
void Lobby::FrameStart() {
//
}
void Lobby::Update(double delta) {
while(HandlePacket(popNetworkPacket()));
}
void Lobby::FrameEnd() {
//
}
void Lobby::Render(SDL_Surface* const screen) {
refreshButton.DrawTo(screen);
joinButton.DrawTo(screen);
backButton.DrawTo(screen);
for (int i = 0; i < serverList.size(); i++) {
if (selectedServer == &serverList[i]) {
//draw the highlight box
SDL_Rect r = listBox;
r.y += i * font.GetCharH();
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39));
}
font.DrawStringTo(serverList[i].name, screen, listBox.x, listBox.y + i * font.GetCharH());
}
}
//-------------------------
//Event handlers
//-------------------------
void Lobby::MouseMotion(SDL_MouseMotionEvent const& motion) {
refreshButton.MouseMotion(motion);
joinButton.MouseMotion(motion);
backButton.MouseMotion(motion);
}
void Lobby::MouseButtonDown(SDL_MouseButtonEvent const& button) {
refreshButton.MouseButtonDown(button);
joinButton.MouseButtonDown(button);
backButton.MouseButtonDown(button);
}
void Lobby::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (refreshButton.MouseButtonUp(button) == Button::State::HOVER) {
BroadcastNetwork();
selectedServer = nullptr;
}
else if (joinButton.MouseButtonUp(button) == Button::State::HOVER) {
if (selectedServer) {
ConnectToServer(selectedServer);
selectedServer = nullptr;
}
}
else if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::MAINMENU);
endQueueThread();
selectedServer = nullptr;
}
else if (
//clicked within bounds TODO: make the damn collision system
button.x > listBox.x &&
button.y > listBox.y &&
button.x < listBox.x + listBox.w &&
button.y < listBox.y + (listBox.h * serverList.size())
)
{
//selecting a server
selectedServer = &serverList[(button.y - listBox.y) / listBox.h];
}
else {
//lose focus on a server
selectedServer = nullptr;
}
}
void Lobby::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU);
break;
}
}
void Lobby::KeyUp(SDL_KeyboardEvent const& key) {
//
}
//-------------------------
//Utilities
//-------------------------
int Lobby::HandlePacket(Packet p) {
switch(p.meta.type) {
case Packet::Type::NONE:
//DO NOTHING
return 0;
break;
case Packet::Type::PING:
//quick pong
p.meta.type = Packet::Type::PONG;
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
break;
case Packet::Type::PONG:
//
break;
// case Packet::Type::BROADCAST_REQUEST:
// //
// break;
case Packet::Type::BROADCAST_RESPONSE:
PushServer(p);
break;
// case Packet::Type::JOIN_REQUEST:
// //
// break;
case Packet::Type::JOIN_RESPONSE:
BeginGame(p);
break;
// case Packet::Type::DISCONNECT:
// //
// break;
// case Packet::Type::SYNCHRONIZE:
// //
// break;
// case Packet::Type::PLAYER_NEW:
// //
// break;
// case Packet::Type::PLAYER_DELETE:
// //
// break;
// case Packet::Type::PLAYER_UPDATE:
// //
// break;
default:
throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type))));
}
return 1;
}
void Lobby::BroadcastNetwork() {
Packet p;
p.meta.type = Packet::Type::BROADCAST_REQUEST;
netUtil->Send("255.255.255.255", configUtil->Int("server.port"), &p, sizeof(Packet));
serverList.clear();
}
void Lobby::PushServer(Packet& bcast) {
ServerEntry entry;
entry.name = bcast.serverInfo.name;
entry.address = bcast.meta.address;
serverList.push_back(entry);
}
void Lobby::ConnectToServer(ServerEntry* server) {
//_attempt_ to connect to a server
if (!server) {
throw(runtime_error("No server received"));
}
Packet p;
p.meta.type = Packet::Type::JOIN_REQUEST;
netUtil->Send(&server->address, reinterpret_cast<void*>(&p), sizeof(Packet));
}
void Lobby::BeginGame(Packet& response) {
//should be downloading the resources here as well
infoMgr->SetClientIndex(response.meta.clientIndex);
netUtil->Bind(&response.meta.address, GAME_CHANNEL);
SetNextScene(SceneList::INWORLD);
}
+237
View File
@@ -0,0 +1,237 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 "lobby_menu.hpp"
#include "channels.hpp"
#include "utility.hpp"
#include <stdexcept>
//-------------------------
//Public access members
//-------------------------
LobbyMenu::LobbyMenu(
ConfigUtility* const argConfig,
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex
):
config(*argConfig),
network(*argNetwork),
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex),
characterIndex(*argCharacterIndex)
{
//setup the utility objects
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
image.SetClipH(image.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
search.SetImage(&image);
search.SetFont(&font);
join.SetImage(&image);
join.SetFont(&font);
back.SetImage(&image);
back.SetFont(&font);
//set the button positions
search.SetX(50);
search.SetY(50 + image.GetClipH() * 0);
join.SetX(50);
join.SetY(50 + image.GetClipH() * 1);
back.SetX(50);
back.SetY(50 + image.GetClipH() * 2);
//set the button texts
search.SetText("Search");
join.SetText("Join");
back.SetText("Back");
//set the server list's position
listBox = {300, 50, 200, font.GetCharH()};
}
LobbyMenu::~LobbyMenu() {
//
}
//-------------------------
//Frame loop
//-------------------------
void LobbyMenu::FrameStart() {
//
}
void LobbyMenu::Update(double delta) {
//suck in and process all waiting packets
SerialPacket packet;
while(network.Receive(&packet)) {
HandlePacket(packet);
}
}
void LobbyMenu::FrameEnd() {
//
}
void LobbyMenu::Render(SDL_Surface* const screen) {
//TODO: I need a proper UI system for the entire client and the editor
//UI
search.DrawTo(screen);
join.DrawTo(screen);
back.DrawTo(screen);
//TODO: draw headers for the server list
for (int i = 0; i < serverInfo.size(); i++) {
//draw the selected server's highlight
if (selection == &serverInfo[i]) {
SDL_Rect r = listBox;
r.y += i * listBox.h;
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39));
}
//draw the server name
font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h);
//draw the player count
font.DrawStringTo(to_string_custom(serverInfo[i].playerCount), screen, listBox.x + listBox.w, listBox.y + i*listBox.h);
//compatible?
if (!serverInfo[i].compatible) {
font.DrawStringTo("?", screen, listBox.x - font.GetCharW(), listBox.y + i*listBox.h);
}
//TODO: ping/delay?
}
}
//-------------------------
//Event handlers
//-------------------------
void LobbyMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
search.MouseMotion(motion);
join.MouseMotion(motion);
back.MouseMotion(motion);
}
void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
search.MouseButtonDown(button);
join.MouseButtonDown(button);
back.MouseButtonDown(button);
}
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (search.MouseButtonUp(button) == Button::State::HOVER) {
//broadcast to the network, or a specific server
SerialPacket packet;
packet.meta.type = SerialPacket::Type::BROADCAST_REQUEST;
network.SendTo(config["server.host"].c_str(), config.Int("server.port"), &packet);
//reset the server list
serverInfo.clear();
selection = nullptr;
}
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr && selection->compatible) {
//pack the packet
SerialPacket packet;
packet.meta.type = SerialPacket::Type::JOIN_REQUEST;
strncpy(packet.clientInfo.username, config["client.username"].c_str(), PACKET_STRING_SIZE);
strncpy(packet.clientInfo.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
strncpy(packet.clientInfo.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
//join the selected server
network.SendTo(&selection->address, &packet);
selection = nullptr;
}
else if (back.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::MAINMENU);
}
else if (
//has the user selected a server on the list?
button.x > listBox.x &&
button.x < listBox.x + listBox.w &&
button.y > listBox.y &&
button.y < listBox.y + listBox.h * serverInfo.size()
) {
selection = &serverInfo[(button.y - listBox.y)/listBox.h];
}
else {
selection = nullptr;
}
}
void LobbyMenu::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU);
break;
}
}
void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
//
}
//-------------------------
//Network handlers
//-------------------------
void LobbyMenu::HandlePacket(SerialPacket packet) {
switch(packet.meta.type) {
case SerialPacket::Type::BROADCAST_RESPONSE: {
//extract the data
ServerInformation server;
server.address = packet.meta.srcAddress;
server.networkVersion = packet.serverInfo.networkVersion;
server.name = packet.serverInfo.name;
server.playerCount = packet.serverInfo.playerCount;
//NOTE: Check compatibility here
server.compatible = server.networkVersion == NETWORK_VERSION;
//push
serverInfo.push_back(server);
}
break;
case SerialPacket::Type::JOIN_RESPONSE:
clientIndex = packet.clientInfo.clientIndex;
accountIndex = packet.clientInfo.accountIndex;
characterIndex = packet.clientInfo.characterIndex;
network.Bind(&packet.meta.srcAddress, Channels::SERVER);
SetNextScene(SceneList::INWORLD);
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in LobbyMenu: " + to_string_custom(int(packet.meta.type))));
break;
}
}
+50 -43
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,38 +19,35 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef LOBBY_HPP_
#define LOBBY_HPP_
#ifndef LOBBYMENU_HPP_
#define LOBBYMENU_HPP_
//graphics & utilities
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
#include "config_utility.hpp"
//network
#include "udp_network_utility.hpp"
//client
#include "base_scene.hpp"
#include "defines.hpp"
#include "singleton.hpp"
#include "packet.hpp"
#include "network_queue.hpp"
#include "information_manager.hpp"
#include "config_utility.hpp"
#include "surface_manager.hpp"
#include "udp_network_utility.hpp"
#include "button.hpp"
#include "raster_font.hpp"
//STL
#include <vector>
#include <string>
struct ServerEntry {
std::string name;
IPaddress address;
//TODO: player count
};
class Lobby : public BaseScene {
class LobbyMenu : public BaseScene {
public:
//Public access members
Lobby();
~Lobby();
LobbyMenu(
ConfigUtility* const argConfig,
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex
);
~LobbyMenu();
protected:
//Frame loop
@@ -66,28 +63,38 @@ protected:
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
//utilities
int HandlePacket(Packet);
void BroadcastNetwork();
void PushServer(Packet&);
void ConnectToServer(ServerEntry*);
void BeginGame(Packet&);
//Network handlers
void HandlePacket(SerialPacket);
//services
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
InformationManager* infoMgr = Singleton<InformationManager>::Get();
//shared parameters
ConfigUtility& config;
UDPNetworkUtility& network;
int& clientIndex;
int& accountIndex;
int& characterIndex;
//members
Button refreshButton;
Button joinButton;
Button backButton;
Image image;
RasterFont font;
Button search;
Button join;
Button back;
//server list
struct ServerInformation {
IPaddress address;
int networkVersion;
std::string name;
int playerCount;
bool compatible;
};
std::vector<ServerInformation> serverInfo;
//a terrible hack, forgive me
//I'd love a proper gui system for this
SDL_Rect listBox;
std::vector<ServerEntry> serverList;
ServerEntry* selectedServer = nullptr;
ServerInformation* selection = nullptr;
};
#endif
+5 -9
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -26,22 +26,18 @@
using namespace std;
int main(int, char**) {
#ifdef DEBUG
cout << "Beginning program" << endl;
#endif
int main(int argc, char** argv) {
cout << "Beginning client" << endl;
try {
ClientApplication app;
app.Init();
app.Init(argc, argv);
app.Proc();
app.Quit();
}
catch(exception& e) {
cerr << "Fatal error: " << e.what() << endl;
cerr << "Fatal exception thrown: " << e.what() << endl;
return 1;
}
#ifdef DEBUG
cout << "Clean exit" << endl;
#endif
return 0;
}
+37 -18
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,27 +21,42 @@
*/
#include "main_menu.hpp"
#include <iostream>
using namespace std;
//-------------------------
//Public access members
//-------------------------
MainMenu::MainMenu() {
#ifdef DEBUG
cout << "entering MainMenu" << endl;
#endif
startButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Start");
optionsButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Options");
quitButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3 * 2, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Quit");
MainMenu::MainMenu(ConfigUtility* const argConfig):
config(*argConfig)
{
//setup the utility objects
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
image.SetClipH(image.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
startButton.SetImage(&image);
startButton.SetFont(&font);
optionsButton.SetImage(&image);
optionsButton.SetFont(&font);
quitButton.SetImage(&image);
quitButton.SetFont(&font);
//set the button positions
startButton.SetX(50);
startButton.SetY(50 + image.GetClipH() * 0);
optionsButton.SetX(50);
optionsButton.SetY(50 + image.GetClipH() * 1);
quitButton.SetX(50);
quitButton.SetY(50 + image.GetClipH() * 2);
//set the button texts
startButton.SetText("Start");
optionsButton.SetText("Options");
quitButton.SetText("Quit");
}
MainMenu::~MainMenu() {
#ifdef DEBUG
cout << "leaving MainMenu" << endl;
#endif
//
}
//-------------------------
@@ -84,10 +99,10 @@ void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (startButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::LOBBY);
SetNextScene(SceneList::LOBBYMENU);
}
if (optionsButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::OPTIONSCREEN);
SetNextScene(SceneList::OPTIONSMENU);
}
if (quitButton.MouseButtonUp(button) == Button::State::HOVER) {
QuitEvent();
@@ -98,6 +113,10 @@ void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
QuitEvent();
break;
break;
}
}
void MainMenu::KeyUp(SDL_KeyboardEvent const& key) {
//
}
+14 -8
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -23,32 +23,38 @@
#define MAINMENU_HPP_
#include "base_scene.hpp"
#include "singleton.hpp"
#include "surface_manager.hpp"
#include "config_utility.hpp"
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
class MainMenu : public BaseScene {
public:
/* Public access members */
MainMenu();
//Public access members
MainMenu(ConfigUtility* const);
~MainMenu();
protected:
/* Frame loop */
//Frame loop
void FrameStart();
void Update(double delta);
void FrameEnd();
void Render(SDL_Surface* const);
/* Event handlers */
//Event handlers
void MouseMotion(SDL_MouseMotionEvent const&);
void MouseButtonDown(SDL_MouseButtonEvent const&);
void MouseButtonUp(SDL_MouseButtonEvent const&);
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
//shared parameters
ConfigUtility& config;
//members
Image image;
RasterFont font;
Button startButton;
Button optionsButton;
Button quitButton;
+6 -7
View File
@@ -1,15 +1,14 @@
#config
LOCALLIBS=../lib/libCommon.a
LIB=$(LOCALLIBS) -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL
INCLUDES=../common
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
INCLUDES+=. ../common/gameplay ../common/graphics ../common/map ../common/network ../common/ui ../common/utilities
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -DGRAPHICS
#source
SRC=$(wildcard *.cpp)
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../out
@@ -17,7 +16,7 @@ OUT=$(addprefix $(OUTDIR)/,client)
#targets
all: $(OBJ) $(OUT)
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
$(OBJ): | $(OBJDIR)
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,59 +19,84 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "option_screen.hpp"
#include <iostream>
using namespace std;
#include "options_menu.hpp"
//-------------------------
//Public access members
//-------------------------
OptionScreen::OptionScreen() {
#ifdef DEBUG
cout << "entering OptionScreen" << endl;
#endif
backButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Back");
OptionsMenu::OptionsMenu(ConfigUtility* const argConfig):
config(*argConfig)
{
//setup the utility objects
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
image.SetClipH(image.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
backButton.SetImage(&image);
backButton.SetFont(&font);
//set the button positions
backButton.SetX(50);
backButton.SetY(50 + image.GetClipH() * 0);
//set the button texts
backButton.SetText("Back");
}
OptionScreen::~OptionScreen() {
#ifdef DEBUG
cout << "leaving OptionScreen" << endl;
#endif
OptionsMenu::~OptionsMenu() {
//
}
//-------------------------
//Frame loop
//-------------------------
void OptionScreen::Render(SDL_Surface* const screen) {
void OptionsMenu::FrameStart() {
//
}
void OptionsMenu::Update(double delta) {
//
}
void OptionsMenu::FrameEnd() {
//
}
void OptionsMenu::Render(SDL_Surface* const screen) {
backButton.DrawTo(screen);
font.DrawStringTo("Oh, were you looking for the options screen?", screen, 50, 30);
}
//-------------------------
//Event handlers
//-------------------------
void OptionScreen::MouseMotion(SDL_MouseMotionEvent const& motion) {
void OptionsMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
backButton.MouseMotion(motion);
}
void OptionScreen::MouseButtonDown(SDL_MouseButtonEvent const& button) {
void OptionsMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
backButton.MouseButtonDown(button);
}
void OptionScreen::MouseButtonUp(SDL_MouseButtonEvent const& button) {
void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::MAINMENU);
}
}
void OptionScreen::KeyDown(SDL_KeyboardEvent const& key) {
void OptionsMenu::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU);
break;
break;
}
}
void OptionsMenu::KeyUp(SDL_KeyboardEvent const& key) {
//
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,32 +19,42 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef OPTIONSCREEN_HPP_
#define OPTIONSCREEN_HPP_
#ifndef OPTIONSMENU_HPP_
#define OPTIONSMENU_HPP_
#include "base_scene.hpp"
#include "singleton.hpp"
#include "surface_manager.hpp"
#include "config_utility.hpp"
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
class OptionScreen : public BaseScene {
class OptionsMenu : public BaseScene {
public:
/* Public access members */
OptionScreen();
~OptionScreen();
//Public access members
OptionsMenu(ConfigUtility* const);
~OptionsMenu();
protected:
/* Frame loop */
//Frame loop
void FrameStart();
void Update(double delta);
void FrameEnd();
void Render(SDL_Surface* const);
/* Event handlers */
//Event handlers
void MouseMotion(SDL_MouseMotionEvent const&);
void MouseButtonDown(SDL_MouseButtonEvent const&);
void MouseButtonUp(SDL_MouseButtonEvent const&);
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
//shared parameters
ConfigUtility& config;
//members
Image image;
RasterFont font;
Button backButton;
};
-114
View File
@@ -1,114 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 "player_character.hpp"
void PlayerCharacter::Update(double delta) {
if (limitSpeed) {
constexpr double d = 1.0/sqrt(2);
position += motion * delta * d;
}
else {
position += motion * delta;
}
sprite.Update(delta);
}
void PlayerCharacter::MoveDirection(CardinalDirection cd) {
//shift the movement in this direction
switch(cd) {
case CardinalDirection::NORTH:
if (motion.y >= 0) {
motion.y -= WALKING_SPEED;
}
break;
case CardinalDirection::SOUTH:
if (motion.y <= 0) {
motion.y += WALKING_SPEED;
}
break;
case CardinalDirection::WEST:
if (motion.x >= 0) {
motion.x -= WALKING_SPEED;
}
break;
case CardinalDirection::EAST:
if (motion.x <= 0) {
motion.x += WALKING_SPEED;
}
break;
}
//face the correct direction
FaceDirection();
}
void PlayerCharacter::FaceDirection(CardinalDirection cd) {
switch(cd) {
case CardinalDirection::NORTH:
sprite.SetCurrentStrip(1);
break;
case CardinalDirection::SOUTH:
sprite.SetCurrentStrip(0);
break;
case CardinalDirection::WEST:
sprite.SetCurrentStrip(2);
break;
case CardinalDirection::EAST:
sprite.SetCurrentStrip(3);
break;
}
}
void PlayerCharacter::FaceDirection() {
//base the direction on the character's movement
if (motion.y < 0) {
FaceDirection(CardinalDirection::NORTH);
}
if (motion.y > 0) {
FaceDirection(CardinalDirection::SOUTH);
}
if (motion.x < 0) {
FaceDirection(CardinalDirection::WEST);
}
if (motion.x > 0) {
FaceDirection(CardinalDirection::EAST);
}
CheckSpeed();
}
void PlayerCharacter::CheckSpeed() {
//diagonal
if (motion.x != 0 && motion.y != 0) {
sprite.SetDelay(0.1);
limitSpeed = true;
}
//cardinal
else if (motion != 0) {
sprite.SetDelay(0.1);
limitSpeed = false;
}
//not moving
else {
sprite.SetDelay(0);
sprite.SetCurrentFrame(0);
limitSpeed = false;
}
}
-63
View File
@@ -1,63 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 PLAYERCHARACTER_HPP_
#define PLAYERCHARACTER_HPP_
#include "vector2.hpp"
#include "sprite_sheet.hpp"
#include "defines.hpp"
class PlayerCharacter {
public:
PlayerCharacter() = default;
~PlayerCharacter() = default;
void Update(double delta);
void MoveDirection(CardinalDirection);
void FaceDirection(CardinalDirection);
void FaceDirection();
void DrawTo(SDL_Surface* const dest) { sprite.DrawTo(dest, position.x, position.y); }
//accessors and mutators
Vector2 SetPosition(Vector2 v) { return position = v; }
Vector2 ShiftPosition(Vector2 v) { return position += v; }
Vector2 GetPosition() { return position; }
Vector2 SetMotion(Vector2 v) { return motion = v; }
Vector2 ShiftMotion(Vector2 v) { return motion += v; }
Vector2 GetMotion() { return motion; }
SpriteSheet* GetSprite() { return &sprite; }
private:
void CheckSpeed();
Vector2 position;
Vector2 motion;
SpriteSheet sprite;
//for moving diagonal
bool limitSpeed = false;
};
#endif
+6 -6
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -29,12 +29,12 @@ enum class SceneList {
FIRST,
//custom indexes
INCOMBAT,
INWORLD,
LOBBY,
MAINMENU,
OPTIONSCREEN,
SPLASHSCREEN,
MAINMENU,
OPTIONSMENU,
LOBBYMENU,
INWORLD,
INCOMBAT,
};
#endif
+11 -46
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,66 +21,31 @@
*/
#include "splash_screen.hpp"
#include <iostream>
using namespace std;
//-------------------------
//Public access members
//-------------------------
SplashScreen::SplashScreen() {
#ifdef DEBUG
cout << "entering SplashScreen" << endl;
#endif
logo.SetSurface(surfaceMgr->Load("splash-logo", configUtil->String("logos") + "/krstudios.bmp"));
SplashScreen::SplashScreen(ConfigUtility* const argConfig):
config(*argConfig)
{
logo.LoadSurface(config["dir.logos"] + "krstudios.bmp");
startTick = std::chrono::steady_clock::now();
}
SplashScreen::~SplashScreen() {
surfaceMgr->Free("splash-logo");
#ifdef DEBUG
cout << "leaving SplashScreen" << endl;
#endif
//
}
//-------------------------
//Frame loop
//-------------------------
void SplashScreen::RunFrame(double delta) {
HandleEvents();
if (!loaded) {
//never repeat this
loaded = true;
//quick draw
RenderFrame();
LoadResources();
}
if (std::chrono::steady_clock::now() - start > std::chrono::duration<int>(1)) {
void SplashScreen::Update(double delta) {
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(1)) {
SetNextScene(SceneList::MAINMENU);
}
}
void SplashScreen::RenderFrame() {
SDL_FillRect(GetScreen(), 0, 0);
int x = (GetScreen()->w - logo.GetClipW()) / 2;
int y = (GetScreen()->h - logo.GetClipH()) / 2;
logo.DrawTo(GetScreen(), x, y);
SDL_Flip(GetScreen());
}
void SplashScreen::LoadResources() {
//standard
surfaceMgr->Load("font", configUtil->String("fonts") + "/pk_white_8.bmp");
surfaceMgr->Load("button", configUtil->String("interface") + "/button_menu.bmp");
//debugging
surfaceMgr->Load("elliot", configUtil->String("sprites") + "/elliot2.bmp");
surfaceMgr->Load("coa", configUtil->String("sprites") + "/coa2.bmp");
surfaceMgr->Load("flower", configUtil->String("sprites") + "/aniflower.bmp");
surfaceMgr->Load("terrain", configUtil->String("tilesets") + "/terrain.bmp");
//TODO
void SplashScreen::Render(SDL_Surface* const screen) {
logo.DrawTo(screen, (screen->w - logo.GetClipW()) / 2, (screen->h - logo.GetClipH()) / 2);
}
+11 -13
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -23,31 +23,29 @@
#define SPLASHSCREEN_HPP_
#include "base_scene.hpp"
#include "singleton.hpp"
#include "config_utility.hpp"
#include "surface_manager.hpp"
#include "image.hpp"
#include <chrono>
class SplashScreen : public BaseScene {
public:
/* Public access members */
SplashScreen();
//Public access members
SplashScreen(ConfigUtility* const);
~SplashScreen();
protected:
/* Frame loop */
void RunFrame(double delta);
void RenderFrame();
void LoadResources();
//Frame loop
void Update(double delta);
void Render(SDL_Surface* const);
bool loaded = false;
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
//shared parameters
ConfigUtility& config;
//members
std::chrono::steady_clock::time_point startTick;
Image logo;
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
};
#endif
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,20 +19,18 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef SINGLETON_HPP_
#define SINGLETON_HPP_
#ifndef ACCOUNTDATA_HPP_
#define ACCOUNTDATA_HPP_
template<typename T>
class Singleton {
public:
static T* Get() {
return &instance;
}
private:
static T instance;
#include <string>
struct AccountData {
std::string username;
//TODO: password
bool blackListed = false;
bool whiteListed = true;
int clientIndex;
};
template<typename T>
T Singleton<T>::instance;
#endif
+67
View File
@@ -0,0 +1,67 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "character_data.hpp"
void CharacterData::Update(double delta) {
if (motion.x && motion.y) {
position += motion * delta * CHARACTER_WALKING_MOD;
}
else if (motion != 0) {
position += motion * delta;
}
#ifdef GRAPHICS
sprite.Update(delta);
#endif
}
#ifdef GRAPHICS
void CharacterData::DrawTo(SDL_Surface* const dest, int camX, int camY) {
sprite.DrawTo(dest, position.x - camX, position.y - camY);
}
void CharacterData::CorrectSprite() {
//NOTE: These must correspond to the sprite sheet in use
if (motion.y > 0) {
sprite.SetYIndex(0);
}
else if (motion.y < 0) {
sprite.SetYIndex(1);
}
else if (motion.x > 0) {
sprite.SetYIndex(3);
}
else if (motion.x < 0) {
sprite.SetYIndex(2);
}
//animation
if (motion != 0) {
sprite.SetDelay(0.1);
}
else {
sprite.SetDelay(0);
sprite.SetXIndex(0);
}
}
#endif
+80
View File
@@ -0,0 +1,80 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 CHARACTERDATA_HPP_
#define CHARACTERDATA_HPP_
//POD members
#include "bbox.hpp"
#include "vector2.hpp"
#include "statistics.hpp"
//graphics
#ifdef GRAPHICS
#include "sprite_sheet.hpp"
#endif
//std namespace
#include <string>
#include <cmath>
//the speeds that the characters move
constexpr double CHARACTER_WALKING_SPEED = 140.0;
constexpr double CHARACTER_WALKING_MOD = 1.0/sqrt(2.0);
struct CharacterData {
//metadata
int owner;
std::string handle;
std::string avatar;
//world position
int mapIndex = 0;
Vector2 position = {0.0,0.0};
Vector2 motion = {0.0,0.0};
//base statistics
Statistics stats;
//TODO: equipment
//TODO: items
//TODO: buffs
//TODO: debuffs
//methods
void Update(double delta);
#ifdef GRAPHICS
void DrawTo(SDL_Surface* const, int camX, int camY);
void CorrectSprite();
#endif
//active gameplay members
//NOTE: these are lost when unloaded
#ifdef GRAPHICS
SpriteSheet sprite;
#endif
BBox bbox = {0,0,0,0};
bool inCombat = false;
int atbGauge = 0;
//TODO: stored command
};
#endif
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,16 +19,13 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef DEFINES_HPP_
#define DEFINES_HPP_
#ifndef CLIENTDATA_HPP_
#define CLIENTDATA_HPP_
#define GAME_CHANNEL 0
#define CHAT_CHANNEL 1
#include "SDL/SDL_net.h"
#define WALKING_SPEED 140
enum class CardinalDirection {
NORTH, SOUTH, EAST, WEST
struct ClientData {
IPaddress address = {0,0};
};
#endif
+64
View File
@@ -0,0 +1,64 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 COMBATDATA_HPP_
#define COMBATDATA_HPP_
//POD members
#include "vector2.hpp"
#include "bbox.hpp"
//gameplay members
#include "character_data.hpp"
#include "enemy_data.hpp"
//graphics
#ifdef GRAPHICS
#include "sprite_sheet.hpp"
#endif
//std namespace
#include <chrono>
#include <list>
#include <utility>
struct CombatData {
typedef std::chrono::steady_clock Clock;
//combatants, point to the std::map's internal pairs
std::list<std::pair<const int, CharacterData>*> characterList;
std::list<std::pair<const int, EnemyData>*> enemyList;
//world interaction
int mapIndex = 0;
Vector2 position = {0.0,0.0};
BBox bbox = {0,0,0,0};
//time interval
Clock::time_point lastTick = Clock::now();
//graphics
#ifdef GRAPHICS
SpriteSheet sprite;
#endif
};
#endif
+58
View File
@@ -0,0 +1,58 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 ENEMYDATA_HPP_
#define ENEMYDATA_HPP_
//gameplay
#include "statistics.hpp"
//graphics
#ifdef GRAPHICS
#include "sprite_sheet.hpp"
#endif
//std namespace
#include <string>
struct EnemyData {
//metadata
std::string handle;
std::string avatar;
//gameplay
Statistics stats;
//TODO: equipment
//TODO: items
//TODO: buffs
//TODO: debuffs
//active gameplay members
//NOTE: these are lost when unloaded
#ifdef GRAPHICS
SpriteSheet sprite;
#endif
int tableIndex;
int atbGauge = 0;
};
#endif
+8 -9
View File
@@ -1,23 +1,22 @@
#config
LOCALLIBS=../lib/libCommon.a
LIB=
INCLUDES=../common
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
INCLUDES+=. ../utilities ../graphics
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -DGRAPHICS
#source
SRC=$(wildcard *.cpp)
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../out
OUT=$(addprefix $(OUTDIR)/,test)
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
+36
View File
@@ -0,0 +1,36 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "account_data.hpp"
#include "character_data.hpp"
#include "client_data.hpp"
#include "combat_data.hpp"
#include "enemy_data.hpp"
#include "statistics.hpp"
/* DOCS: Sanity check, read more
* Since most/all of the files in this directory are header files, I've created
* this source file as a "sanity check", to ensure that the above header files
* are written correctly via make.
*
* Oddly enough, I'm pretty sure this is the first directory compiled in a
* clean build.
*/
+42
View File
@@ -0,0 +1,42 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 STATISTICS_HPP_
#define STATISTICS_HPP_
struct Statistics {
int level = 0;
int exp = 0;
int maxHP = 0;
int health = 0;
int maxMP = 0;
int mana = 0;
int attack = 0;
int defence = 0;
int intelligence = 0;
int resistance = 0;
int speed = 0;
float accuracy = 0.0;
float evasion = 0.0;
float luck = 0.0;
};
#endif
+81 -13
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,16 +22,88 @@
#include "image.hpp"
#include <stdexcept>
#include <sstream>
Image& Image::operator=(Image const& rhs) {
//don't screw yourself
if (this == &rhs) {
return *this;
}
FreeSurface();
//Copy the other Image's stuff
surface = rhs.surface;
clip = rhs.clip;
local = false;
}
Image& Image::operator=(Image&& rhs) {
//don't screw yourself
if (this == &rhs) {
return *this;
}
FreeSurface();
//Steal the other Image's stuff
surface = rhs.surface;
clip = rhs.clip;
local = rhs.local;
rhs.surface = nullptr;
rhs.clip = {0, 0, 0, 0};
rhs.local = false;
}
SDL_Surface* Image::LoadSurface(std::string fname) {
FreeSurface();
SDL_Surface* p = SDL_LoadBMP(fname.c_str());
if (!p) {
throw(std::runtime_error(std::string() + "Failed to load file: " + fname));
std::ostringstream os;
os << "Failed to load file: " << fname;
throw(std::runtime_error(os.str()));
}
surface = p;
SetTransparentColor(255, 0, 255); //default
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
local = true;
SetTransparentColor(255, 0, 255); //default
return surface;
}
SDL_Surface* Image::CreateSurface(Uint16 w, Uint16 h) {
FreeSurface();
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
SDL_Surface* p = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, rmask, gmask, bmask, amask);
if (!p) {
throw(std::runtime_error("Failed to create Image surface"));
}
surface = p;
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
local = true;
SetTransparentColor(255, 0, 255); //default
return surface;
}
SDL_Surface* Image::SetSurface(SDL_Surface* p) {
FreeSurface();
if (!p) {
throw(std::invalid_argument("No surface pointer provided"));
}
surface = p;
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
local = false;
return surface;
}
@@ -44,16 +116,6 @@ void Image::FreeSurface() {
clip = {0, 0, 0, 0};
}
SDL_Surface* Image::SetSurface(SDL_Surface* p) {
if (!p) {
throw(std::invalid_argument("No surface pointer provided"));
}
surface = p;
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
local = false;
return surface;
}
void Image::DrawTo(SDL_Surface* dest, Sint16 x, Sint16 y) {
if (!surface) {
throw(std::logic_error("No image surface to draw"));
@@ -66,6 +128,9 @@ void Image::SetTransparentColor(Uint8 r, Uint8 g, Uint8 b) {
if (!surface) {
throw(std::logic_error("Failed to set the transparent color"));
}
if (!local) {
throw(std::logic_error("Cannot set the transparent color of a non-local surface"));
}
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, SDL_MapRGB(surface->format, r, g, b));
}
@@ -73,5 +138,8 @@ void Image::ClearTransparentColor() {
if (!surface) {
throw(std::logic_error("Failed to clear the transparent color"));
}
if (!local) {
throw(std::logic_error("Cannot clear the transparent color of a non-local surface"));
}
SDL_SetColorKey(surface, 0, 0);
}
+11 -4
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -28,14 +28,21 @@
class Image {
public:
Image() = default;
Image(Image const& rhs) { *this = rhs; }
Image(Image&& rhs) { *this = std::move(rhs); }
Image(std::string fname) { LoadSurface(fname); }
Image(Uint16 w, Uint16 h) { CreateSurface(w, h); }
Image(SDL_Surface* p) { SetSurface(p); }
~Image() { FreeSurface(); }
SDL_Surface* LoadSurface(std::string fname);
void FreeSurface();
Image& operator=(Image const&);
Image& operator=(Image&&);
SDL_Surface* LoadSurface(std::string fname);
SDL_Surface* CreateSurface(Uint16 w, Uint16 h);
SDL_Surface* SetSurface(SDL_Surface*);
SDL_Surface* GetSurface() const { return surface; }
void FreeSurface();
void DrawTo(SDL_Surface* const, Sint16 x, Sint16 y);
@@ -53,7 +60,7 @@ public:
Uint16 GetClipW() const { return clip.w; }
Uint16 GetClipH() const { return clip.h; }
bool GetLocal() { return local; }
bool GetLocal() const { return local; }
void SetTransparentColor(Uint8 r, Uint8 g, Uint8 b);
void ClearTransparentColor();
+37
View File
@@ -0,0 +1,37 @@
#config
INCLUDES+=. ../map
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+102
View File
@@ -0,0 +1,102 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 "sprite_sheet.hpp"
#include <stdexcept>
#include <sstream>
void SpriteSheet::Update(double delta) {
if (delay && (tick += delta) >= delay) {
if (++xIndex >= xCount) {
xIndex = 0;
}
tick = 0;
}
image.SetClipX(xIndex * image.GetClipW());
image.SetClipY(yIndex * image.GetClipH());
}
SDL_Surface* SpriteSheet::LoadSurface(std::string fname, Uint16 xCellCount, Uint16 yCellCount) {
image.LoadSurface(fname);
xCount = xCellCount;
yCount = yCellCount;
image.SetClipW(image.GetSurface()->w / xCount);
image.SetClipH(image.GetSurface()->h / yCount);
xIndex = yIndex = 0;
delay = tick = 0.0;
}
SDL_Surface* SpriteSheet::SetSurface(SDL_Surface* surface, Uint16 xCellCount, Uint16 yCellCount) {
image.SetSurface(surface);
xCount = xCellCount;
yCount = yCellCount;
image.SetClipW(image.GetSurface()->w / xCount);
image.SetClipH(image.GetSurface()->h / yCount);
xIndex = yIndex = 0;
delay = tick = 0.0;
}
void SpriteSheet::FreeSurface() {
image.FreeSurface();
xCount = yCount = 0;
xIndex = yIndex = 0;
delay = tick = 0.0;
}
Uint16 SpriteSheet::SetXCount(Uint16 i) {
xIndex = 0;
return xCount = i;
}
Uint16 SpriteSheet::SetYCount(Uint16 i) {
yIndex = 0;
return yCount = i;
}
Uint16 SpriteSheet::SetXIndex(Uint16 i) {
if (i > xCount) {
std::ostringstream os;
os << "Cannot set x index to " << i;
throw(std::invalid_argument(os.str()));
}
return xIndex = i;
}
Uint16 SpriteSheet::SetYIndex(Uint16 i) {
if (i > yCount) {
std::ostringstream os;
os << "Cannot set y index to " << i;
throw(std::invalid_argument(os.str()));
}
return yIndex = i;
}
double SpriteSheet::SetDelay(double d) {
tick = 0;
return delay = d;
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -24,39 +24,43 @@
#include "image.hpp"
#include "SDL/SDL.h"
class SpriteSheet {
public:
SpriteSheet() = default;
SpriteSheet(SDL_Surface* s, Uint16 w, Uint16 h) { SetSurface(s, w, h); }
~SpriteSheet() = default;
SpriteSheet(std::string fname, Uint16 xCellCount, Uint16 yCellCount) { LoadSurface(fname, xCellCount, yCellCount); }
SpriteSheet(SDL_Surface* surface, Uint16 xCellCount, Uint16 yCellCount) { SetSurface(surface, xCellCount, yCellCount); }
~SpriteSheet() { FreeSurface(); };
void Update(double delta);
SDL_Surface* SetSurface(SDL_Surface* const, Uint16 w, Uint16 h);
SDL_Surface* GetSurface() const { return image.GetSurface(); }
SDL_Surface* LoadSurface(std::string fname, Uint16 xCellCount, Uint16 yCellCount);
SDL_Surface* SetSurface(SDL_Surface* surface, Uint16 xCellCount, Uint16 yCellCount);
SDL_Surface* GetSurface() { return image.GetSurface(); }
void FreeSurface();
void DrawTo(SDL_Surface* const dest, Sint16 x, Sint16 y) { image.DrawTo(dest, x, y); }
//Accessors and Mutators
double SetDelay(double i) { return delay = i; }
//accessors and mutators
Image* GetImage() { return &image; } //OO breaker
Uint16 SetXCount(Uint16);
Uint16 SetYCount(Uint16);
Uint16 SetXIndex(Uint16);
Uint16 SetYIndex(Uint16);
Uint16 GetXCount() const { return xCount; }
Uint16 GetYCount() const { return yCount; }
Uint16 GetXIndex() const { return xIndex; }
Uint16 GetYIndex() const { return yIndex; }
double SetDelay(double d);
double GetDelay() const { return delay; }
int SetCurrentFrame(int i) { return currentFrame = i; }
int SetCurrentStrip(int i) { return currentStrip = i; }
Uint16 GetFrameWidth() const { return image.GetClipW(); }
Uint16 GetFrameHeight() const { return image.GetClipH(); }
int GetCurrentFrame() const { return currentFrame; };
int GetCurrentStrip() const { return currentStrip; };
int GetMaxFrames() const { return maxFrames; }
int GetMaxStrips() const { return maxStrips; }
private:
Image image;
int currentFrame = 0, maxFrames = 0;
int currentStrip = 0, maxStrips = 0;
double delay = 0, ticks = 0;
Uint16 xCount = 0, yCount = 0; //number of cells
Uint16 xIndex = 0, yIndex = 0; //current cell being drawn
double delay = 0.0, tick = 0.0;
};
#endif
+61
View File
@@ -0,0 +1,61 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "tile_sheet.hpp"
void TileSheet::Load(std::string fname, int xc, int yc) {
XCount = xc;
YCount = yc;
image.LoadSurface(fname);
image.SetClipW(image.GetClipW()/XCount);
image.SetClipH(image.GetClipH()/YCount);
}
void TileSheet::Unload() {
image.FreeSurface();
XCount = YCount = 0;
}
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile) {
//0 is invisible
if (tile == 0) return;
image.SetClipX((tile-1) % XCount * image.GetClipW());
image.SetClipY((tile-1) / XCount * image.GetClipH());
image.DrawTo(dest, x, y);
}
void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY) {
Region::type_t tile = 0;
for (register int i = 0; i < REGION_WIDTH; ++i) {
for (register int j = 0; j < REGION_HEIGHT; ++j) {
for (register int k = 0; k < REGION_DEPTH; ++k) {
tile = region->GetTile(i, j, k);
//0 is invisible
if (tile == 0) continue;
image.SetClipX((tile-1) % XCount * image.GetClipW());
image.SetClipY((tile-1) / XCount * image.GetClipH());
image.DrawTo(dest,
(region->GetX() + i) * image.GetClipW() - camX,
(region->GetY() + j) * image.GetClipH() - camY);
}
}
}
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,31 +19,36 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef SURFACEMANAGER_HPP_
#define SURFACEMANAGER_HPP_
#ifndef TILESHEET_HPP_
#define TILESHEET_HPP_
#include "SDL/SDL.h"
#include "region.hpp"
#include "image.hpp"
#include <map>
#include <string>
class SurfaceManager {
class TileSheet {
public:
SurfaceManager() = default;
~SurfaceManager() noexcept { FreeAll(); }
TileSheet() = default;
TileSheet(std::string f, int x, int y) { Load(f, x, y); }
~TileSheet() = default;
SDL_Surface* Load(std::string key, std::string fname);
SDL_Surface* Reload(std::string key, std::string fname);
SDL_Surface* Get(std::string key);
SDL_Surface* Set(std::string key, SDL_Surface* ptr);
void Free(std::string key);
void FreeAll();
void Load(std::string fname, int XCount, int YCount);
void Unload();
SDL_Surface* operator[](std::string key) { return Get(key); };
void DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile);
void DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY);
//accessors
Image* GetImage() { return &image; }
int GetXCount() { return XCount; }
int GetYCount() { return YCount; }
int GetTileW() { return image.GetClipW(); }
int GetTileH() { return image.GetClipH(); }
private:
SDL_Surface* LoadSurface(std::string key, std::string fname);
typedef std::map<std::string, SDL_Surface*> MapType;
MapType surfaceMap;
Image image;
int XCount = 0, YCount = 0;
};
#endif
+8 -33
View File
@@ -1,36 +1,11 @@
#config
LOCALLIBS=
LIB=
INCLUDES=
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
#source
SRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
#output
OUTDIR=../lib
OUT=$(addprefix $(OUTDIR)/,libCommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
all:
$(MAKE) -C gameplay
$(MAKE) -C graphics
$(MAKE) -C map
$(MAKE) -C network
$(MAKE) -C script
$(MAKE) -C ui
$(MAKE) -C utilities
clean:
$(RM) *.o *.a *.exe
+37
View File
@@ -0,0 +1,37 @@
#config
INCLUDES+=. ../utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+60
View File
@@ -0,0 +1,60 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "map_allocator.hpp"
#include <stdexcept>
void BlankAllocator::Create(Region** const ptr, int x, int y) {
(*ptr) = new Region(x, y);
}
void BlankAllocator::Unload(Region* const ptr) {
delete ptr;
}
void LuaAllocator::Create(Region** const ptr, int x, int y) {
//something to work on
(*ptr) = new Region(x, y);
//API hook
lua_getglobal(state, "map");
lua_getfield(state, -1, "create");
lua_pushlightuserdata(state, *ptr);
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
}
lua_pop(state, 1);
}
void LuaAllocator::Unload(Region* const ptr) {
//API hook
lua_getglobal(state, "map");
lua_getfield(state, -1, "unload");
lua_pushlightuserdata(state, ptr);
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
}
lua_pop(state, 1);
//clean up the memory
delete ptr;
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,22 +19,30 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef INFORMATIONMANAGER_HPP_
#define INFORMATIONMANAGER_HPP_
#ifndef MAPALLOCATOR_HPP_
#define MAPALLOCATOR_HPP_
class InformationManager {
#include "region.hpp"
#include "lua/lua.hpp"
class BlankAllocator {
public:
int SetClientIndex(int i) { return clientIndex = i; }
int GetClientIndex() { return clientIndex; }
void ResetClientIndex() { clientIndex = -1; }
//one player at a time
int SetPlayerIndex(int i) { return playerIndex = i; }
int GetPlayerIndex() { return playerIndex; }
void ResetPlayerIndex() { playerIndex = -1; }
void Create(Region** const, int x, int y);
void Unload(Region* const);
private:
int clientIndex = -1;
int playerIndex = -1;
//
};
class LuaAllocator {
public:
void Create(Region** const, int x, int y);
void Unload(Region* const);
lua_State* SetLuaState(lua_State* L) { return state = L; }
lua_State* GetLuaState() { return state; }
private:
lua_State* state = nullptr;
};
#endif
+66
View File
@@ -0,0 +1,66 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "map_file_format.hpp"
#include <stdexcept>
void DummyFormat::Load(Region** const ptr, int x, int y) {
//EMPTY
}
void DummyFormat::Save(Region* const ptr) {
//EMPTY
}
void LuaFormat::Load(Region** const ptr, int x, int y) {
//something to load into
if (!(*ptr)) {
(*ptr) = new Region(x, y);
}
//API hook
lua_getglobal(state, "map");
lua_getfield(state, -1, "load");
lua_pushlightuserdata(state, *ptr);
lua_pushstring(state, saveDir.c_str());
if (lua_pcall(state, 2, 1, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
}
if (lua_toboolean(state, -1) == false) {
delete (*ptr);
(*ptr) = nullptr;
}
lua_pop(state, 2);
}
void LuaFormat::Save(Region* const ptr) {
//API hook
lua_getglobal(state, "map");
lua_getfield(state, -1, "save");
lua_pushlightuserdata(state, ptr);
lua_pushstring(state, saveDir.c_str());
if (lua_pcall(state, 2, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
}
lua_pop(state, 1);
}
+60
View File
@@ -0,0 +1,60 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 MAPFILEFORMAT_HPP_
#define MAPFILEFORMAT_HPP_
#include "region.hpp"
#include "lua/lua.hpp"
#include <string>
class DummyFormat {
public:
void Load(Region** const, int x, int y);
void Save(Region* const);
std::string SetSaveDir(std::string s) { return saveDir = s; }
std::string GetSaveDir() { return saveDir; }
private:
std::string saveDir;
};
//TODO: verbose save file format
//TODO: compact save file format
class LuaFormat {
public:
void Load(Region** const, int x, int y);
void Save(Region* const);
std::string SetSaveDir(std::string s) { return saveDir = s; }
std::string GetSaveDir() { return saveDir; }
lua_State* SetLuaState(lua_State* L) { return state = L; }
lua_State* GetLuaState() { return state; }
private:
std::string saveDir;
lua_State* state = nullptr;
};
#endif
+39
View File
@@ -0,0 +1,39 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "region.hpp"
Region::Region(int argX, int argY):
x(argX),
y(argY)
{
for (register int i = 0; i < REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH; ++i) {
*(reinterpret_cast<type_t*>(tiles) + i) = 0;
}
}
Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
return tiles[x][y][z] = v;
}
Region::type_t Region::GetTile(int x, int y, int z) {
return tiles[x][y][z];
}
+50
View File
@@ -0,0 +1,50 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 REGION_HPP_
#define REGION_HPP_
#define REGION_WIDTH 20
#define REGION_HEIGHT 20
#define REGION_DEPTH 3
class Region {
public:
typedef unsigned short type_t;
Region() = delete;
Region(int x, int y);
~Region() = default;
type_t SetTile(int x, int y, int z, type_t v);
type_t GetTile(int x, int y, int z);
//accessors
int GetX() const { return x; }
int GetY() const { return y; }
private:
const int x;
const int y;
type_t tiles[REGION_WIDTH][REGION_HEIGHT][REGION_DEPTH];
};
#endif
+67
View File
@@ -0,0 +1,67 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "region_pager.hpp"
#include "utility.hpp"
Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) {
Region* ptr = GetRegion(x, y);
return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v);
}
Region::type_t RegionPagerBase::GetTile(int x, int y, int z) {
Region* ptr = GetRegion(x, y);
return ptr->GetTile(x - ptr->GetX(), y - ptr->GetY(), z);
}
Region* RegionPagerBase::GetRegion(int x, int y) {
//snap the coords
x = snapToBase(REGION_WIDTH, x);
y = snapToBase(REGION_HEIGHT, y);
//get the region by various means
Region* ptr = nullptr;
ptr = FindRegion(x, y);
if (ptr) return ptr;
ptr = LoadRegion(x, y);
if (ptr) return ptr;
return CreateRegion(x, y);
}
Region* RegionPagerBase::FindRegion(int x, int y) {
//snap the coords
x = snapToBase(REGION_WIDTH, x);
y = snapToBase(REGION_HEIGHT, y);
//find the region
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
if ((*it)->GetX() == x && (*it)->GetY() == y) {
return *it;
}
}
return nullptr;
}
Region* RegionPagerBase::PushRegion(Region* ptr) {
regionList.push_front(ptr);
return regionList.front();
}
+133
View File
@@ -0,0 +1,133 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 REGIONPAGER_HPP_
#define REGIONPAGER_HPP_
#include "region.hpp"
#include "utility.hpp"
#include <list>
class RegionPagerBase {
public:
RegionPagerBase() {};
virtual ~RegionPagerBase() {};
//tile manipulation
Region::type_t SetTile(int x, int y, int z, Region::type_t v);
Region::type_t GetTile(int x, int y, int z);
//region manipulation
Region* GetRegion(int x, int y);
Region* FindRegion(int x, int y);
Region* PushRegion(Region*);
//interface
virtual Region* LoadRegion(int x, int y) = 0;
virtual Region* SaveRegion(int x, int y) = 0;
virtual Region* CreateRegion(int x, int y) = 0;
virtual void UnloadRegion(int x, int y) = 0;
//TODO: delete existing regions
//accessors & mutators
std::list<Region*>* GetContainer() { return &regionList; }
protected:
std::list<Region*> regionList;
};
template<typename Allocator, typename FileFormat>
class RegionPager : public RegionPagerBase {
public:
RegionPager() {};
~RegionPager() {
UnloadAll();
}
Region* LoadRegion(int x, int y) {
//snap the coords
x = snapToBase(REGION_WIDTH, x);
y = snapToBase(REGION_HEIGHT, y);
//load the region if possible
Region* ptr = nullptr;
format.Load(&ptr, x, y);
if (ptr) {
return PushRegion(ptr);
}
return nullptr;
}
Region* SaveRegion(int x, int y) {
//snap the coords
x = snapToBase(REGION_WIDTH, x);
y = snapToBase(REGION_HEIGHT, y);
//find & save the region
Region* ptr = FindRegion(x, y);
if (ptr) {
format.Save(ptr);
}
return ptr;
}
Region* CreateRegion(int x, int y) {
//snap the coords
x = snapToBase(REGION_WIDTH, x);
y = snapToBase(REGION_HEIGHT, y);
//create and push the object
Region* ptr = nullptr;
allocator.Create(&ptr, x, y);
return PushRegion(ptr);
}
void UnloadRegion(int x, int y) {
//snap the coords
x = snapToBase(REGION_WIDTH, x);
y = snapToBase(REGION_HEIGHT, y);
//custom loop
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) {
if ((*it)->GetX() == x && (*it)->GetY() == y) {
allocator.Unload(*it);
it = regionList.erase(it);
continue;
}
++it;
}
}
void UnloadAll() {
for (auto& it : regionList) {
allocator.Unload(it);
}
regionList.clear();
}
//accessors
Allocator* GetAllocator() { return &allocator; }
FileFormat* GetFormat() { return &format; }
protected:
Allocator allocator;
FileFormat format;
};
#endif
+37
View File
@@ -0,0 +1,37 @@
#config
INCLUDES+=. ../gameplay ../map ../utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+433
View File
@@ -0,0 +1,433 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "serial.hpp"
#include "map_allocator.hpp"
#include "statistics.hpp"
#include <cstring>
//-------------------------
//Convenience Macros
//-------------------------
#define SERIALIZE(buffer, data, size) memcpy(buffer, data, size); buffer += size;
#define DESERIALIZE(buffer, data, size) memcpy(data, buffer, size); buffer += size;
//-------------------------
//internal serialization functions
//-------------------------
void serializeType(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
}
void serializeServer(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//server info
SERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int));
SERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
SERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int));
}
void serializeClient(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//indexes
SERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int));
SERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int));
SERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int));
//texts
SERIALIZE(buffer, packet->clientInfo.username, PACKET_STRING_SIZE);
//TODO: password
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
}
void serializeRegionFormat(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//format
SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
}
void serializeRegionContent(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//format
SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
//content
for (register int i = 0; i < REGION_WIDTH; i++) {
for (register int j = 0; j < REGION_HEIGHT; j++) {
for (register int k = 0; k < REGION_DEPTH; k++) {
*reinterpret_cast<Region::type_t*>(buffer) = packet->regionInfo.region->GetTile(i, j, k);
buffer += sizeof(Region::type_t);
}
}
}
}
void serializeCombat(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//integers
SERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
SERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
//TODO: more comabat info
}
void serializeStatistics(Statistics* stats, char* buffer) {
//integers
SERIALIZE(buffer, &stats->level, sizeof(int));
SERIALIZE(buffer, &stats->exp, sizeof(int));
SERIALIZE(buffer, &stats->maxHP, sizeof(int));
SERIALIZE(buffer, &stats->health, sizeof(int));
SERIALIZE(buffer, &stats->maxMP, sizeof(int));
SERIALIZE(buffer, &stats->mana, sizeof(int));
SERIALIZE(buffer, &stats->attack, sizeof(int));
SERIALIZE(buffer, &stats->defence, sizeof(int));
SERIALIZE(buffer, &stats->intelligence, sizeof(int));
SERIALIZE(buffer, &stats->resistance, sizeof(int));
SERIALIZE(buffer, &stats->speed, sizeof(int));
//floats
SERIALIZE(buffer, &stats->accuracy, sizeof(float));
SERIALIZE(buffer, &stats->evasion, sizeof(float));
SERIALIZE(buffer, &stats->luck, sizeof(float));
}
void serializeCharacter(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//indexes
SERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int));
SERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int));
SERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int));
//texts
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
//vectors
SERIALIZE(buffer, &packet->characterInfo.position.x, sizeof(double));
SERIALIZE(buffer, &packet->characterInfo.position.y, sizeof(double));
SERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
SERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
//stats structure
serializeStatistics(&packet->characterInfo.stats, buffer);
buffer += sizeof(Statistics);
}
void serializeEnemy(SerialPacket* packet, char* buffer) {
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//texts
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
//stats structure
serializeStatistics(&packet->characterInfo.stats, buffer);
buffer += sizeof(Statistics);
}
//-------------------------
//internal deserialization functions
//-------------------------
void deserializeType(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
}
void deserializeServer(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//server info
DESERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int));
DESERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
DESERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int));
}
void deserializeClient(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//indexes
DESERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int));
DESERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int));
DESERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int));
//texts
DESERIALIZE(buffer, packet->clientInfo.username, PACKET_STRING_SIZE);
//TODO: password
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
}
void deserializeRegionFormat(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//format
DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
}
void deserializeRegionContent(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//format
DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
//an object to work on
BlankAllocator().Create(
&packet->regionInfo.region,
packet->regionInfo.x,
packet->regionInfo.y
);
//content
for (register int i = 0; i < REGION_WIDTH; i++) {
for (register int j = 0; j < REGION_HEIGHT; j++) {
for (register int k = 0; k < REGION_DEPTH; k++) {
packet->regionInfo.region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
buffer += sizeof(Region::type_t);
}
}
}
}
void deserializeCombat(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//integers
DESERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
DESERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
//TODO: more comabat info
}
void deserializeStatistics(Statistics* stats, char* buffer) {
//integers
DESERIALIZE(buffer, &stats->level, sizeof(int));
DESERIALIZE(buffer, &stats->exp, sizeof(int));
DESERIALIZE(buffer, &stats->maxHP, sizeof(int));
DESERIALIZE(buffer, &stats->health, sizeof(int));
DESERIALIZE(buffer, &stats->maxMP, sizeof(int));
DESERIALIZE(buffer, &stats->mana, sizeof(int));
DESERIALIZE(buffer, &stats->attack, sizeof(int));
DESERIALIZE(buffer, &stats->defence, sizeof(int));
DESERIALIZE(buffer, &stats->intelligence, sizeof(int));
DESERIALIZE(buffer, &stats->resistance, sizeof(int));
DESERIALIZE(buffer, &stats->speed, sizeof(int));
//floats
DESERIALIZE(buffer, &stats->accuracy, sizeof(float));
DESERIALIZE(buffer, &stats->evasion, sizeof(float));
DESERIALIZE(buffer, &stats->luck, sizeof(float));
}
void deserializeCharacter(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//indexes
DESERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int));
DESERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int));
DESERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int));
//texts
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
//vectors
DESERIALIZE(buffer, &packet->characterInfo.position.x, sizeof(double));
DESERIALIZE(buffer, &packet->characterInfo.position.y, sizeof(double));
DESERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
DESERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
//stats structure
deserializeStatistics(&packet->characterInfo.stats, buffer);
buffer += sizeof(Statistics);
}
void deserializeEnemy(SerialPacket* packet, char* buffer) {
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
//texts
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
//stats structure
deserializeStatistics(&packet->characterInfo.stats, buffer);
buffer += sizeof(Statistics);
}
//-------------------------
//the interface functions
//-------------------------
void serialize(SerialPacket* packet, void* buffer) {
switch(packet->meta.type) {
//no extra data
case SerialPacket::Type::NONE:
case SerialPacket::Type::PING:
case SerialPacket::Type::PONG:
case SerialPacket::Type::BROADCAST_REQUEST:
//all rejections
case SerialPacket::Type::BROADCAST_REJECTION:
case SerialPacket::Type::JOIN_REJECTION:
case SerialPacket::Type::REGION_REJECTION:
case SerialPacket::Type::CHARACTER_REJECTION:
case SerialPacket::Type::ENEMY_REJECTION:
case SerialPacket::Type::COMBAT_REJECTION:
serializeType(packet, reinterpret_cast<char*>(buffer));
break;
//server info
case SerialPacket::Type::BROADCAST_RESPONSE:
serializeServer(packet, reinterpret_cast<char*>(buffer));
break;
//client info
case SerialPacket::Type::JOIN_REQUEST:
case SerialPacket::Type::JOIN_RESPONSE:
case SerialPacket::Type::SYNCHRONIZE:
case SerialPacket::Type::DISCONNECT:
case SerialPacket::Type::SHUTDOWN:
serializeClient(packet, reinterpret_cast<char*>(buffer));
break;
//region info
case SerialPacket::Type::REGION_REQUEST:
serializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
break;
case SerialPacket::Type::REGION_CONTENT:
serializeRegionContent(packet, reinterpret_cast<char*>(buffer));
break;
//combat info
case SerialPacket::Type::COMBAT_ENTER:
case SerialPacket::Type::COMBAT_EXIT:
serializeCombat(packet, reinterpret_cast<char*>(buffer));
break;
//character info
case SerialPacket::Type::CHARACTER_NEW:
case SerialPacket::Type::CHARACTER_DELETE:
case SerialPacket::Type::CHARACTER_UPDATE:
case SerialPacket::Type::CHARACTER_STATS_REQUEST:
case SerialPacket::Type::CHARACTER_STATS_RESPONSE:
serializeCharacter(packet, reinterpret_cast<char*>(buffer));
break;
//enemy info
case SerialPacket::Type::ENEMY_NEW:
case SerialPacket::Type::ENEMY_DELETE:
case SerialPacket::Type::ENEMY_UPDATE:
case SerialPacket::Type::ENEMY_STATS_REQUEST:
case SerialPacket::Type::ENEMY_STATS_RESPONSE:
serializeEnemy(packet, reinterpret_cast<char*>(buffer));
break;
}
}
void deserialize(SerialPacket* packet, void* buffer) {
//find the type, so that you can actually deserialize the packet!
deserializeType(packet, reinterpret_cast<char*>(buffer));
switch(packet->meta.type) {
//no extra data
case SerialPacket::Type::NONE:
case SerialPacket::Type::PING:
case SerialPacket::Type::PONG:
case SerialPacket::Type::BROADCAST_REQUEST:
//all rejections
case SerialPacket::Type::BROADCAST_REJECTION:
case SerialPacket::Type::JOIN_REJECTION:
case SerialPacket::Type::REGION_REJECTION:
case SerialPacket::Type::CHARACTER_REJECTION:
case SerialPacket::Type::ENEMY_REJECTION:
case SerialPacket::Type::COMBAT_REJECTION:
//NOTHING
break;
//server info
case SerialPacket::Type::BROADCAST_RESPONSE:
deserializeServer(packet, reinterpret_cast<char*>(buffer));
break;
//client info
case SerialPacket::Type::JOIN_REQUEST:
case SerialPacket::Type::JOIN_RESPONSE:
case SerialPacket::Type::SYNCHRONIZE:
case SerialPacket::Type::DISCONNECT:
case SerialPacket::Type::SHUTDOWN:
deserializeClient(packet, reinterpret_cast<char*>(buffer));
break;
//region info
case SerialPacket::Type::REGION_REQUEST:
deserializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
break;
case SerialPacket::Type::REGION_CONTENT:
deserializeRegionContent(packet, reinterpret_cast<char*>(buffer));
break;
//combat info
case SerialPacket::Type::COMBAT_ENTER:
case SerialPacket::Type::COMBAT_EXIT:
serializeCombat(packet, reinterpret_cast<char*>(buffer));
break;
//character info
case SerialPacket::Type::CHARACTER_NEW:
case SerialPacket::Type::CHARACTER_DELETE:
case SerialPacket::Type::CHARACTER_UPDATE:
case SerialPacket::Type::CHARACTER_STATS_REQUEST:
case SerialPacket::Type::CHARACTER_STATS_RESPONSE:
deserializeCharacter(packet, reinterpret_cast<char*>(buffer));
break;
//enemy info
case SerialPacket::Type::ENEMY_NEW:
case SerialPacket::Type::ENEMY_DELETE:
case SerialPacket::Type::ENEMY_UPDATE:
case SerialPacket::Type::ENEMY_STATS_REQUEST:
case SerialPacket::Type::ENEMY_STATS_RESPONSE:
serializeEnemy(packet, reinterpret_cast<char*>(buffer));
break;
}
}
+38
View File
@@ -0,0 +1,38 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 SERIAL_HPP_
#define SERIAL_HPP_
#include "serial_packet.hpp"
/* NOTE: Keep the PACKET_BUFFER_SIZE up to date
* NOTE: REGION_CONTENT is currently the largest type of packet
* map content: REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizoeof(region::type_t)
* map format: sizeof(int) * 3
* metadata: sizeof(SerialPacket::Type)
*/
#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 3 + sizeof(SerialPacket::Type)
void serialize(SerialPacket* const, void* dest);
void deserialize(SerialPacket* const, void* src);
#endif
+175
View File
@@ -0,0 +1,175 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 SERIALPACKET_HPP_
#define SERIALPACKET_HPP_
#include "vector2.hpp"
#include "region.hpp"
#include "statistics.hpp"
#include "SDL/SDL_net.h"
#define NETWORK_VERSION 20140528
#define PACKET_STRING_SIZE 100
union SerialPacket {
//types of packets
enum class Type {
//default: there is something wrong
NONE = 0,
//keep alive
PING = 1,
PONG = 2,
//searching for a server to join
BROADCAST_REQUEST = 3,
BROADCAST_RESPONSE = 4,
BROADCAST_REJECTION = 5,
//try to join the server
JOIN_REQUEST = 6,
JOIN_RESPONSE = 7,
JOIN_REJECTION = 8,
//mass update
SYNCHRONIZE = 9,
//disconnect from the server
DISCONNECT = 10,
//shut down the server
SHUTDOWN = 11,
//map data
REGION_REQUEST = 12,
REGION_CONTENT = 13,
REGION_REJECTION = 14,
//combat data
COMBAT_ENTER = 15,
COMBAT_EXIT = 16,
COMBAT_UPDATE = 17,
COMBAT_REJECTION = 18,
//character data
CHARACTER_NEW = 19,
CHARACTER_DELETE = 20,
CHARACTER_UPDATE = 21,
CHARACTER_STATS_REQUEST = 22,
CHARACTER_STATS_RESPONSE = 23,
CHARACTER_REJECTION = 24,
//enemy data
ENEMY_NEW = 25,
ENEMY_DELETE = 26,
ENEMY_UPDATE = 27,
ENEMY_STATS_REQUEST = 28,
ENEMY_STATS_RESPONSE = 29,
ENEMY_REJECTION = 30,
//more packet types go here
//not used
LAST,
};
//metadata on the packet itself
struct Metadata {
Type type;
IPaddress srcAddress;
}meta;
//info about the server
struct ServerInformation {
Metadata meta;
int networkVersion;
char name[PACKET_STRING_SIZE];
int playerCount;
}serverInfo;
//info about the client
struct ClientInformation {
Metadata meta;
int clientIndex;
int accountIndex;
int characterIndex;
char username[PACKET_STRING_SIZE];
//TODO: password
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
}clientInfo;
//info about a region
struct RegionInformation {
Metadata meta;
int mapIndex;
int x, y;
Region* region;
}regionInfo;
//info about a combat scenario
struct CombatInformation {
Metadata meta;
int combatIndex;
int difficulty;
//TODO: background image, based on terrain type
//TODO: array of combatants
//TODO: rewards
}combatInfo;
//info about a character
struct CharacterInformation {
Metadata meta;
int clientIndex;
int accountIndex;
int characterIndex;
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
int mapIndex;
Vector2 position;
Vector2 motion;
Statistics stats;
}characterInfo;
//info about an enemy
struct EnemyInformation {
Metadata meta;
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
Statistics stats;
}enemyInfo;
//defaults
SerialPacket() {
meta.type = Type::NONE;
meta.srcAddress = {0,0};
}
};
#endif
+224
View File
@@ -0,0 +1,224 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 "udp_network_utility.hpp"
#include "serial.hpp"
#include <stdexcept>
//DOCS: memset() is used before sending a packet to remove old data; you don't want to send sensitive data over the network
//NOTE: don't confuse SerialPacket with UDPpacket
void UDPNetworkUtility::Open(int port) {
socket = SDLNet_UDP_Open(port);
packet = SDLNet_AllocPacket(PACKET_BUFFER_SIZE);
if (!socket || !packet) {
Close();
throw(std::runtime_error("Failed to open UDPNetworkUtility"));
}
}
void UDPNetworkUtility::Close() {
SDLNet_UDP_Close(socket);
SDLNet_FreePacket(packet);
socket = nullptr;
packet = nullptr;
}
//-------------------------
//bind to a channel
//-------------------------
int UDPNetworkUtility::Bind(const char* ip, int port, int channel) {
IPaddress add;
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
throw(std::runtime_error("Failed to resolve a host"));
}
return Bind(&add, channel);
}
int UDPNetworkUtility::Bind(IPaddress* add, int channel) {
int ret = SDLNet_UDP_Bind(socket, channel, add);
if (ret < 0) {
throw(std::runtime_error("Failed to bind to a channel"));
}
return ret;
}
void UDPNetworkUtility::Unbind(int channel) {
SDLNet_UDP_Unbind(socket, channel);
}
//-------------------------
//send a buffer
//-------------------------
int UDPNetworkUtility::SendTo(const char* ip, int port, void* data, int len) {
IPaddress add;
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
throw(std::runtime_error("Failed to resolve a host"));
}
SendTo(&add, data, len);
}
int UDPNetworkUtility::SendTo(IPaddress* add, void* data, int len) {
if (len > packet->maxlen) {
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
}
memset(packet->data, 0, packet->maxlen);
memcpy(packet->data, data, len);
packet->len = len;
packet->address = *add;
int ret = SDLNet_UDP_Send(socket, -1, packet);
if (ret <= 0) {
throw(std::runtime_error("Failed to send a packet"));
}
return ret;
}
int UDPNetworkUtility::SendTo(int channel, void* data, int len) {
if (len > packet->maxlen) {
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
}
memset(packet->data, 0, packet->maxlen);
memcpy(packet->data, data, len);
packet->len = len;
int ret = SDLNet_UDP_Send(socket, channel, packet);
if (ret <= 0) {
throw(std::runtime_error("Failed to send a packet"));
}
return ret;
}
int UDPNetworkUtility::SendToAllChannels(void* data, int len) {
if (len > packet->maxlen) {
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
}
memset(packet->data, 0, packet->maxlen);
memcpy(packet->data, data, len);
packet->len = len;
int sent = 0;
//send to all bound channels
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
sent += SDLNet_UDP_Send(socket, i, packet);
}
}
return sent;
}
//TODO: put a void* and int* parameter list here
int UDPNetworkUtility::Receive() {
memset(packet->data, 0, packet->maxlen);
int ret = SDLNet_UDP_Recv(socket, packet);
if (ret < 0) {
throw(std::runtime_error("Unknown network error occured"));
}
return ret;
}
//-------------------------
//send a SerialPacket
//-------------------------
int UDPNetworkUtility::SendTo(const char* ip, int port, SerialPacket* serialPacket) {
IPaddress add;
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
throw(std::runtime_error("Failed to resolve a host"));
}
SendTo(&add, serialPacket);
}
int UDPNetworkUtility::SendTo(IPaddress* add, SerialPacket* serialPacket) {
memset(packet->data, 0, packet->maxlen);
serialize(serialPacket, packet->data);
packet->len = PACKET_BUFFER_SIZE;
packet->address = *add;
int ret = SDLNet_UDP_Send(socket, -1, packet);
if (ret <= 0) {
throw(std::runtime_error("Failed to send a packet"));
}
return ret;
}
int UDPNetworkUtility::SendTo(int channel, SerialPacket* serialPacket) {
memset(packet->data, 0, packet->maxlen);
serialize(serialPacket, packet->data);
packet->len = PACKET_BUFFER_SIZE;
int ret = SDLNet_UDP_Send(socket, channel, packet);
if (ret <= 0) {
throw(std::runtime_error("Failed to send a packet"));
}
return ret;
}
int UDPNetworkUtility::SendToAllChannels(SerialPacket* serialPacket) {
memset(packet->data, 0, packet->maxlen);
serialize(serialPacket, packet->data);
packet->len = PACKET_BUFFER_SIZE;
int sent = 0;
//send to all bound channels
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
sent += SDLNet_UDP_Send(socket, i, packet);
}
}
return sent;
}
int UDPNetworkUtility::Receive(SerialPacket* serialPacket) {
memset(packet->data, 0, packet->maxlen);
int ret = SDLNet_UDP_Recv(socket, packet);
deserialize(serialPacket, packet->data);
serialPacket->meta.srcAddress = packet->address;
if (ret < 0) {
throw(std::runtime_error("Unknown network error occured"));
}
return ret;
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -24,56 +24,49 @@
#include "SDL/SDL_net.h"
#include "serial_packet.hpp"
class UDPNetworkUtility {
public:
UDPNetworkUtility() = default;
~UDPNetworkUtility() = default;
void Open(int port, int packSize);
void Open(int port);
void Close();
//bind to an available channel
int Bind(const char* ip, int port) {
Bind(ip, port, -1);
}
int Bind(IPaddress* add) {
Bind(add, -1);
}
//bind to certain channel
int Bind(const char* ip, int port, int channel);
int Bind(IPaddress* add, int channel);
//bind to a channel
int Bind(const char* ip, int port, int channel = -1);
int Bind(IPaddress* add, int channel = -1);
void Unbind(int channel);
IPaddress* GetIPAddress(int channel) {
return SDLNet_UDP_GetPeerAddress(socket, channel);
}
int Send(const char* ip, int port, void* data, int len);
int Send(IPaddress* add, void* data, int len);
int Send(int channel, void* data, int len);
int SendAll(void* data, int len);
//send a buffer
int SendTo(const char* ip, int port, void* data, int len);
int SendTo(IPaddress* add, void* data, int len);
int SendTo(int channel, void* data, int len);
int SendToAllChannels(void* data, int len);
int Receive();
void* GetOutData() const {
return reinterpret_cast<void*>(packOut->data);
};
void* GetInData() const {
return reinterpret_cast<void*>(packIn->data);
};
UDPpacket* GetOutPacket() const {
return packOut;
}
UDPpacket* GetInPacket() const {
return packIn;
//send a SerialPacket
int SendTo(const char* ip, int port, SerialPacket* serialPacket);
int SendTo(IPaddress* add, SerialPacket* serialPacket);
int SendTo(int channel, SerialPacket* serialPacket);
int SendToAllChannels(SerialPacket* serialPacket);
int Receive(SerialPacket* serialPacket);
//accessors
UDPpacket* GetPacket() const {
return packet;
}
UDPsocket GetSocket() const {
return socket;
}
private:
UDPsocket socket = nullptr;
UDPpacket* packOut = nullptr;
UDPpacket* packIn = nullptr;
UDPpacket* packet = nullptr;
};
#endif
-110
View File
@@ -1,110 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 "network_queue.hpp"
#include "singleton.hpp"
#include "udp_network_utility.hpp"
#include "SDL/SDL_thread.h"
#include <stdexcept>
#include <deque>
static SDL_sem* lock = SDL_CreateSemaphore(1);
static SDL_Thread* queueThread = nullptr;
static std::deque<Packet> queue;
static bool running = false;
static int networkQueue(void*) {
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
while(running) {
SDL_SemWait(lock);
while(netUtil->Receive()) {
Packet p;
memcpy(&p, netUtil->GetInData(), sizeof(Packet));
p.meta.address = netUtil->GetInPacket()->address;
queue.push_back(p);
}
SDL_SemPost(lock);
SDL_Delay(10);
}
return 0;
}
void beginQueueThread() {
if (running) {
return;
}
running = true;
if (!(queueThread = SDL_CreateThread(networkQueue, nullptr))) {
throw(std::runtime_error("Failed to create the network thread"));
}
}
void endQueueThread() {
if (!running) {
return;
}
running = false;
SDL_WaitThread(queueThread, nullptr);
queueThread = nullptr;
}
void killQueueThread() {
if (!running) {
return;
}
running = false;
SDL_KillThread(queueThread);
queueThread = nullptr;
}
Packet peekNetworkPacket() {
SDL_SemWait(lock);
Packet p;
if (queue.size() > 0) {
Packet p = queue[0];
}
SDL_SemPost(lock);
return p;
}
Packet popNetworkPacket() {
SDL_SemWait(lock);
Packet p;
if (queue.size() > 0) {
p = queue[0];
queue.pop_front();
}
SDL_SemPost(lock);
return p;
}
void flushNetworkQueue() {
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
SDL_SemWait(lock);
while(netUtil->Receive());
queue.clear();
SDL_SemPost(lock);
}
-90
View File
@@ -1,90 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 PACKETTYPE_HPP_
#define PACKETTYPE_HPP_
#include "vector2.hpp"
#include "SDL/SDL_net.h"
#define PACKET_STRING_SIZE 100
#pragma pack(push, 0)
union Packet {
//the type of packet being sent
enum class Type {
NONE = 0,
PING = 1,
PONG = 2,
BROADCAST_REQUEST = 3,
BROADCAST_RESPONSE = 4,
JOIN_REQUEST = 5,
JOIN_RESPONSE = 6,
DISCONNECT = 7,
SYNCHRONIZE = 8,
PLAYER_NEW = 9,
PLAYER_DELETE = 10,
PLAYER_UPDATE = 11,
};
//metadata on the packet itself
struct Metadata {
Type type;
IPaddress address;
int clientIndex;
}meta;
//information about the server
struct ServerInformation {
Metadata meta;
//TODO: version info
char name[PACKET_STRING_SIZE];
//TODO: player count
}serverInfo;
//information about a specific player
struct PlayerInformation {
Metadata meta;
int index;
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
Vector2 position;
Vector2 motion;
//TODO Playerdata
}playerInfo;
//zero the packet
Packet() {
meta.type = Type::NONE;
meta.address.host = 0;
meta.address.port = 0;
meta.clientIndex = -1;
};
};
#pragma pack(pop)
#endif
+72
View File
@@ -0,0 +1,72 @@
/*
** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $
** Initialization of libraries for lua.c and other clients
** See Copyright Notice in lua.h
*/
/* Modified for use in Tortuga, renamed to linit.cpp
*/
/*
** If you embed Lua in your program and need to open the standard
** libraries, call luaL_openlibs in your program. If you need a
** different set of libraries, copy this file to your project and edit
** it to suit your needs.
*/
#define linit_c
#define LUA_LIB
#include "lua/lua.hpp"
#include "map_api.hpp"
/*
** these libs are loaded by lua.c and are readily available to any Lua
** program
*/
static const luaL_Reg loadedlibs[] = {
/* Standard libs */
{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_BITLIBNAME, luaopen_bit32},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug},
/* custom libs */
{LUA_MAPLIBNAME, luaopen_mapapi},
{NULL, NULL}
};
/*
** these libs are preloaded and must be required before used
*/
static const luaL_Reg preloadedlibs[] = {
{NULL, NULL}
};
LUALIB_API void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib;
/* call open functions from 'loadedlibs' and set results to global table */
for (lib = loadedlibs; lib->func; lib++) {
luaL_requiref(L, lib->name, lib->func, 1);
lua_pop(L, 1); /* remove lib */
}
/* add open functions from 'preloadedlibs' into 'package.preload' table */
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
for (lib = preloadedlibs; lib->func; lib++) {
lua_pushcfunction(L, lib->func);
lua_setfield(L, -2, lib->name);
}
lua_pop(L, 1); /* remove _PRELOAD table */
}
+37
View File
@@ -0,0 +1,37 @@
#config
INCLUDES+=. ../map ../utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+126
View File
@@ -0,0 +1,126 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "map_api.hpp"
//map headers
#include "map_allocator.hpp"
#include "map_file_format.hpp"
#include "region_pager.hpp"
//NOTE: When operating on a region, setTile() & getTile() *are not* zero indexed, but when operating on the entire map they *are* zero indexed.
static int setTile(lua_State* L) {
if (lua_gettop(L) == 5) {
//operating on a region
Region* ptr = (Region*)lua_touserdata(L, 1);
ptr->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
}
else {
//operating on the whole map
lua_pushstring(L, "pager");
lua_gettable(L, LUA_REGISTRYINDEX);
//assume the pager is using lua
RegionPager<LuaAllocator, LuaFormat>* pager = reinterpret_cast<RegionPager<LuaAllocator, LuaFormat>*>(lua_touserdata(L, -1));
//balance the stack
lua_pop(L, 1);
pager->SetTile(lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4));
}
return 0;
}
static int getTile(lua_State* L) {
if (lua_gettop(L) == 4) {
//operating on a region
Region* ptr = (Region*)lua_touserdata(L, 1);
int ret = ptr->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
lua_pushnumber(L, ret);
}
else {
//operating on the whole map
lua_pushstring(L, "pager");
lua_gettable(L, LUA_REGISTRYINDEX);
//assume the pager is using lua
RegionPager<LuaAllocator, LuaFormat>* pager = reinterpret_cast<RegionPager<LuaAllocator, LuaFormat>*>(lua_touserdata(L, -1));
//balance the stack
lua_pop(L, 1);
int ret = pager->GetTile(lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3));
lua_pushnumber(L, ret);
}
return 1;
}
static int getX(lua_State* L) {
Region* ptr = (Region*)lua_touserdata(L, 1);
lua_pushinteger(L, ptr->GetX());
return 1;
}
static int getY(lua_State* L) {
Region* ptr = (Region*)lua_touserdata(L, 1);
lua_pushinteger(L, ptr->GetY());
return 1;
}
static int getRegionWidth(lua_State* L) {
lua_pushinteger(L, REGION_WIDTH);
return 1;
}
static int getRegionHeight(lua_State* L) {
lua_pushinteger(L, REGION_HEIGHT);
return 1;
}
static int getRegionDepth(lua_State* L) {
lua_pushinteger(L, REGION_DEPTH);
return 1;
}
static int dummy(lua_State* L) {
return 0;
}
static const luaL_Reg regionlib[] = {
{"create", dummy},
{"unload", dummy},
{"load", dummy},
{"save", dummy},
{"settile",setTile},
{"gettile",getTile},
{"getx",getX},
{"gety",getY},
{"getregionwidth",getRegionWidth},
{"getregionheight",getRegionHeight},
{"getregiondepth",getRegionDepth},
{nullptr, nullptr}
};
LUAMOD_API int luaopen_mapapi(lua_State* L) {
luaL_newlib(L, regionlib);
return 1;
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,16 +19,12 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef NETWORKQUEUE_HPP_
#define NETWORKQUEUE_HPP_
#ifndef MAPAPI_HPP_
#define MAPAPI_HPP_
#include "packet.hpp"
#include "lua/lua.hpp"
void beginQueueThread();
void endQueueThread();
void killQueueThread();
Packet peekNetworkPacket();
Packet popNetworkPacket();
void flushNetworkQueue();
#define LUA_MAPLIBNAME "map"
LUAMOD_API int luaopen_mapapi(lua_State* L);
#endif
-81
View File
@@ -1,81 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 "surface_manager.hpp"
#include <stdexcept>
SDL_Surface* SurfaceManager::Load(std::string key, std::string fname) {
MapType::iterator it = surfaceMap.find(key);
if (it != surfaceMap.end()) {
throw(std::runtime_error(std::string("Surface already loaded: ") + key + std::string(", ") + fname));
}
return LoadSurface(key, fname);
}
SDL_Surface* SurfaceManager::Reload(std::string key, std::string fname) {
MapType::iterator it = surfaceMap.find(key);
if (it != surfaceMap.end()) {
SDL_FreeSurface(it->second);
surfaceMap.erase(it);
}
return LoadSurface(key, fname);
}
SDL_Surface* SurfaceManager::Get(std::string key) {
MapType::iterator it = surfaceMap.find(key);
if (it == surfaceMap.end()) {
throw(std::runtime_error(std::string("Could not find key: ") + key));
}
return it->second;
}
SDL_Surface* SurfaceManager::Set(std::string key, SDL_Surface* ptr) {
MapType::iterator it = surfaceMap.find(key);
if (it != surfaceMap.end()) {
throw(std::runtime_error(std::string("Key already exists: ") + key));
}
return surfaceMap[key] = ptr;
}
void SurfaceManager::Free(std::string key) {
MapType::iterator it = surfaceMap.find(key);
if (it != surfaceMap.end()) {
SDL_FreeSurface(it->second);
surfaceMap.erase(it);
}
}
void SurfaceManager::FreeAll() {
for (auto it : surfaceMap) {
SDL_FreeSurface(it.second);
}
surfaceMap.clear();
}
SDL_Surface* SurfaceManager::LoadSurface(std::string key, std::string fname) {
SDL_Surface* ptr = SDL_LoadBMP(fname.c_str());
if (!ptr) {
throw(std::runtime_error(std::string("Failed to load file: ") + fname));
}
SDL_SetColorKey(ptr, SDL_SRCCOLORKEY, SDL_MapRGB(ptr->format, 255, 0, 255)); //default
return surfaceMap[key] = ptr;
}
-148
View File
@@ -1,148 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 "udp_network_utility.hpp"
#include <stdexcept>
void UDPNetworkUtility::Open(int port, int packSize) {
if (!(socket = SDLNet_UDP_Open(port))) {
Close();
throw(std::runtime_error("Failed to open a UDP socket"));
}
if (!(packOut = SDLNet_AllocPacket(packSize))) {
Close();
throw(std::runtime_error("Failed to allocate the out packet"));
}
if (!(packIn = SDLNet_AllocPacket(packSize))) {
Close();
throw(std::runtime_error("Failed to allocate the in packet"));
}
}
void UDPNetworkUtility::Close() {
SDLNet_UDP_Close(socket);
SDLNet_FreePacket(packOut);
SDLNet_FreePacket(packIn);
socket = nullptr;
packOut = nullptr;
packIn = nullptr;
}
int UDPNetworkUtility::Bind(const char* ip, int port, int channel) {
IPaddress add;
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
throw(std::runtime_error("Failed to resolve a host"));
}
return Bind(&add, channel);
}
int UDPNetworkUtility::Bind(IPaddress* add, int channel) {
int ret = SDLNet_UDP_Bind(socket, channel, add);
if (ret == -1) {
throw(std::runtime_error("Failed to bind to a channel"));
}
return ret;
}
void UDPNetworkUtility::Unbind(int channel) {
SDLNet_UDP_Unbind(socket, channel);
}
int UDPNetworkUtility::Send(const char* ip, int port, void* data, int len) {
IPaddress add;
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
throw(std::runtime_error("Failed to resolve a host"));
}
Send(&add, data, len);
}
int UDPNetworkUtility::Send(IPaddress* add, void* data, int len) {
if (len > packOut->maxlen) {
throw(std::runtime_error("Failed to copy the data into the packet"));
}
memset(packOut->data, 0, packOut->maxlen);
memcpy(packOut->data, data, len);
packOut->len = len;
packOut->address = *add;
int ret = SDLNet_UDP_Send(socket, -1, packOut);
if (ret <= 0) {
throw(std::runtime_error("Failed to send a packet"));
}
return ret;
}
int UDPNetworkUtility::Send(int channel, void* data, int len) {
if (len > packOut->maxlen) {
throw(std::runtime_error("Failed to copy the data into the packet"));
}
memset(packOut->data, 0, packOut->maxlen);
memcpy(packOut->data, data, len);
packOut->len = len;
int ret = SDLNet_UDP_Send(socket, channel, packOut);
if (ret <= 0) {
throw(std::runtime_error("Failed to send a packet"));
}
return ret;
}
int UDPNetworkUtility::SendAll(void* data, int len) {
if (len > packOut->maxlen) {
throw(std::runtime_error("Failed to copy the data into the packet"));
}
memset(packOut->data, 0, packOut->maxlen);
memcpy(packOut->data, data, len);
packOut->len = len;
int sent = 0;
//send to all bound channels
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
sent += SDLNet_UDP_Send(socket, i, packOut);
}
}
return sent;
}
int UDPNetworkUtility::Receive() {
memset(packIn->data, 0, packIn->maxlen);
int ret = SDLNet_UDP_Recv(socket, packIn);
if (ret < 0) {
throw(std::runtime_error("Unknown network error occured"));
}
return ret;
}
+19 -27
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -23,13 +23,6 @@
#include <stdexcept>
void Button::Setup(Sint16 i, Sint16 j, SDL_Surface* bg, SDL_Surface* fg, std::string t) {
x = i;
y = j;
SetSurfaces(bg, fg);
SetText(t);
}
Button::State Button::MouseMotion(SDL_MouseMotionEvent const& motion) {
return CalcState(motion.x, motion.y, motion.state & SDL_BUTTON_LMASK);
}
@@ -49,41 +42,40 @@ Button::State Button::MouseButtonUp(SDL_MouseButtonEvent const& button) {
}
void Button::DrawTo(SDL_Surface* const dest) {
image.DrawTo(dest, x, y);
font.DrawStringTo(text, dest, textX + x, textY + y);
}
void Button::SetSurfaces(SDL_Surface* bg, SDL_Surface* fg) {
//graphical stuff
image.SetSurface(bg);
image.SetClipH(image.GetClipH() / 3); //3 phases, vertical storage
font.SetSurface(fg);
//reset textX & textY
SetText(text);
if (!image || !font) {
throw(std::runtime_error("Surface not set for Button"));
}
image->SetClipY(state * image->GetClipH());
image->DrawTo(dest, x, y);
font->DrawStringTo(text, dest, textX + x, textY + y);
}
std::string Button::SetText(std::string t) {
if (!image || !font) {
throw(std::runtime_error("Surface not set for Button"));
}
//one line, cache the position
text = t;
textX = (image.GetClipW() / 2) - (font.GetCharW() * text.size() / 2);
textY = (image.GetClipH() / 2) - (font.GetCharH() / 2);
textX = (image->GetClipW() / 2) - (font->GetCharW() * text.size() / 2);
textY = (image->GetClipH() / 2) - (font->GetCharH() / 2);
return text;
}
Button::State Button::CalcState(Sint16 i, Sint16 j, bool leftPressed) {
if (i < x || i > (x + image.GetClipW()) ||
j < y || j > (y + image.GetClipH())
if (!image || !font) {
throw(std::runtime_error("Surface not set for Button"));
}
//if out of bounds
if (i < x || i >= (x + image->GetClipW()) ||
j < y || j >= (y + image->GetClipH())
) {
image.SetClipY(0);
return state = State::NORMAL;
}
if (leftPressed) {
image.SetClipY(image.GetClipH()*2);
return state = State::PRESSED;
}
else {
image.SetClipY(image.GetClipH());
return state = State::HOVER;
}
}
+37 -23
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -27,52 +27,66 @@
#include <string>
//3-phases, no toggle, centred text
/* 3-phases, no toggle, centred text
* This class uses the size of the provided image as its bounds. Also,
* The provided image should be formatted correctly.
*
* The button's image should be divided into 3 sections virtucally,
* which act as the different button images. The clip width & height of the
* Image should be set manually, and the height should be 1/3 of the total
* graphical data.
*/
class Button {
public:
enum class State {
NORMAL, HOVER, PRESSED
enum State {
NORMAL = 0, HOVER = 1, PRESSED = 2
};
Button() = default;
Button(Sint16 x, Sint16 y, SDL_Surface* bg, SDL_Surface* fg, std::string t = "") { Setup(x, y, bg, fg, t); }
~Button() = default;
void Setup(Sint16 x, Sint16 y, SDL_Surface* bg, SDL_Surface* fg, std::string text = "");
//return the current state
//handle input
State MouseMotion(SDL_MouseMotionEvent const&);
State MouseButtonDown(SDL_MouseButtonEvent const&);
State MouseButtonUp(SDL_MouseButtonEvent const&);
State GetState() const { return state; }
//yet another draw function
void DrawTo(SDL_Surface* const);
//simple accessors and mutators
//accessors and mutators
Image* SetImage(Image* const ptr) { return image = ptr; }
Image* GetImage() { return image; }
RasterFont* SetFont(RasterFont* const ptr) { return font = ptr; }
RasterFont* GetFont() { return font; }
Sint16 SetX(Sint16 i) { return x = i; }
Sint16 SetY(Sint16 i) { return y = i; }
Sint16 GetX() const { return x; }
Sint16 GetY() const { return y; }
void SetSurfaces(SDL_Surface* bg, SDL_Surface* fg);
std::string SetText(std::string t);
std::string GetText() const { return text; }
//raw access, be careful
Image* GetImage() { return &image; }
RasterFont* GetFont() { return &font; }
//debug
Sint16 SetTextX(Sint16 i) { return textX = i; }
Sint16 SetTextY(Sint16 i) { return textY = i; }
Sint16 GetTextX() const { return textX; }
Sint16 GetTextY() const { return textY; }
State SetState(State s) { return state = s; }
State GetState() const { return state; }
std::string SetText(std::string);
std::string GetText() const { return text; }
private:
State CalcState(Sint16 x, Sint16 y, bool leftPressed);
//point to the provided external objects
Image* image = nullptr;
RasterFont* font = nullptr;
//positions
Sint16 x = 0, y = 0;
Sint16 textX = 0, textY = 0; //prevent recalc every loop
Image image;
RasterFont font;
Sint16 textX = 0, textY = 0;
//
State state = State::NORMAL;
std::string text;
};
+37
View File
@@ -0,0 +1,37 @@
#config
INCLUDES+=. ../graphics
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+139
View File
@@ -0,0 +1,139 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 "menu_bar.hpp"
#include <stdexcept>
#include <sstream>
void MenuBar::DrawTo(SDL_Surface* const dest) {
for (auto& i : entries) {
i.DrawTo(dest);
}
}
void MenuBar::MouseMotion(SDL_MouseMotionEvent const& motion) {
for (auto& i : entries) {
i.MouseMotion(motion);
}
}
void MenuBar::MouseButtonDown(SDL_MouseButtonEvent const& button) {
for (auto& i : entries) {
i.MouseButtonDown(button);
}
}
void MenuBar::MouseButtonUp(SDL_MouseButtonEvent const& button, int* entry, int* butt) {
*entry = *butt = -1;
int ret = -1;
for (auto& i : entries) {
ret = i.MouseButtonUp(button);
if (ret != -1) {
*entry = (&i - entries.data());
*butt = ret;
}
}
}
void MenuBar::SetEntries(std::vector<std::vector<std::string>> info) {
if (!image || !font) {
throw(std::runtime_error("Surfaces not loaded into the menu bar"));
}
entries.clear();
for (int i = 0; i < info.size(); i++) {
//create the entry & the main button
entries.push_back(MenuBarEntry());
entries[i].mainButton.SetImage(image);
entries[i].mainButton.SetFont(font);
entries[i].mainButton.SetText(info[i][0]);
entries[i].mainButton.SetX(i * image->GetClipW());
entries[i].mainButton.SetY(0);
for (int j = 0; j < info[i].size()-1; j++) {
//create each drop button in this entry
entries[i].dropButtons.push_back(Button());
entries[i].dropButtons[j].SetImage(image);
entries[i].dropButtons[j].SetFont(font);
entries[i].dropButtons[j].SetText(info[i][j+1]);
entries[i].dropButtons[j].SetX(i * image->GetClipW());
entries[i].dropButtons[j].SetY((j+1) * image->GetClipH());
}
}
}
void MenuBar::MenuBarEntry::DrawTo(SDL_Surface* const dest) {
//only draw the dropButtons in the user has this menu open
mainButton.DrawTo(dest);
if (!open) {
return;
}
for (auto& i : dropButtons) {
i.DrawTo(dest);
}
}
void MenuBar::MenuBarEntry::MouseMotion(SDL_MouseMotionEvent const& motion) {
//open the menu
bool o = mainButton.MouseMotion(motion) == Button::State::PRESSED;
if (!(open |= o)) {
return;
}
for (auto& i : dropButtons) {
//dragging down the menu
o |= i.MouseMotion(motion) == Button::State::PRESSED;
}
open = o;
}
void MenuBar::MenuBarEntry::MouseButtonDown(SDL_MouseButtonEvent const& button) {
//open the menu
if (!(open = mainButton.MouseButtonDown(button) == Button::State::PRESSED)) {
return;
}
//update the others anyway
for (auto& i : dropButtons) {
i.MouseButtonDown(button);
}
}
int MenuBar::MenuBarEntry::MouseButtonUp(SDL_MouseButtonEvent const& button) {
int ret = -1;
mainButton.MouseButtonUp(button);
for (auto& i : dropButtons) {
//the user just released this button
if (i.GetState() != i.MouseButtonUp(button) && i.GetState() == Button::State::HOVER && open) {
//get this button's index
ret = (&i - dropButtons.data());
}
}
open = false;
return ret;
}
+91
View File
@@ -0,0 +1,91 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 MENUBAR_HPP_
#define MENUBAR_HPP_
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
#include <string>
#include <vector>
/* I've redesigned this so that the contents of the menu bar can't change during run time.
* This is more restrictive but I'm focusing on getting this working first.
* The Image and Font pointers must be set before the text data is entered.
*
* This class needs a rewrite.
*/
class MenuBar {
public:
MenuBar() = default;
~MenuBar() = default;
//yet another draw function
void DrawTo(SDL_Surface* const dest);
//user inputs
void MouseMotion(SDL_MouseMotionEvent const&);
void MouseButtonDown(SDL_MouseButtonEvent const&);
void MouseButtonUp(SDL_MouseButtonEvent const&, int* entry, int* button);
//manage the entries & buttons
void SetEntries(std::vector<std::vector<std::string>> info);
void ClearEntries() { entries.clear(); }
//Accessors and mutators
Image* SetImage(Image* const ptr) { return image = ptr; }
Image* GetImage() { return image; }
RasterFont* SetFont(RasterFont* const ptr) { return font = ptr; }
RasterFont* GetFont() { return font; }
private:
class MenuBarEntry;
std::vector<MenuBarEntry> entries;
Image* image = nullptr;
RasterFont* font = nullptr;
};
class MenuBar::MenuBarEntry {
public:
MenuBarEntry() = default;
~MenuBarEntry() = default;
void DrawTo(SDL_Surface* const dest);
void MouseMotion(SDL_MouseMotionEvent const&);
void MouseButtonDown(SDL_MouseButtonEvent const&);
int MouseButtonUp(SDL_MouseButtonEvent const&);
private:
Button mainButton;
std::vector<Button> dropButtons;
bool open = false;
friend class MenuBar;
};
#endif
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -23,9 +23,8 @@
#include <stdexcept>
/* Note: This class can only take a raster font with 16*16 characters, and the
* indevidual characters must have the same dimensions. Overall this class is too
* restrictive; I suggest using a 3rd party library.
/* It might be more efficient to render to a different surface (like an Image)
* rather than calling this function with all of it's '%' and '/'.
*/
void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x, Sint16 y) {
@@ -41,10 +40,21 @@ void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x,
}
}
SDL_Surface* RasterFont::SetSurface(SDL_Surface* p) {
if (image.SetSurface(p)) {
image.SetClipW(image.GetSurface()->w/16);
image.SetClipH(image.GetSurface()->h/16);
}
/* Note: This class can only take a raster font with 16*16 characters, and the
* indevidual characters must have the same dimensions. Overall this class is too
* restrictive; I suggest using a 3rd party library.
*/
SDL_Surface* RasterFont::LoadSurface(std::string fname) {
image.LoadSurface(fname);
image.SetClipW(image.GetSurface()->w/16);
image.SetClipH(image.GetSurface()->h/16);
return image.GetSurface();
}
SDL_Surface* RasterFont::SetSurface(SDL_Surface* p) {
image.SetSurface(p);
image.SetClipW(image.GetSurface()->w/16);
image.SetClipH(image.GetSurface()->h/16);
return image.GetSurface();
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -24,21 +24,29 @@
#include "image.hpp"
#include <string>
class RasterFont {
public:
RasterFont() = default;
RasterFont(RasterFont const& rhs) { *this = rhs; }
RasterFont(RasterFont&& rhs) { *this = std::move(rhs); }
RasterFont(std::string fname) { LoadSurface(fname); }
RasterFont(SDL_Surface* p) { SetSurface(p); }
~RasterFont() = default;
RasterFont& operator=(RasterFont const& rhs) { image = rhs.image; }
RasterFont& operator=(RasterFont&& rhs) { image = std::move(rhs.image); }
void DrawStringTo(std::string, SDL_Surface* const, Sint16 x, Sint16 y);
//Accessors and Mutators
SDL_Surface* LoadSurface(std::string);
SDL_Surface* SetSurface(SDL_Surface*);
SDL_Surface* GetSurface() const { return image.GetSurface(); }
Uint16 GetCharW() { return image.GetClipW(); }
Uint16 GetCharH() { return image.GetClipH(); }
void FreeSurface() { image.FreeSurface(); }
Uint16 GetCharW() const { return image.GetClipW(); }
Uint16 GetCharH() const { return image.GetClipH(); }
private:
Image image;
};
+75
View File
@@ -0,0 +1,75 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 BBOX_HPP_
#define BBOX_HPP_
#include <type_traits>
#include <stdexcept>
#include <algorithm>
//TODO: This is supposed to interact with the vector
class BBox {
public:
double x, y;
double w, h;
BBox() = default;
BBox(double i, double j, double k, double l): x(i), y(j), w(k), h(l) {};
~BBox() = default;
BBox& operator=(BBox const&) = default;
double Size() {
return std::max(w*h,0.0);
}
bool IsCollision(BBox rhs) {
return not (
x >= rhs.x + rhs.w ||
y >= rhs.y + rhs.h ||
rhs.x >= x + w ||
rhs.y >= y + h
);
}
BBox Intersection(BBox rhs) {
if (!IsCollision(rhs)) {
return {0, 0, 0, 0};
}
BBox ret;
ret.x = std::max(x, rhs.x);
ret.y = std::max(y, rhs.y);
ret.w = std::min(x+w, rhs.x+rhs.w) - ret.x;
ret.h = std::min(y+h, rhs.y+rhs.h) - ret.y;
return ret;
}
double operator[](size_t i) {
if (i >= 4)
throw(std::domain_error("Out of range"));
return *(&x+i);
}
};
//This is explicitly a POD
static_assert(std::is_pod<BBox>::value, "BBox is not a POD");
#endif
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,8 +21,9 @@
*/
#include "config_utility.hpp"
#include <stdexcept>
#include <cstdlib>
#include <fstream>
#include <stdexcept>
using namespace std;
@@ -74,3 +75,31 @@ void ConfigUtility::Load(string fname) {
is.close();
}
std::string& ConfigUtility::String(std::string s) {
return table[s];
}
int ConfigUtility::Integer(std::string s) {
std::map<std::string, std::string>::iterator it = table.find(s);
if (it == table.end()) {
return 0;
}
return atoi(it->second.c_str());
}
double ConfigUtility::Double(std::string s) {
std::map<std::string, std::string>::iterator it = table.find(s);
if (it == table.end()) {
return 0.0;
}
return atof(it->second.c_str());
}
bool ConfigUtility::Boolean(std::string s) {
std::map<std::string, std::string>::iterator it = table.find(s);
if (it == table.end()) {
return false;
}
return it->second == "true";
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -24,40 +24,32 @@
#include <map>
#include <string>
#include <cstdlib>
class ConfigUtility {
public:
ConfigUtility() {}
ConfigUtility() = default;
ConfigUtility(std::string s) { Load(s); }
void Load(std::string fname);
std::string String(std::string s) {
return table[s];
}
const char* CString(std::string s) {
return table[s].c_str();
}
int Integer(std::string s) {
return atoi(table[s].c_str());
}
double Double(std::string s) {
return atof(table[s].c_str());
}
bool Boolean(std::string s) {
return table[s] == "true";
}
//convert to a type
std::string& String(std::string);
int Integer(std::string);
double Double(std::string);
bool Boolean(std::string);
//shorthand
std::string& operator[](std::string s) {
return table[s];
return String(s);
}
int Int(std::string s) {
return Integer(s);
}
int Bool(std::string s) {
bool Bool(std::string s) {
return Boolean(s);
}
//OO breaker
std::map<std::string, std::string>* GetMap() {
return &table;
}
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,26 +19,30 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "frame_rate.hpp"
#ifndef FRAMERATE_HPP_
#define FRAMERATE_HPP_
#include <chrono>
typedef std::chrono::high_resolution_clock Clock;
class FrameRate {
public:
typedef std::chrono::high_resolution_clock Clock;
static int frameCount = 0;
static int lastFrameRate = 0;
static Clock::time_point tick = Clock::now();
int clockFrameRate() {
frameCount++;
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
lastFrameRate = frameCount;
frameCount = 0;
tick = Clock::now();
FrameRate() = default;
int Calculate() {
frameCount++;
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
lastFrameRate = frameCount;
frameCount = 0;
tick = Clock::now();
}
return lastFrameRate;
}
return lastFrameRate;
}
int GetFrameRate() { return lastFrameRate; }
private:
int frameCount = 0;
int lastFrameRate = 0;
Clock::time_point tick = Clock::now();
};
int getFrameRate() {
return lastFrameRate;
}
#endif
+37
View File
@@ -0,0 +1,37 @@
#config
INCLUDES+=.
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+50
View File
@@ -0,0 +1,50 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "sql_utility.hpp"
#include "utility.hpp"
#include <stdexcept>
#include <fstream>
#include <cstdlib>
int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**), void* argPtr) {
//load the file into a string
std::ifstream is(fname);
if (!is.is_open()) {
return -1;
}
std::string script;
getline(is, script, '\0');
is.close();
//run the SQL loaded from the file
char* errmsg = nullptr;
int ret = sqlite3_exec(db, script.c_str(), callback, argPtr, &errmsg);
if (ret != SQLITE_OK) {
//handle any errors received from the SQL
std::runtime_error e(std::string() + "SQL Script Error " + to_string_custom(ret) + ": " + errmsg);
free(errmsg);
throw(e);
}
return ret;
}
+31
View File
@@ -0,0 +1,31 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 SERVERUTILITY_HPP_
#define SERVERUTILITY_HPP_
#include "sqlite3/sqlite3.h"
#include <string>
int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**) = nullptr, void* argPtr = nullptr);
#endif
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -19,23 +19,41 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "sprite_sheet.hpp"
#include "utility.hpp"
void SpriteSheet::Update(double delta) {
if (delay && (ticks += delta) >= delay) {
if (++currentFrame >= maxFrames) {
currentFrame = 0;
}
ticks = 0;
#include <algorithm>
int snapToBase(int base, int x) {
//snap to a grid
if (x < 0) {
x++;
return x / base * base - base;
}
image.SetClipX(currentFrame * image.GetClipW());
image.SetClipY(currentStrip * image.GetClipH());
return x / base * base;
}
SDL_Surface* SpriteSheet::SetSurface(SDL_Surface* const s, Uint16 w, Uint16 h) {
image.SetSurface(s);
image.SetClip({0, 0, w, h});
currentFrame = 0; maxFrames = image.GetSurface()->w / image.GetClipW();
currentStrip = 0; maxStrips = image.GetSurface()->h / image.GetClipH();
delay = ticks = 0;
std::string truncatePath(std::string pathname) {
return std::string(
std::find_if(
pathname.rbegin(),
pathname.rend(),
[](char ch) -> bool {
//windows only
return ch == '/' || ch == '\\';
// //unix only
// return ch == '/';
}).base(),
pathname.end());
}
std::string to_string_custom(int i) {
char buffer[20];
snprintf(buffer, 20, "%d", i);
return std::string(buffer);
}
int to_integer_custom(std::string s) {
int ret = 0;
sscanf(s.c_str(), "%d", &ret);
return ret;
}
+48
View File
@@ -0,0 +1,48 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* 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 UTILITY_HPP_
#define UTILITY_HPP_
#include <string>
int snapToBase(int base, int x);
std::string truncatePath(std::string pathname);
//fixing known bugs in g++
std::string to_string_custom(int i);
int to_integer_custom(std::string);
//wow
template<typename ContainerT, typename PredicateT>
void erase_if(ContainerT& items, const PredicateT& predicate) {
for(auto it = items.begin(); it != items.end(); /* empty */) {
if(predicate(*it)) {
it = items.erase(it);
}
else {
++it;
}
}
};
#endif
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -22,13 +22,18 @@
#ifndef VECTOR2_HPP_
#define VECTOR2_HPP_
#include <type_traits>
#include <stdexcept>
#include <cmath>
class Vector2 {
public:
double x = 0, y = 0;
double x, y;
Vector2() = default;
Vector2(double i, double j): x(i), y(j) {};
~Vector2() = default;
Vector2& operator=(Vector2 const&) = default;
double Length() const {
return sqrt(x*x+y*y);
@@ -89,7 +94,7 @@ public:
bool operator==(Vector2 v) { return (x == v.x && y == v.y); }
bool operator!=(Vector2 v) { return (x != v.x || y != v.y); }
//member templates
//member templates (curry the above operators)
template<typename T> Vector2 operator+=(T t) { return *this = *this + t; }
template<typename T> Vector2 operator-=(T t) { return *this = *this - t; }
template<typename T> Vector2 operator*=(T t) { return *this = *this * t; }
@@ -98,7 +103,7 @@ public:
template<typename T> bool operator!=(T t) { return (x != t || y != t); }
};
//non-member templates
//non-member templates (flip the order)
template<typename T> Vector2 operator+(T t, Vector2 v) { return v + t; }
template<typename T> Vector2 operator-(T t, Vector2 v) { return v - t; }
template<typename T> Vector2 operator*(T t, Vector2 v) { return v * t; }
@@ -107,4 +112,7 @@ template<typename T> Vector2 operator/(T t, Vector2 v) { return v / t; }
template<typename T> bool operator==(T t, Vector2 v) { return v == t; }
template<typename T> bool operator!=(T t, Vector2 v) { return v != t; }
//This is explicitly a POD
static_assert(std::is_pod<Vector2>::value, "Vector2 is not a POD");
#endif
+11 -6
View File
@@ -1,14 +1,19 @@
LIBDIR=lib
#for use on Windows:
#MKDIR=mkdir
#RM=del /y
CXXFLAGS+=-static-libgcc -static-libstdc++
CFLAGS+=-static-libgcc
export
OUTDIR=out
all: $(LIBDIR) $(OUTDIR)
all: $(OUTDIR)
$(MAKE) -C common
$(MAKE) -C server
$(MAKE) -C client
$(MAKE) -C test
$(LIBDIR):
mkdir $(LIBDIR)
$(OUTDIR):
mkdir $(OUTDIR)
+21 -11
View File
@@ -1,20 +1,30 @@
#configuration of the programs
server.host = 127.0.0.1
server.port = 1991
server.name = foobar
server.host = 255.255.255.255
server.port = 21795
server.name = local
server.dbname = database.db
screen.w = 800
screen.h = 600
screen.f = false
#directories
fonts = rsc/graphics/fonts
logos = rsc/graphics/logos
sprites = rsc/graphics/sprites
tilesets = rsc/graphics/tilesets
interface = rsc/graphics/interface
dir.fonts = rsc/graphics/fonts/
dir.logos = rsc/graphics/logos/
dir.sprites = rsc/graphics/sprites/
dir.tilesets = rsc/graphics/tilesets/
dir.interface = rsc/graphics/interface/
dir.scripts = rsc/scripts/
#map system
map.pager.width = 20
map.pager.height = 20
map.pager.depth = 3
#player options
client.username = Kayne Ruse
client.handle = Ratstail91
client.avatar = elliot2.bmp
#debugging
debug = true
avatar = elliot
handle = UserName
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

+36
View File
@@ -0,0 +1,36 @@
print("Lua script check (./rsc)")
-------------------------
--Map API overrides
-------------------------
function map.create(region)
for i = 1, map.getregionwidth() do
for j = 1, map.getregionheight() do
if math.abs(map.getx(region) + i -1) == math.abs(map.gety(region) + j -1) then
map.settile(region, i, j, 1, 50)
else
map.settile(region, i, j, 1, 14)
end
end
end
end
function map.unload(region)
--
end
function map.load(region, dir)
--return true if file loaded, otherwise return false
return false
end
function map.save(region, dir)
--
end
-------------------------
--Enemy API
-------------------------
--TODO
+63
View File
@@ -0,0 +1,63 @@
CREATE TABLE IF NOT EXISTS Accounts (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
username varchar(100) UNIQUE,
--TODO: server-client security
-- password varchar(100),
blacklisted BIT DEFAULT 0,
whitelisted BIT DEFAULT 1,
administrator BIT DEFAULT 0
);
CREATE TABLE IF NOT EXISTS Characters (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
--metadata
owner INTEGER REFERENCES Accounts(uid),
handle varchar(100) UNIQUE,
avatar varchar(100),
birth timestamp NOT NULL DEFAULT (datetime()),
--position
mapIndex INTEGER DEFAULT 0,
positionX INTEGER DEFAULT 0,
positionY INTEGER DEFAULT 0,
--statistics
level INTEGER DEFAULT 0,
exp INTEGER DEFAULT 0,
maxHP INTEGER DEFAULT 0,
health INTEGER DEFAULT 0,
maxMP INTEGER DEFAULT 0,
mana INTEGER DEFAULT 0,
attack INTEGER DEFAULT 0,
defence INTEGER DEFAULT 0,
intelligence INTEGER DEFAULT 0,
resistance INTEGER DEFAULT 0,
speed INTEGER DEFAULT 0,
accuracy REAL DEFAULT 0.0,
evasion REAL DEFAULT 0.0,
luck REAL DEFAULT 0.0,
--equipment
weapon INTEGER REFERENCES WornEquipment(uid),
helmet INTEGER REFERENCES WornEquipment(uid),
armour INTEGER REFERENCES WornEquipment(uid)
--etc.
);
CREATE TABLE IF NOT EXISTS InventoryItems (
--metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT,
itemID INTEGER, --type
stackSize INTEGER DEFAULT 0,
owner INTEGER REFERENCES Characters(uid)
);
CREATE TABLE IF NOT EXISTS WornEquipment (
--metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT,
itemID INTEGER, --type
owner INTEGER REFERENCES Characters(uid)
--hold all equipment info
--stat mods, special effects, etc.
);
+191
View File
@@ -0,0 +1,191 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "server_application.hpp"
#include "sqlite3/sqlite3.h"
#include <stdexcept>
//-------------------------
//Define the queries
//-------------------------
static const char* CREATE_USER_ACCOUNT = "INSERT INTO Accounts (username) VALUES (?);";
static const char* LOAD_USER_ACCOUNT = "SELECT * FROM Accounts WHERE username = ?;";
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted = ?2, whitelisted = ?3 WHERE uid = ?1;";
static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;";
//-------------------------
//Define the methods
//-------------------------
int ServerApplication::CreateUserAccount(std::string username, int clientIndex) {
//create this user account, failing if it exists, leave this account in memory
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, CREATE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameter
if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than this account exists
sqlite3_finalize(statement);
return -1;
}
sqlite3_finalize(statement);
//load this account into memory
return LoadUserAccount(username, clientIndex);
}
int ServerApplication::LoadUserAccount(std::string username, int clientIndex) {
//load this user account, failing if it is in memory, creating it if it doesn't exist
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, LOAD_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameter
if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
int ret = sqlite3_step(statement);
//process the result
if (ret == SQLITE_ROW) {
//get the index
int uid = sqlite3_column_int(statement, 0);
//check to see if this account is already loaded
if (accountMap.find(uid) != accountMap.end()) {
sqlite3_finalize(statement);
return -1;
}
//extract the data into memory
AccountData& newAccount = accountMap[uid];
newAccount.username = reinterpret_cast<const char*>(sqlite3_column_text(statement, 1));
newAccount.blackListed = sqlite3_column_int(statement, 2);
newAccount.whiteListed = sqlite3_column_int(statement, 3);
newAccount.clientIndex = clientIndex;
//finish the routine
sqlite3_finalize(statement);
return uid;
}
sqlite3_finalize(statement);
if (ret == SQLITE_DONE) {
//create the non-existant account instead
return CreateUserAccount(username, clientIndex);
}
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadUserAccount: " + sqlite3_errmsg(database) ));
}
int ServerApplication::SaveUserAccount(int uid) {
//save this user account from memory, replacing it if it exists in the database
//DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID.
//this method fails if this account is not loaded
if (accountMap.find(uid) == accountMap.end()) {
return -1;
}
AccountData& account = accountMap[uid];
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, SAVE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameters
bool ret = false;
ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 2, account.blackListed) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 3, account.whiteListed) != SQLITE_OK;
//check for binding errors
if (ret) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than something went horribly wrong
sqlite3_finalize(statement);
throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) );
}
sqlite3_finalize(statement);
//successful execution
return 0;
}
void ServerApplication::UnloadUserAccount(int uid) {
//save this user account, and then unload it
//NOTE: the associated characters are unloaded externally
SaveUserAccount(uid);
accountMap.erase(uid);
}
void ServerApplication::DeleteUserAccount(int uid) {
//delete a user account from the database, and remove it from memory
//NOTE: the associated characters are unloaded externally
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, DELETE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameter
if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than something went horribly wrong
sqlite3_finalize(statement);
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) );
}
//finish the routine
sqlite3_finalize(statement);
accountMap.erase(uid);
}
+231
View File
@@ -0,0 +1,231 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "server_application.hpp"
#include "sqlite3/sqlite3.h"
#include <stdexcept>
//-------------------------
//Define the queries
//-------------------------
//TODO: save and load the statistics
static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, avatar) VALUES (?, ?, ?);";
static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;";
static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET mapIndex = ?2, positionX = ?3, positionY = ?4 WHERE uid = ?1;";
static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;";
//-------------------------
//Define the methods
//-------------------------
//TODO: default stats as a parameter
int ServerApplication::CreateCharacter(int owner, std::string handle, std::string avatar) {
//Create the character, failing if it exists
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, CREATE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameters
bool ret = false;
ret |= sqlite3_bind_int(statement, 1, owner);
ret |= sqlite3_bind_text(statement, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC);
ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC);
//check for binding errors
if (ret) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than this character exists
sqlite3_finalize(statement);
return -1;
}
sqlite3_finalize(statement);
//load this character into memory
return LoadCharacter(owner, handle, avatar);
}
int ServerApplication::LoadCharacter(int owner, std::string handle, std::string avatar) {
//load the specified character, creating it if it doesn't exist
//fail if it is already loaded, or does not belong to this account
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, LOAD_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameter
if (sqlite3_bind_text(statement, 1, handle.c_str(), handle.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
int ret = sqlite3_step(statement);
//process the result
if (ret == SQLITE_ROW) {
//get the index
int uid = sqlite3_column_int(statement, 0);
//check to see if this character is already loaded
if (characterMap.find(uid) != characterMap.end()) {
sqlite3_finalize(statement);
return -1;
}
//check the owner
if (owner != sqlite3_column_int(statement, 1)) {
sqlite3_finalize(statement);
return -2;
}
//extract the data into memory
CharacterData& newChar = characterMap[uid];
//metadata
newChar.owner = owner;
newChar.handle = reinterpret_cast<const char*>(sqlite3_column_text(statement, 2));
newChar.avatar = reinterpret_cast<const char*>(sqlite3_column_text(statement, 3));
//Don't cache the birth
//world position
newChar.mapIndex = sqlite3_column_int(statement, 5);
newChar.position.x = (double)sqlite3_column_int(statement, 6);
newChar.position.y = (double)sqlite3_column_int(statement, 7);
//statistics
newChar.stats.level = sqlite3_column_int(statement, 8);
newChar.stats.exp = sqlite3_column_int(statement, 9);
newChar.stats.maxHP = sqlite3_column_int(statement, 10);
newChar.stats.health = sqlite3_column_int(statement, 11);
newChar.stats.maxMP = sqlite3_column_int(statement, 12);
newChar.stats.mana = sqlite3_column_int(statement, 13);
newChar.stats.attack = sqlite3_column_int(statement, 14);
newChar.stats.defence = sqlite3_column_int(statement, 15);
newChar.stats.intelligence = sqlite3_column_int(statement, 16);
newChar.stats.resistance = sqlite3_column_int(statement, 17);
newChar.stats.speed = sqlite3_column_int(statement, 18);
newChar.stats.accuracy = sqlite3_column_double(statement, 19);
newChar.stats.evasion = sqlite3_column_double(statement, 20);
newChar.stats.luck = sqlite3_column_double(statement, 21);
//TODO: equipment
//finish the routine
sqlite3_finalize(statement);
return uid;
}
sqlite3_finalize(statement);
if (ret == SQLITE_DONE) {
//create the non-existant character instead
return CreateCharacter(owner, handle, avatar);
}
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) ));
}
int ServerApplication::SaveCharacter(int uid) {
//save this character from memory, replacing it if it exists in the database
//DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID.
//this method fails if this character is not loaded
if (characterMap.find(uid) == characterMap.end()) {
return -1;
}
CharacterData& character = characterMap[uid];
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, SAVE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameters
bool ret = false;
ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 2, character.mapIndex) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 3, (int)character.position.x) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 4, (int)character.position.y) != SQLITE_OK;
//TODO: stats, etc.
//check for binding errors
if (ret) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than something went horribly wrong
sqlite3_finalize(statement);
throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) );
}
sqlite3_finalize(statement);
//successful execution
return 0;
}
void ServerApplication::UnloadCharacter(int uid) {
//save this character, then unload it
SaveCharacter(uid);
characterMap.erase(uid);
}
void ServerApplication::DeleteCharacter(int uid) {
//delete this character from the database, then remove it from memory
sqlite3_stmt* statement = nullptr;
//prep
if (sqlite3_prepare_v2(database, DELETE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
}
//parameter
if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) {
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
}
//execute
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than something went horribly wrong
sqlite3_finalize(statement);
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) );
}
//finish the routine
sqlite3_finalize(statement);
characterMap.erase(uid);
}
+34
View File
@@ -0,0 +1,34 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "enemy_factory_generic.hpp"
EnemyFactoryGeneric::EnemyFactoryGeneric() : EnemyFactoryInterface() {
//EMPTY
}
EnemyFactoryGeneric::~EnemyFactoryGeneric() noexcept {
//EMPTY
}
void EnemyFactoryGeneric::Generate(std::list<EnemyData>* container) {
//TODO: fill this out
}
+42
View File
@@ -0,0 +1,42 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 ENEMYFACTORYGENERIC_HPP_
#define ENEMYFACTORYGENERIC_HPP_
#include "enemy_factory_interface.hpp"
#include "enemy_data.hpp"
#include <list>
//DOCS: Not really intended for use, but rather for copying and tweaking
class EnemyFactoryGeneric : public EnemyFactoryInterface {
public:
EnemyFactoryGeneric();
~EnemyFactoryGeneric() noexcept override;
void Generate(std::list<EnemyData>* container) override;
private:
//TODO: hold the parameters specified by the room
};
#endif
+56
View File
@@ -0,0 +1,56 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 ENEMYFACTORYINTERFACE_HPP_
#define ENEMYFACTORYINTERFACE_HPP_
#include "enemy_data.hpp"
#include <list>
//TODO: move this elsewhere
enum RoomType {
OVERWORLD,
RUINS,
TOWERS,
FORESTS,
CAVES,
};
//NOTE: Based on biome, world difficulty, etc.
class EnemyFactoryInterface {
public:
EnemyFactoryInterface() = default;
virtual ~EnemyFactoryInterface() = default;
virtual void Generate(std::list<EnemyData>* container) = 0;
//control the difficulty of the room
RoomType SetType(RoomType t) { return type = t; }
int SetDifficulty(int d) { return difficulty = d; }
RoomType GetType() { return type; }
int GetDifficulty() { return difficulty; }
protected:
RoomType type;
int difficulty;
};
#endif
+6 -8
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -21,18 +21,18 @@
*/
#include "server_application.hpp"
#include "SDL/SDL.h"
#include <stdexcept>
#include <iostream>
using namespace std;
int main(int, char**) {
#ifdef DEBUG
int main(int argc, char** argv) {
cout << "Beginning server" << endl;
#endif
try {
ServerApplication app;
app.Init();
app.Init(argc, argv);
app.Proc();
app.Quit();
}
@@ -40,8 +40,6 @@ int main(int, char**) {
cerr << "Fatal error: " << e.what() << endl;
return 1;
}
#ifdef DEBUG
cout << "Clean exit" << endl;
#endif
return 0;
}
}
+6 -7
View File
@@ -1,15 +1,14 @@
#config
LOCALLIBS=../lib/libCommon.a
LIB=$(LOCALLIBS) -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL
INCLUDES=../common
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
INCLUDES+=. ../common/gameplay ../common/map ../common/network ../common/script ../common/utilities
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
SRC=$(wildcard *.cpp)
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=../out
@@ -17,7 +16,7 @@ OUT=$(addprefix $(OUTDIR)/,server)
#targets
all: $(OBJ) $(OUT)
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
$(OBJ): | $(OBJDIR)
-318
View File
@@ -1,318 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013
*
* 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 "server_application.hpp"
#include <stdexcept>
#include <iostream>
#include <chrono>
using namespace std;
//-------------------------
//Quick and dirty
//-------------------------
static std::string itos(int i) {
char buffer[20];
snprintf(buffer, 20, "%d", i);
return std::string(buffer);
}
//-------------------------
//Public access members
//-------------------------
ServerApplication::ServerApplication() {
//
}
ServerApplication::~ServerApplication() {
//
}
/* ServerApplication::Init()
* This function initializes the entire program. There are a number of things
* that could go wrong here, which is why there is such an unusual order of
* operations.
* Important things to note:
* The APIs are initiated here.
* The global objects are initialized here.
* The ConfigUtility's call to Load() also ensures that the "rsc\" folder is in the directory. It's easy to forget it.
*/
void ServerApplication::Init() {
//load the config file
try {
configUtil->Load("rsc/config.cfg");
}
catch(std::runtime_error& e) {
std::string s = e.what();
s += "; Ensure that the \"rsc\" directory is present";
throw(std::runtime_error(s));
}
//check the port is valid
if (configUtil->Int("server.port") <= 0) {
throw(runtime_error("Cannot open the server on an invalid port or port 0"));
}
//initialize the APIs
if (SDLNet_Init()) {
throw(runtime_error("Failed to initialize SDL_net"));
}
//initiate the remaining singletons
netUtil->Open(configUtil->Int("server.port"), sizeof(Packet));
//create the threads
beginQueueThread();
//output the server information
cout << configUtil->String("server.name") << endl;
cout << "Open on port " << configUtil->String("server.port") << endl;
//disable this for debugging
running = true;
}
void ServerApplication::Proc() {
typedef chrono::high_resolution_clock Clock;
Clock::time_point lastTick = Clock::now();
Clock::duration delta;
while(running) {
try {
//process all packets on the network queue
while(HandlePacket(popNetworkPacket()));
}
catch(exception& e) {
//handle any errors
cerr << "Network Error: " << e.what() << endl;
continue;
}
//get the time since last update
delta = Clock::now() - lastTick;
lastTick = Clock::now();
//update the world
UpdateWorld(double(delta.count()) / Clock::duration::period::den);
//give the machine a break
SDL_Delay(10);
}
}
void ServerApplication::Quit() {
//close the threads
endQueueThread();
//clean up the singletons
netUtil->Close();
//deinitialize the APIs
SDLNet_Quit();
}
//-------------------------
//Game loop
//-------------------------
void ServerApplication::UpdateWorld(double delta) {
//the recalc here each loop is a stopgap, see issue #9 for details
for (auto& it : players) {
if (it.second.motion.x != 0 && it.second.motion.y != 0) {
constexpr double d = 1.0/sqrt(2);
it.second.position += it.second.motion * delta * d;
}
else {
it.second.position += it.second.motion * delta;
}
}
}
//-------------------------
//Network loop
//-------------------------
int ServerApplication::HandlePacket(Packet p) {
switch(p.meta.type) {
case Packet::Type::NONE:
//DO NOTHING
return 0;
break;
case Packet::Type::PING:
//quick pong
p.meta.type = Packet::Type::PONG;
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
break;
case Packet::Type::PONG:
//
break;
case Packet::Type::BROADCAST_REQUEST:
HandleBroadcast(p);
break;
// case PacketType::BROADCAST_RESPONSE:
// //
// break;
case Packet::Type::JOIN_REQUEST:
HandleConnection(p);
break;
// case PacketType::JOIN_RESPONSE:
// //
// break;
case Packet::Type::DISCONNECT:
HandleDisconnection(p);
break;
case Packet::Type::SYNCHRONIZE:
SynchronizeEverything(p);
break;
case Packet::Type::PLAYER_NEW:
AddPlayer(p);
RelayPacket(p);
break;
case Packet::Type::PLAYER_DELETE:
RemovePlayer(p);
RelayPacket(p);
break;
case Packet::Type::PLAYER_UPDATE:
UpdatePlayer(p);
RelayPacket(p);
break;
default:
throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type))));
}
return 1;
}
void ServerApplication::RelayPacket(Packet& p) {
//pump this packet to all clients
for (auto& it : clients) {
netUtil->Send(&it.second.address, &p, sizeof(Packet));
}
}
void ServerApplication::SynchronizeEverything(Packet& sync) {
//send all known data to this client
//TODO multithreading?
//all players
Packet p;
p.meta.type = Packet::Type::PLAYER_UPDATE;
for (auto& it : players) {
p.meta.clientIndex = it.second.clientIndex;
p.playerInfo.index = it.second.index;
snprintf(p.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
snprintf(p.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
p.playerInfo.position = it.second.position;
p.playerInfo.motion = it.second.motion;
netUtil->Send(&clients[sync.meta.clientIndex].address, &p, sizeof(Packet));
}
}
void ServerApplication::HandleBroadcast(Packet& bcast) {
//respond to a broadcast request with the server's data
Packet p;
p.meta.type = Packet::Type::BROADCAST_RESPONSE;
snprintf(p.serverInfo.name, PACKET_STRING_SIZE, "%s", configUtil->CString("server.name"));
//TODO version information
netUtil->Send(&bcast.meta.address, &p, sizeof(Packet));
}
void ServerApplication::HandleConnection(Packet& request) {
//create the entries
ClientEntry newClient = {
uniqueIndex++,
request.meta.address
};
//push this information
clients[newClient.index] = newClient;
//send the player their information
Packet p;
p.meta.type = Packet::Type::JOIN_RESPONSE;
p.meta.clientIndex = newClient.index;
//TODO: resource list
netUtil->Send(&newClient.address, &p, sizeof(Packet));
//debugging
cout << "New connection: index " << newClient.index << endl;
cout << "number of clients: " << clients.size() << endl;
}
void ServerApplication::HandleDisconnection(Packet& disconnect) {
//disconnect a client (redundant message)
netUtil->Send(&clients[disconnect.meta.clientIndex].address, &disconnect, sizeof(Packet));
clients.erase(disconnect.meta.clientIndex);
//TODO remove the player...
//remove if(...)
//remove the player from other clients
//debugging
cout << "Lost connection: index " << disconnect.meta.clientIndex << endl;
cout << "number of clients: " << clients.size() << endl;
}
void ServerApplication::AddPlayer(Packet& p) {
//add the player
PlayerEntry newPlayer = {
uniqueIndex++,
p.meta.clientIndex,
p.playerInfo.handle,
p.playerInfo.avatar,
p.playerInfo.position,
p.playerInfo.motion
};
players[newPlayer.index] = newPlayer;
//prep for relay
p.playerInfo.index = newPlayer.index;
//debugging
cout << "New player " << newPlayer.handle << " has joined the game" << endl;
cout << "Number of players: " << players.size() << endl;
}
void ServerApplication::RemovePlayer(Packet& p) {
if (players.find(p.playerInfo.index) == players.end()) {
throw(runtime_error("Player to delete not found"));
}
players.erase(p.playerInfo.index);
}
void ServerApplication::UpdatePlayer(Packet& p) {
if (players.find(p.playerInfo.index) == players.end()) {
throw(runtime_error("Player to update not found"));
}
players[p.playerInfo.index].position = p.playerInfo.position;
players[p.playerInfo.index].motion = p.playerInfo.motion;
}

Some files were not shown because too many files have changed in this diff Show More