Compare commits
664 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0bbadb0bf | |||
| c6bc8c24fb | |||
| ffe5c80117 | |||
| 188a6805bf | |||
| 626435974e | |||
| b6c9361876 | |||
| 45f67476b8 | |||
| dfa8683c47 | |||
| c36c5210ab | |||
| 57a4fc8380 | |||
| caf6403a76 | |||
| f585b8adda | |||
| 3e42371e02 | |||
| 563a217237 | |||
| 41d601ab06 | |||
| 915660da0e | |||
| 3d6509b5a5 | |||
| dc5b09a9b4 | |||
| 371ca4a22c | |||
| 00fe2263d5 | |||
| f2ee1e8b24 | |||
| dd50287bdd | |||
| 2f86511254 | |||
| e8347cb9fb | |||
| 8c3f7913f6 | |||
| a7ce7a0e9b | |||
| a4d3a356c3 | |||
| fedc420c19 | |||
| b10572ccaf | |||
| ca67bf3bdd | |||
| f0ab1dfef8 | |||
| 8838fcd14e | |||
| 0150dbb929 | |||
| aa9081d9cf | |||
| 48f5512e1a | |||
| d2e75e02c5 | |||
| 4ced681c76 | |||
| e08e34b677 | |||
| af17bd2800 | |||
| 24eb730c72 | |||
| f82b0a8843 | |||
| 210bccbe0d | |||
| 68429806d1 | |||
| a8cf0a6947 | |||
| 822d0636cc | |||
| 164a3e18d9 | |||
| 3498b5d154 | |||
| 96c10da527 | |||
| 3856b3cdd2 | |||
| 661f6db82c | |||
| 99b35483f8 | |||
| 102ba18b7b | |||
| 07faf1b96b | |||
| 1d70e271b6 | |||
| 0bf5ccee4d | |||
| 35e7d0cf61 | |||
| 27fd810cfd | |||
| 8903b1e28d | |||
| c1ace69e19 | |||
| 5c404c572e | |||
| 878d502b8b | |||
| 2a1ee4acbf | |||
| 0e149acc62 | |||
| 63e4394583 | |||
| 7aeabf0d14 | |||
| 9d5a668045 | |||
| 0efb541074 | |||
| 4ae58550b5 | |||
| d82e3a8b79 | |||
| 954213f1ff | |||
| d2bb3575fc | |||
| ca6afb72ad | |||
| 670ab22e96 | |||
| 4d71d4cc40 | |||
| 81b3769188 | |||
| c3c6d42a80 | |||
| 3d8ee25ae7 | |||
| decc77e21c | |||
| 501b1e9814 | |||
| 01502372c9 | |||
| a8c309ec9d | |||
| 41d6314beb | |||
| 74ed93ddc7 | |||
| 18a7143926 | |||
| bd68af5875 | |||
| b8806cc209 | |||
| edcb6f05ce | |||
| cb63c9b07c | |||
| a00ddb3142 | |||
| 3431d323e5 | |||
| 84c4dd0497 | |||
| 3e6a05307e | |||
| c45bda645b | |||
| 1210d2d24f | |||
| 894b53e760 | |||
| 4630b7e403 | |||
| 067bf40be7 | |||
| d8045ae339 | |||
| eff23352aa | |||
| 46df0f17b7 | |||
| ddedc06e47 | |||
| 6a999a8a72 | |||
| 8a97cb8c2c | |||
| e011e6bdc5 | |||
| a106134dd1 | |||
| a538cf73d5 | |||
| b273b4c04a | |||
| 248d142c2b | |||
| 2cc7260552 | |||
| fa4ccb6596 | |||
| 87af4f1a1e | |||
| 18b144fa46 | |||
| e71d0b3a09 | |||
| 9710acad6f | |||
| ca2d4c9217 | |||
| bad6cc2fab | |||
| 95e3ce9a69 | |||
| 5583ba4323 | |||
| a18577665a | |||
| 0bdafe7e15 | |||
| 38f6ced633 | |||
| 65f23bbd1a | |||
| 453a211343 | |||
| 1e8f91a871 | |||
| 2a86a09693 | |||
| bd878e20ce | |||
| 92a02c7f0c | |||
| dacb8df674 | |||
| 7356e8ae77 | |||
| 9b2e78a68e | |||
| be90694234 | |||
| e2757a7628 | |||
| 42662c3f61 | |||
| e752dd7b0f | |||
| 44e24b667e | |||
| de6eb38516 | |||
| 74bf70c44d | |||
| cd06ccc1a5 | |||
| dc40ee64cf | |||
| de1cd8d6a8 | |||
| 1923f90329 | |||
| eeac329c49 | |||
| f13e8479e4 | |||
| cf1008f0d9 | |||
| dfae33cbd1 | |||
| 9f3721247d | |||
| d0b2f8e12f | |||
| 051ed0f14c | |||
| 8ea667a0b5 | |||
| b391dde089 | |||
| be67906218 | |||
| 70d4233a15 | |||
| 31fc5a8fa5 | |||
| 1973cfd061 | |||
| 3322783d95 | |||
| 9895e27d5a | |||
| 877c0f59d3 | |||
| 92eb75af7e | |||
| d815f17442 | |||
| 0344fe0d6d | |||
| a10636e067 | |||
| 4b8f9b4330 | |||
| eb897c81e8 | |||
| 963aca218a | |||
| c6981e6216 | |||
| 8b8ef088d9 | |||
| 6704944105 | |||
| 8e50be24d4 | |||
| f9c19a630d | |||
| 78c04718e0 | |||
| bb592b2436 | |||
| 4b5011a579 | |||
| f3fb5017b3 | |||
| 3a9fdd511b | |||
| 57c6f45c21 | |||
| 8d204dc3c4 | |||
| 9413adcf4a | |||
| 99af76c5b5 | |||
| cc6458daa7 | |||
| 8708cfbee0 | |||
| b67e85e87b | |||
| 33c3143de9 | |||
| ce16fc6969 | |||
| f6e90d7e39 | |||
| ee0b7884a8 | |||
| 7e5a7f8183 | |||
| f2d517df9d | |||
| 6c11aa0927 | |||
| 398f1c8bfd | |||
| 3e2d1a5a56 | |||
| f52eafdf55 | |||
| dff04b5b69 | |||
| 900f623f3b | |||
| 44a1edac30 | |||
| 2ae2c48819 | |||
| 07af05712b | |||
| 15ea360b8a | |||
| 0d9dfad4a5 | |||
| 7962692641 | |||
| 4d1bb17382 | |||
| 015631a73d | |||
| 3399053e64 | |||
| ae046977f0 | |||
| 72f641bf63 | |||
| dbd1289ced | |||
| de4e539449 | |||
| 61f462a882 | |||
| 5607f76ce7 | |||
| 0e666d3203 | |||
| f50406d69f | |||
| cc167180f6 | |||
| c89f94b681 | |||
| 822ff5827e | |||
| 8579d7e0d6 | |||
| 06eb1f2e9e | |||
| b59cd0fe87 | |||
| bac8bc2b41 | |||
| e5abd51f76 | |||
| 584b6ea303 | |||
| 01461deaa5 | |||
| fa0d232727 | |||
| 6485839dcf | |||
| 81a3a92603 | |||
| 9ba76c8987 | |||
| 5eeda8235d | |||
| 20d40d5b81 | |||
| 5e11077c7a | |||
| 5deb6a9d8e | |||
| ba81bcba69 | |||
| 9329274866 | |||
| ace87b438b | |||
| 1f3c1f32f4 | |||
| cacd3dcd6d | |||
| 97b7945191 | |||
| a01d75549f | |||
| ecd0b43abe | |||
| d35ab24e15 | |||
| 100c4f6522 | |||
| a1c20959fe | |||
| 3b9df46510 | |||
| f7ba34dcec | |||
| 3192524922 | |||
| 74234684af | |||
| 06e027710f | |||
| 73d9095604 | |||
| f2d79225a3 | |||
| daa38413f3 | |||
| a4ed23f6c7 | |||
| cfdc61c357 | |||
| 77b47b4634 | |||
| 0f139562c3 | |||
| fc2bc06992 | |||
| 8eefdd71b5 | |||
| 966443be3d | |||
| 5327d91917 | |||
| 6399efc227 | |||
| 7da5de619b | |||
| 0735037f10 | |||
| 8c78a5d26c | |||
| f584dd140b | |||
| 4434900afc | |||
| 2a7a2889c6 | |||
| e488b15acc | |||
| 387e86de63 | |||
| 0e3a042fbb | |||
| de7167e830 | |||
| 40c76b4285 | |||
| 12cc970bf1 | |||
| bd2fd4ee97 | |||
| c3041d2a74 | |||
| 974effd95e | |||
| f3073efa39 | |||
| 1761134839 | |||
| 7c4762852b | |||
| 8dcd02aba3 | |||
| 4d6186021f | |||
| b7847d6260 | |||
| 869780589f | |||
| 254b97aa80 | |||
| 5a42a7e36c | |||
| 76206a1146 | |||
| 1f099a07dc | |||
| 356d83caf6 | |||
| be9ce33637 | |||
| 9b43b4641f | |||
| 6589a1a06d | |||
| db40f198be | |||
| 87ef03d512 | |||
| 8e97de6979 | |||
| d4740df996 | |||
| 926871d5fe | |||
| c010c0da0a | |||
| 8dc41886ef | |||
| e452f2ecfc | |||
| bfcf9a1d37 | |||
| 59e3518dd8 | |||
| 58bb70d1c5 | |||
| 9367bd802f | |||
| 411687b41c | |||
| ad2c65dc67 | |||
| 712d94d3b2 | |||
| 17b9eb7ad4 | |||
| 2c06232264 | |||
| 4c882682ed | |||
| f581c3238f | |||
| ceb6fe73f5 | |||
| 246a5ee541 | |||
| 79c7e48139 | |||
| 06922dc820 | |||
| 5577387d61 | |||
| d50cf5b91e | |||
| 6ca62db16d | |||
| 5536bf366d | |||
| 094efad728 | |||
| f77aec6dd7 | |||
| 6f4334f84d | |||
| 4ed512e0e2 | |||
| d0cc5521da | |||
| af8e7b70a0 | |||
| 8bc1326fef | |||
| dfe8c108de | |||
| 61337e29f6 | |||
| 5dea53ad50 | |||
| f52a022e64 | |||
| 0fdaa90a83 | |||
| e7ba097e6a | |||
| 3b409a8608 | |||
| ce97245131 | |||
| 59c9ba698f | |||
| 52ab9f0087 | |||
| 4ea1f8b016 | |||
| f1080151e3 | |||
| 5af0a7999c | |||
| 1e9ac9815b | |||
| 98ffcb8cd3 | |||
| 1b041d7771 | |||
| 6d98bab000 | |||
| b6c70cbc0d | |||
| e56a3d121c | |||
| 1776583e01 | |||
| 74f809a801 | |||
| 182101b592 | |||
| 07885cca1b | |||
| 956e920b7a | |||
| 908f91d674 | |||
| fd320767c5 | |||
| c830fa0537 | |||
| 10c89970cc | |||
| 0b512305a9 | |||
| 555abf9c95 | |||
| 2b3ea5eb80 | |||
| 66815016ba | |||
| 46f02dcfdd | |||
| 414a0896c9 | |||
| 0077d501ac | |||
| e946a0741d | |||
| 839c2af940 | |||
| f70241cc57 | |||
| 36d30ce39b | |||
| 28d083cba4 | |||
| 4dd4b37fc0 | |||
| 82b1b589dc | |||
| bac493c96b | |||
| d5520e83c6 | |||
| 93480be685 | |||
| 8ed308e89a | |||
| 8df1ecd804 | |||
| 8c9d071c7a | |||
| ac1098fa86 | |||
| deba324449 | |||
| 95362286f8 | |||
| f5c58bf5ad | |||
| 316db43b0a | |||
| 46ed196bf4 | |||
| 64baa63d12 | |||
| e19b6fbc23 | |||
| a64411a567 | |||
| 3662a97475 | |||
| 97aaacbc23 | |||
| 8afd0e7c8a | |||
| 82c776df83 | |||
| 924ebc2ee9 | |||
| d3bf099a98 | |||
| a6de5f9e69 | |||
| 618666de43 | |||
| 5c74ecdd72 | |||
| 61848db65b | |||
| dfc464ddd6 | |||
| bd5e57401e | |||
| a23fbbfb38 | |||
| c021032512 | |||
| d4be22a6eb | |||
| c210b99a5f | |||
| 01eb934fad | |||
| 52e6b144c1 | |||
| b418ad713d | |||
| 1bc51fe035 | |||
| 793737e1ed | |||
| e57b047343 | |||
| a11867126c | |||
| bf4a7561ed | |||
| 13332bf3fc | |||
| 955aed2224 | |||
| ee79231de0 | |||
| 5128d17759 | |||
| a07e7418a6 | |||
| 1ef5eb7a0f | |||
| 135e650ec8 | |||
| b7c12ba106 | |||
| 2d27399fd1 | |||
| ba83fac29f | |||
| 3bd4f1bb1d | |||
| b269ce5fb9 | |||
| f034c32c38 | |||
| 5175a4e40d | |||
| ee2ac0b7a9 | |||
| 63be0ee70d | |||
| cac273da5e | |||
| 170096b5db | |||
| 10e857ecd1 | |||
| 5c8572d811 | |||
| 973a2be16b | |||
| 9b9f6700af | |||
| 7fb458ddc1 | |||
| 310f701b0d | |||
| 6664f8a8bc | |||
| 2c9b0fc3e7 | |||
| 5966d7b51a | |||
| 46dff9b97b | |||
| 23364b2810 | |||
| da60fa8f94 | |||
| fbac14e188 | |||
| 0a03535ecb | |||
| 2bebfdfb97 | |||
| fb6fba9564 | |||
| d2f03b98dc | |||
| 4acd350219 | |||
| 9d83abbd38 | |||
| 1cfb814ee4 | |||
| 2e8a474792 | |||
| 93c41bb19c | |||
| bf922ec598 | |||
| de902d2d3d | |||
| 7b3bf24e5d | |||
| de7da81102 | |||
| 6428b02d85 | |||
| 519b8a1e36 | |||
| 967f0653a1 | |||
| b86d393571 | |||
| 6b38501c27 | |||
| 5893342ad8 | |||
| ac4a264f12 | |||
| 43895a462a | |||
| 1bde0ed3f7 | |||
| d903c0df30 | |||
| 9620826d65 | |||
| 0a71f43ef3 | |||
| a47e76845f | |||
| c2eb08bd5e | |||
| 7b76e07231 | |||
| 1dd8042d3d | |||
| c575ee9ce1 | |||
| 1befc76b70 | |||
| 6a6e7f7125 | |||
| bb6e248583 | |||
| f7df4fba6c | |||
| e7403be508 | |||
| 873715b28c | |||
| b1d6e5a314 | |||
| f0453375c4 | |||
| e5a98efd7d | |||
| 14b330009b | |||
| 288b62d3f8 | |||
| c5e8f1b3af | |||
| 980717f9fd | |||
| 68475eee0f | |||
| eeb2400e79 | |||
| 01244005e9 | |||
| c5005b9b07 | |||
| 80a26341b1 | |||
| b7877962f1 | |||
| 688d064085 | |||
| 1c4d53e3ef | |||
| a53a134163 | |||
| 4d12788c53 | |||
| 1beb7cbd5d | |||
| 8358d72a98 | |||
| 4ebff4a25a | |||
| 0ff787abda | |||
| 9b5b48a8ab | |||
| 5dd0fb9e23 | |||
| 7c210e04a5 | |||
| 9236e02101 | |||
| 8f4ebf20da | |||
| 910e51f637 | |||
| 92fc9b4e25 | |||
| 2b8e7241c9 | |||
| 124cb3ad13 | |||
| 6d3400d948 | |||
| 5031352fe3 | |||
| 624369f147 | |||
| 9a7f7b8684 | |||
| fa9487c2f2 | |||
| 9ec1ddab99 | |||
| 6f1c2d0555 | |||
| 01b50d5590 | |||
| 9c673928e6 | |||
| d55dfb90e4 | |||
| 235a05d006 | |||
| dabb7b3b2e | |||
| e756289c2b | |||
| c534158c2e | |||
| b47191a0c1 | |||
| 6c6a025f2a | |||
| 60edc97ea5 | |||
| a5b209d9e0 | |||
| fd673a415f | |||
| 4270765146 | |||
| f56cb58dfb | |||
| f315f4bf35 | |||
| 69765de433 | |||
| 35d463d4ba | |||
| 894b46c5db | |||
| eb0b18af6f | |||
| fba183fa27 | |||
| c5a627004a | |||
| ac27fb0ca7 | |||
| be4a8311d5 | |||
| 6d32d44fa3 | |||
| 9bacfb1424 | |||
| c3464be589 | |||
| 7fe71c60d0 | |||
| 0c6537fb36 | |||
| 854dc0eb45 | |||
| e90afb7e4a | |||
| 0453f6becf | |||
| c8a58ab515 | |||
| 553f8dbfa5 | |||
| 2bacdcdab7 | |||
| 99aecbfdbb | |||
| 27bda5dc28 | |||
| 962f3f5dd0 | |||
| 41077b43b3 | |||
| 4410ab892f | |||
| 60000cb0cf | |||
| 66b00255d5 | |||
| a5b68cf1fd | |||
| 4cff57fe71 | |||
| 38b603fc8f | |||
| 47684380a9 | |||
| e4bfbfb906 | |||
| 9db86c19f6 | |||
| d5b551cec3 | |||
| 7e500027e3 | |||
| dd786ba579 | |||
| 5a57888305 | |||
| 706aa5e1d7 | |||
| 19c1b1197d | |||
| 5cf62f5517 | |||
| 56d02ad8d4 | |||
| 006a72174f | |||
| 0cbc9dd9db | |||
| 60c31ff56d | |||
| 6a204643f6 | |||
| 59285d1630 | |||
| a850d6b1af | |||
| f17fa0f345 | |||
| 756d4e770d | |||
| 7bb5e8ce0d | |||
| 975533afba | |||
| 19749f7c87 | |||
| 7703c4b0ad | |||
| dc8f594eec | |||
| 4629b7302b | |||
| 02d83d1f16 | |||
| 91c9cef56d | |||
| f7d4912942 | |||
| eb8674b84f | |||
| ff44e4d916 | |||
| e66540f114 | |||
| 639c0c70e3 | |||
| 37b02352e2 | |||
| 31c8bd7fd2 | |||
| 808fe570a3 | |||
| e706cc9d13 | |||
| eb02cc4b6a | |||
| 31cca61d1c | |||
| 071e0d9021 | |||
| a494bfbb38 | |||
| baadf554cd | |||
| 9df16fede0 | |||
| dd0ad31ac6 | |||
| be26c9d103 | |||
| a448c8fb68 | |||
| de1a6a050f | |||
| 49c9abe91b | |||
| 3b05476689 | |||
| 1c032bfc47 | |||
| 1a7457f650 | |||
| e640eda771 | |||
| fc2b67608f | |||
| a3a990cc01 | |||
| f6a4674a2f | |||
| 865620b4a8 | |||
| 1e0ed350fc | |||
| 6ccc874583 | |||
| ca86dc5fb8 | |||
| e3605e4dc5 | |||
| cb9aef95ec | |||
| 09f97de0e6 | |||
| f5466b9982 | |||
| e176a60d28 | |||
| dc24d1b059 | |||
| fa3fc18ddf | |||
| c2941cd3e8 | |||
| bf15a5d957 | |||
| f01463bab3 | |||
| 54cd26b76f | |||
| 2bd8adaf69 | |||
| 26eba2def6 | |||
| 43852ce755 | |||
| 81fab06e3b | |||
| 77a90f9c0c | |||
| bc32f2a2f0 | |||
| 76bfecd466 | |||
| d4eb1e7b8d | |||
| 2ec307510d | |||
| 0b4e6003d6 | |||
| 7e603ffa89 | |||
| 6fc8570cf4 | |||
| 0bfd916df4 | |||
| 88aee0f4f5 | |||
| 0d3c3243a0 | |||
| 871b1136c2 | |||
| f64c935ffe | |||
| 600ec6789b | |||
| 65a3937592 | |||
| 719c8f49a6 | |||
| 29928c0b92 | |||
| a88a1f7cf7 | |||
| 46efbfbe9a | |||
| 26ff8dcc8f | |||
| 9c91e9d5fd | |||
| 3628d3c1fd | |||
| 6c9406147a | |||
| aae244de39 | |||
| d5b14c2679 | |||
| a54fbfb9e9 | |||
| 9cbbfe77b7 | |||
| 9b64c67068 | |||
| de0227a1cf | |||
| 1dfeabf195 | |||
| 6c5197f3f2 | |||
| 09453cc24e | |||
| 4b62310158 | |||
| 43f2190c3e | |||
| 3225da6b13 | |||
| 0c233b8764 | |||
| 027d0125ef | |||
| e4884c3e18 | |||
| b675f516e7 | |||
| d5f7363c33 | |||
| 7458962ad4 | |||
| 0a0b61287e |
@@ -0,0 +1,24 @@
|
||||
#Editor generated files
|
||||
*.sln
|
||||
*.vcproj
|
||||
*.suo
|
||||
*.ncb
|
||||
*.user
|
||||
|
||||
#Directories
|
||||
Release/
|
||||
Debug/
|
||||
Out/
|
||||
release/
|
||||
debug/
|
||||
out/
|
||||
|
||||
#Project generated files
|
||||
*.db
|
||||
*.o
|
||||
*.a
|
||||
*.exe
|
||||
|
||||
#Shell files
|
||||
*.bat
|
||||
*.sh
|
||||
@@ -0,0 +1,6 @@
|
||||
[submodule "common"]
|
||||
path = common
|
||||
url = https://github.com/Ratstail91/Tortuga.git
|
||||
[submodule "bin"]
|
||||
path = bin
|
||||
url = https://github.com/Ratstail91/Tortuga.git
|
||||
@@ -0,0 +1,46 @@
|
||||
## Outline
|
||||
|
||||
Tortuga is a 2D MMORPG featuring permadeath, with an emphasis on multiplayer cooperation, exploration and customization. The game runs on customizable public and private servers.
|
||||
|
||||
This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), as well as more modern sandboxes and MMOs (Minecraft, EVE Online). This project is currently independently created and funded, with the goal of creating a game that will engage the players and inspire a large community.
|
||||
|
||||
## Releases
|
||||
|
||||
* The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-win.rar).
|
||||
* The most recent stable build for Linux can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-linux.tar).
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Tortuga Wiki](https://github.com/Ratstail91/Tortuga/wiki) - Full documentation (incomplete)
|
||||
* [Tortuga Bug Tracker](https://github.com/Ratstail91/Tortuga/issues) - A list of all known bugs and issues
|
||||
|
||||
## External Dependencies
|
||||
|
||||
* [SDL 2.0](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
||||
* [SDL_image 2.0](https://www.libsdl.org/projects/SDL_image/) - An SDL Extension for loading multiple image file formats
|
||||
* [SDL_net 2.0](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
|
||||
* [SDL_ttf 2.0](https://www.libsdl.org/projects/SDL_ttf/) - An SDL extention for rendering fonts
|
||||
* [lua 5.2](http://www.lua.org/) - The lua programming language
|
||||
* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine
|
||||
|
||||
## Tools
|
||||
|
||||
* [WinRAR](http://www.rarlab.com/) - A free archive tool; needed for Windows distribution
|
||||
* [tar](http://www.gnu.org/software/tar/manual/) - The GNU archive tool; needed for Linux distribution
|
||||
* [Dropbox](https://www.dropbox.com/) - For hosting and distribution
|
||||
|
||||
## 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-2015 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.
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,105 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "base_scene.hpp"
|
||||
|
||||
SDL_Renderer* BaseScene::rendererHandle = nullptr;
|
||||
|
||||
BaseScene::BaseScene() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
BaseScene::~BaseScene() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::RenderFrame(SDL_Renderer* renderer) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::SetRenderer(SDL_Renderer* r) {
|
||||
rendererHandle = r;
|
||||
}
|
||||
|
||||
SDL_Renderer* BaseScene::GetRenderer() {
|
||||
return rendererHandle;
|
||||
}
|
||||
|
||||
void BaseScene::SetSceneSignal(SceneSignal signal) {
|
||||
sceneSignal = signal;
|
||||
}
|
||||
|
||||
SceneSignal BaseScene::GetSceneSignal() {
|
||||
return sceneSignal;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//frame phases
|
||||
//-------------------------
|
||||
|
||||
void BaseScene::FrameStart() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::Update() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::FrameEnd() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//input events
|
||||
//-------------------------
|
||||
|
||||
void BaseScene::QuitEvent() {
|
||||
sceneSignal = SceneSignal::QUIT;
|
||||
}
|
||||
|
||||
void BaseScene::MouseMotion(SDL_MouseMotionEvent const& event) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::MouseButtonDown(SDL_MouseButtonEvent const& event) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::MouseButtonUp(SDL_MouseButtonEvent const& event) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::MouseWheel(SDL_MouseWheelEvent const& event) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void BaseScene::KeyDown(SDL_KeyboardEvent const& event) {
|
||||
//preference as a default
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseScene::KeyUp(SDL_KeyboardEvent const& event) {
|
||||
//EMPTY
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "scene_signal.hpp"
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
|
||||
class BaseScene {
|
||||
public:
|
||||
BaseScene();
|
||||
virtual ~BaseScene();
|
||||
|
||||
virtual void RenderFrame(SDL_Renderer*);
|
||||
static void SetRenderer(SDL_Renderer*);
|
||||
SceneSignal GetSceneSignal();
|
||||
|
||||
//frame phases
|
||||
virtual void FrameStart();
|
||||
virtual void Update();
|
||||
virtual void FrameEnd();
|
||||
|
||||
//input events
|
||||
virtual void QuitEvent();
|
||||
virtual void MouseMotion(SDL_MouseMotionEvent const& event);
|
||||
virtual void MouseButtonDown(SDL_MouseButtonEvent const& event);
|
||||
virtual void MouseButtonUp(SDL_MouseButtonEvent const& event);
|
||||
virtual void MouseWheel(SDL_MouseWheelEvent const& event);
|
||||
virtual void KeyDown(SDL_KeyboardEvent const& event);
|
||||
virtual void KeyUp(SDL_KeyboardEvent const& event);
|
||||
|
||||
//TODO: (9) joystick and controller events
|
||||
|
||||
protected:
|
||||
//control
|
||||
static SDL_Renderer* GetRenderer();
|
||||
void SetSceneSignal(SceneSignal);
|
||||
|
||||
private:
|
||||
static SDL_Renderer* rendererHandle;
|
||||
SceneSignal sceneSignal = SceneSignal::CONTINUE;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,11 +19,8 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "timer.hpp"
|
||||
#pragma once
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Timer& t) {
|
||||
os << t.GetName() << ": ";
|
||||
os << std::chrono::duration_cast<std::chrono::nanoseconds>(t.GetTime()).count();
|
||||
os << "ns";
|
||||
return os;
|
||||
}
|
||||
enum Channels {
|
||||
SERVER = 0
|
||||
};
|
||||
@@ -0,0 +1,355 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "client_application.hpp"
|
||||
|
||||
#include "serial_packet.hpp"
|
||||
#include "config_utility.hpp"
|
||||
|
||||
//for handling platforms
|
||||
#include "SDL2/SDL_syswm.h"
|
||||
#include "SDL2/SDL_version.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
void ClientApplication::Init(int argc, char* argv[]) {
|
||||
std::cout << "Beginning " << argv[0] << std::endl;
|
||||
|
||||
//load the prerequisites
|
||||
ConfigUtility& config = ConfigUtility::GetSingleton();
|
||||
config.Load("rsc/config.cfg", false, argc, argv);
|
||||
|
||||
//-------------------------
|
||||
//create and check the window
|
||||
//-------------------------
|
||||
|
||||
//get the config values
|
||||
int w = config.Int("client.screen.w");
|
||||
int h = config.Int("client.screen.h");
|
||||
int f = config.Boolean("client.screen.f") ? SDL_WINDOW_FULLSCREEN : 0;
|
||||
|
||||
//BUG: fullscreen is disabled
|
||||
f = 0;
|
||||
|
||||
//default sizes
|
||||
w = w ? w : 800;
|
||||
h = h ? h : 600;
|
||||
|
||||
window = SDL_CreateWindow(argv[0], SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, f);
|
||||
|
||||
if (!window) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to create the window: " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
std::cout << "Initialized the window" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//DEBUG: detecting platforms, versions & appropriate fonts
|
||||
//-------------------------
|
||||
|
||||
SDL_SysWMinfo windowInfo;
|
||||
SDL_VERSION(&windowInfo.version);
|
||||
if (SDL_GetWindowWMInfo(window, &windowInfo)) {
|
||||
//
|
||||
std::string platform;
|
||||
std::string fontPath;
|
||||
|
||||
//get the info
|
||||
switch(windowInfo.subsystem) {
|
||||
case SDL_SYSWM_WINDOWS:
|
||||
platform = "Microsoft Windows";
|
||||
fontPath = "C:/Windows/Fonts/arialbd.ttf";
|
||||
break;
|
||||
|
||||
case SDL_SYSWM_X11:
|
||||
platform = "X Window System";
|
||||
fontPath = "/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf";
|
||||
break;
|
||||
|
||||
//NOTE: OS X is currently unsupported, but it could be
|
||||
case SDL_SYSWM_COCOA:
|
||||
platform = "Apple OS X";
|
||||
fontPath = "/System/Library/Fonts/arialbd.ttf";
|
||||
break;
|
||||
|
||||
default:
|
||||
platform = "an unsupported platform";
|
||||
}
|
||||
|
||||
//final output
|
||||
std::cout << "SDL Version ";
|
||||
std::cout << (int)windowInfo.version.major << ".";
|
||||
std::cout << (int)windowInfo.version.minor << ".";
|
||||
std::cout << (int)windowInfo.version.patch << " on ";
|
||||
std::cout << platform << std::endl;
|
||||
|
||||
//handle the default font paths
|
||||
if (config["client.font"].size() == 0) {
|
||||
config["client.font"] = fontPath;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to retrieve window info: " << SDL_GetError();
|
||||
throw(msg.str());
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//create and check the renderer
|
||||
//-------------------------
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||
|
||||
if (!renderer) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to create the renderer: " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//screen scaling
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
|
||||
SDL_RenderSetLogicalSize(renderer, w, h);
|
||||
|
||||
//set the hook for the renderer
|
||||
BaseScene::SetRenderer(renderer);
|
||||
|
||||
std::cout << "Initialized the renderer" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Initialize the APIs
|
||||
//-------------------------
|
||||
|
||||
//initialize SDL_net
|
||||
if (SDLNet_Init()) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to initialize SDL_net 2.0: " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
UDPNetworkUtility::GetSingleton().Open(0);
|
||||
|
||||
std::cout << "Initialized SDL_net 2.0" << std::endl;
|
||||
|
||||
//setting up SDL2_ttf
|
||||
if (TTF_Init()) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to initialize SDL_ttf 2.0: " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
std::cout << "Initialized SDL_ttf 2.0" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//debug output
|
||||
//-------------------------
|
||||
|
||||
#define DEBUG_INTERNAL_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl;
|
||||
|
||||
std::cout << "Internal sizes:" << std::endl;
|
||||
|
||||
DEBUG_INTERNAL_VAR(NETWORK_VERSION);
|
||||
DEBUG_INTERNAL_VAR(sizeof(Region::type_t));
|
||||
DEBUG_INTERNAL_VAR(sizeof(Region));
|
||||
DEBUG_INTERNAL_VAR(REGION_WIDTH);
|
||||
DEBUG_INTERNAL_VAR(REGION_HEIGHT);
|
||||
DEBUG_INTERNAL_VAR(REGION_DEPTH);
|
||||
DEBUG_INTERNAL_VAR(REGION_TILE_FOOTPRINT);
|
||||
DEBUG_INTERNAL_VAR(REGION_SOLID_FOOTPRINT);
|
||||
DEBUG_INTERNAL_VAR(PACKET_STRING_SIZE);
|
||||
DEBUG_INTERNAL_VAR(PACKET_BUFFER_SIZE);
|
||||
DEBUG_INTERNAL_VAR(MAX_PACKET_SIZE);
|
||||
DEBUG_INTERNAL_VAR(static_cast<int>(SerialPacketType::LAST));
|
||||
|
||||
//-------------------------
|
||||
//finalize the startup
|
||||
//-------------------------
|
||||
|
||||
std::cout << "Startup completed successfully" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//debugging
|
||||
//-------------------------
|
||||
|
||||
//...
|
||||
}
|
||||
|
||||
void ClientApplication::Proc() {
|
||||
//load the first scene
|
||||
ProcessSceneSignal(SceneSignal::FIRST);
|
||||
|
||||
//fixed frame rate
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
|
||||
Clock::time_point simTime = Clock::now();
|
||||
Clock::time_point realTime;
|
||||
constexpr std::chrono::duration<int, std::milli> frameDelay(16); //~60FPS
|
||||
|
||||
//the game loop continues until the scenes signal QUIT
|
||||
while(activeScene->GetSceneSignal() != SceneSignal::QUIT) {
|
||||
//switch scenes if necessary
|
||||
if(activeScene->GetSceneSignal() != SceneSignal::CONTINUE) {
|
||||
ProcessSceneSignal(activeScene->GetSceneSignal());
|
||||
continue;
|
||||
}
|
||||
|
||||
//update the current time
|
||||
realTime = Clock::now();
|
||||
|
||||
//simulate the game or give the machine a break
|
||||
if (simTime < realTime) {
|
||||
while(simTime < realTime) {
|
||||
//call the user defined functions
|
||||
activeScene->FrameStart();
|
||||
ProcessEvents();
|
||||
activeScene->Update();
|
||||
activeScene->FrameEnd();
|
||||
|
||||
//step to the next frame
|
||||
simTime += frameDelay;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
activeScene->RenderFrame(renderer);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
ClearScene();
|
||||
}
|
||||
|
||||
void ClientApplication::Quit() {
|
||||
//clean up after the program
|
||||
std::cout << "Shutting down" << std::endl;
|
||||
UDPNetworkUtility::GetSingleton().Close();
|
||||
TTF_Quit();
|
||||
SDLNet_Quit();
|
||||
BaseScene::SetRenderer(nullptr);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
std::cout << "Clean exit" << std::endl;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Scene management
|
||||
//-------------------------
|
||||
|
||||
void ClientApplication::ProcessEvents() {
|
||||
SDL_Event event;
|
||||
while(SDL_PollEvent(&event)) {
|
||||
switch(event.type) {
|
||||
case SDL_QUIT:
|
||||
activeScene->QuitEvent();
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
activeScene->MouseMotion(event.motion);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
activeScene->MouseButtonDown(event.button);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
activeScene->MouseButtonUp(event.button);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEWHEEL:
|
||||
activeScene->MouseWheel(event.wheel);
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
activeScene->KeyDown(event.key);
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
activeScene->KeyUp(event.key);
|
||||
break;
|
||||
|
||||
//TODO: (9) joystick and controller events
|
||||
|
||||
//window events are handled internally
|
||||
case SDL_WINDOWEVENT:
|
||||
switch(event.window.event) {
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
SDL_RenderSetLogicalSize(renderer, event.window.data1, event.window.data2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add the custom scene headers here
|
||||
#include "splash_screen.hpp"
|
||||
#include "main_menu.hpp"
|
||||
#include "options_menu.hpp"
|
||||
#include "lobby_menu.hpp"
|
||||
#include "world.hpp"
|
||||
#include "disconnected_screen.hpp"
|
||||
|
||||
void ClientApplication::ProcessSceneSignal(SceneSignal signal) {
|
||||
//BUG: #16 Resources are being reloaded between scenes
|
||||
ClearScene();
|
||||
switch(signal) {
|
||||
//add scene creation calls here
|
||||
case SceneSignal::FIRST:
|
||||
case SceneSignal::SPLASHSCREEN:
|
||||
activeScene = new SplashScreen(window);
|
||||
break;
|
||||
case SceneSignal::MAINMENU:
|
||||
activeScene = new MainMenu();
|
||||
break;
|
||||
case SceneSignal::OPTIONSMENU:
|
||||
activeScene = new OptionsMenu();
|
||||
break;
|
||||
case SceneSignal::LOBBYMENU:
|
||||
activeScene = new LobbyMenu(&clientIndex, &accountIndex);
|
||||
break;
|
||||
case SceneSignal::WORLD:
|
||||
activeScene = new World(&clientIndex, &accountIndex);
|
||||
break;
|
||||
case SceneSignal::DISCONNECTEDSCREEN:
|
||||
activeScene = new DisconnectedScreen();
|
||||
break;
|
||||
default: {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to recognize the scene signal: " << signal;
|
||||
throw(std::logic_error(msg.str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientApplication::ClearScene() {
|
||||
delete activeScene;
|
||||
activeScene = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base_scene.hpp"
|
||||
#include "scene_signal.hpp"
|
||||
#include "singleton.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_net.h"
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
class ClientApplication: public Singleton<ClientApplication> {
|
||||
public:
|
||||
void Init(int argc, char* argv[]);
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
friend Singleton<ClientApplication>;
|
||||
|
||||
ClientApplication() = default;
|
||||
~ClientApplication() = default;
|
||||
|
||||
//scene management
|
||||
void ProcessEvents();
|
||||
void ProcessSceneSignal(SceneSignal);
|
||||
void ClearScene();
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
|
||||
//TODO: (9) build a "window" class?
|
||||
SDL_Window* window = nullptr;
|
||||
SDL_Renderer* renderer = nullptr;
|
||||
|
||||
//shared parameters
|
||||
int clientIndex = -1;
|
||||
int accountIndex = -1;
|
||||
};
|
||||
@@ -12,7 +12,7 @@ OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
OUT=$(addprefix $(OUTDIR)/,client.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "terminal_error.hpp"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,13 +19,13 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONPAGERAPI_HPP_
|
||||
#define REGIONPAGERAPI_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#define TORTUGA_REGION_PAGER_PSEUDO_INDEX "RegionPagerPseudoIndex"
|
||||
#define TORTUGA_REGION_PAGER_NAME "RegionPager"
|
||||
LUAMOD_API int openRegionPagerAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
class terminal_error: public std::runtime_error {
|
||||
public:
|
||||
explicit terminal_error(const std::string& str): runtime_error(str) {}
|
||||
explicit terminal_error(const char* cstr): runtime_error(cstr) {}
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,35 +19,28 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "character.hpp"
|
||||
#include "base_character.hpp"
|
||||
|
||||
void Character::Update(double delta) {
|
||||
if (motion.x && motion.y) {
|
||||
origin += motion * delta * CHARACTER_WALKING_MOD;
|
||||
}
|
||||
else if (motion != 0) {
|
||||
origin += motion * delta;
|
||||
}
|
||||
sprite.Update(delta);
|
||||
}
|
||||
//TODO: (3) remove this
|
||||
#include "config_utility.hpp"
|
||||
|
||||
void Character::DrawTo(SDL_Surface* const dest, int camX, int camY) {
|
||||
sprite.DrawTo(dest, origin.x - camX, origin.y - camY);
|
||||
}
|
||||
//-------------------------
|
||||
//graphics
|
||||
//-------------------------
|
||||
|
||||
void Character::CorrectSprite() {
|
||||
void BaseCharacter::CorrectSprite() {
|
||||
//NOTE: These must correspond to the sprite sheet in use
|
||||
if (motion.y > 0) {
|
||||
sprite.SetYIndex(0);
|
||||
sprite.SetIndexY(0);
|
||||
}
|
||||
else if (motion.y < 0) {
|
||||
sprite.SetYIndex(1);
|
||||
sprite.SetIndexY(1);
|
||||
}
|
||||
else if (motion.x > 0) {
|
||||
sprite.SetYIndex(3);
|
||||
sprite.SetIndexY(3);
|
||||
}
|
||||
else if (motion.x < 0) {
|
||||
sprite.SetYIndex(2);
|
||||
sprite.SetIndexY(2);
|
||||
}
|
||||
|
||||
//animation
|
||||
@@ -56,6 +49,36 @@ void Character::CorrectSprite() {
|
||||
}
|
||||
else {
|
||||
sprite.SetDelay(0);
|
||||
sprite.SetXIndex(0);
|
||||
sprite.SetIndexX(0);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//metadata
|
||||
//-------------------------
|
||||
|
||||
int BaseCharacter::SetOwner(int i) {
|
||||
return owner = i;
|
||||
}
|
||||
|
||||
int BaseCharacter::GetOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
std::string BaseCharacter::SetHandle(std::string s) {
|
||||
return handle = s;
|
||||
}
|
||||
|
||||
std::string BaseCharacter::GetHandle() const {
|
||||
return handle;
|
||||
}
|
||||
|
||||
std::string BaseCharacter::SetAvatar(SDL_Renderer* const renderer, std::string s) {
|
||||
avatar = s;
|
||||
sprite.Load(renderer, ConfigUtility::GetSingleton()["dir.sprites"] + avatar, CHARACTER_CELLS_X, CHARACTER_CELLS_Y);
|
||||
return avatar;
|
||||
}
|
||||
|
||||
std::string BaseCharacter::GetAvatar() const {
|
||||
return avatar;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//components
|
||||
#include "character_defines.hpp"
|
||||
#include "entity.hpp"
|
||||
|
||||
//std namespace
|
||||
#include <string>
|
||||
|
||||
class BaseCharacter: public Entity {
|
||||
public:
|
||||
BaseCharacter() = default;
|
||||
virtual ~BaseCharacter() = default;
|
||||
|
||||
//graphics
|
||||
void CorrectSprite();
|
||||
|
||||
//metadata
|
||||
int SetOwner(int i);
|
||||
int GetOwner();
|
||||
std::string SetHandle(std::string s);
|
||||
std::string GetHandle() const;
|
||||
std::string SetAvatar(SDL_Renderer* const, std::string s);
|
||||
std::string GetAvatar() const;
|
||||
|
||||
protected:
|
||||
//metadata
|
||||
int owner;
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "base_monster.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
|
||||
void BaseMonster::CorrectSprite() {
|
||||
//TODO: (9) BaseMonster::CorrectSprite()
|
||||
}
|
||||
|
||||
std::string BaseMonster::SetHandle(std::string s) {
|
||||
return handle = s;
|
||||
}
|
||||
|
||||
std::string BaseMonster::GetHandle() const {
|
||||
return handle;
|
||||
}
|
||||
|
||||
std::string BaseMonster::SetAvatar(SDL_Renderer* const renderer, std::string s) {
|
||||
avatar = s;
|
||||
sprite.Load(renderer, ConfigUtility::GetSingleton()["dir.sprites"] + avatar, 4, 1);
|
||||
return avatar;
|
||||
}
|
||||
|
||||
std::string BaseMonster::GetAvatar() const {
|
||||
return avatar;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,24 +19,24 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SIMPLERNG_HPP_
|
||||
#define SIMPLERNG_HPP_
|
||||
#pragma once
|
||||
|
||||
//a simple, stateless, random number generator
|
||||
class SimpleRNG {
|
||||
#include "entity.hpp"
|
||||
|
||||
class BaseMonster: public Entity {
|
||||
public:
|
||||
SimpleRNG() { SetSeed(8891.0); }
|
||||
SimpleRNG(double x) { SetSeed(x); }
|
||||
BaseMonster() = default;
|
||||
virtual ~BaseMonster() = default;
|
||||
|
||||
double SetSeed(double s) { return seed = s; }
|
||||
double GetSeed() { return seed; }
|
||||
void CorrectSprite();
|
||||
|
||||
double operator()(double x) {
|
||||
return (x + seed) * 11235.0 + 81321.0;
|
||||
};
|
||||
std::string SetHandle(std::string s);
|
||||
std::string GetHandle() const;
|
||||
std::string SetAvatar(SDL_Renderer* const, std::string s);
|
||||
std::string GetAvatar() const;
|
||||
|
||||
private:
|
||||
double seed;
|
||||
protected:
|
||||
//metadata
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "entity.hpp"
|
||||
|
||||
void Entity::Update() {
|
||||
origin += motion;
|
||||
sprite.Update(0.016);
|
||||
}
|
||||
|
||||
void Entity::DrawTo(SDL_Renderer* const renderer, int camX, int camY) {
|
||||
sprite.DrawTo(renderer, origin.x - camX, origin.y - camY);
|
||||
}
|
||||
|
||||
SpriteSheet* Entity::GetSprite() {
|
||||
return &sprite;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//accessors & mutators
|
||||
//-------------------------
|
||||
|
||||
Vector2 Entity::SetOrigin(Vector2 v) {
|
||||
return origin = v;
|
||||
}
|
||||
|
||||
Vector2 Entity::SetMotion(Vector2 v) {
|
||||
return motion = v;
|
||||
}
|
||||
|
||||
BoundingBox Entity::SetBounds(BoundingBox b) {
|
||||
return bounds = b;
|
||||
}
|
||||
|
||||
Vector2 Entity::GetOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
Vector2 Entity::GetMotion() {
|
||||
return motion;
|
||||
}
|
||||
|
||||
BoundingBox Entity::GetBounds() {
|
||||
return bounds;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "bounding_box.hpp"
|
||||
#include "sprite_sheet.hpp"
|
||||
#include "vector2.hpp"
|
||||
|
||||
//The base class for all objects in the world
|
||||
//TODO: (9) write a better hierarchy
|
||||
class Entity {
|
||||
public:
|
||||
virtual void Update();
|
||||
virtual void DrawTo(SDL_Renderer* const, int camX, int camY);
|
||||
|
||||
SpriteSheet* GetSprite();
|
||||
|
||||
//accessors & mutators
|
||||
Vector2 SetOrigin(Vector2 v);
|
||||
Vector2 SetMotion(Vector2 v);
|
||||
BoundingBox SetBounds(BoundingBox b);
|
||||
|
||||
Vector2 GetOrigin();
|
||||
Vector2 GetMotion();
|
||||
BoundingBox GetBounds();
|
||||
|
||||
protected:
|
||||
Entity() = default;
|
||||
virtual ~Entity() = default;
|
||||
|
||||
SpriteSheet sprite;
|
||||
Vector2 origin;
|
||||
Vector2 motion;
|
||||
BoundingBox bounds;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,23 +19,18 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "application.hpp"
|
||||
#include "local_character.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
try {
|
||||
Application app;
|
||||
app.Init(argc, argv);
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
bool LocalCharacter::ProcessCollisionGrid(std::list<BoundingBox> boxList) {
|
||||
for(auto& box : boxList) {
|
||||
if (box.CheckOverlap(origin + bounds)) {
|
||||
//TODO: (9) write a better collision system
|
||||
origin -= motion;
|
||||
motion = {0, 0};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,19 +19,21 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef UTILITY_HPP_
|
||||
#define UTILITY_HPP_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "base_character.hpp"
|
||||
#include "bounding_box.hpp"
|
||||
#include "vector2.hpp"
|
||||
|
||||
int snapToBase(int base, int x);
|
||||
double snapToBase(double base, double x);
|
||||
#include <list>
|
||||
|
||||
std::string truncatePath(std::string pathname);
|
||||
class LocalCharacter: public BaseCharacter {
|
||||
public:
|
||||
LocalCharacter() = default;
|
||||
virtual ~LocalCharacter() = default;
|
||||
|
||||
//fixing known bugs in g++
|
||||
std::string to_string_custom(int i);
|
||||
bool ProcessCollisionGrid(std::list<BoundingBox>);
|
||||
|
||||
int to_integer_custom(std::string);
|
||||
|
||||
#endif
|
||||
private:
|
||||
//NOTE: NO MEMBERS
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../../common/gameplay ../../common/graphics ../../common/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)/,client.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 $@ $<
|
||||
@@ -0,0 +1,32 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../client_utilities ../entities ../../common/gameplay ../../common/graphics ../../common/map ../../common/network ../../common/network/packet_types ../../common/ui ../../common/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)/,client.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 $@ $<
|
||||
@@ -0,0 +1,173 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//maps
|
||||
#include "region_pager_base.hpp"
|
||||
|
||||
//utilities
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "serial_packet.hpp"
|
||||
#include "config_utility.hpp"
|
||||
|
||||
//graphics
|
||||
#include "image.hpp"
|
||||
#include "button.hpp"
|
||||
#include "tile_sheet.hpp"
|
||||
#include "text_line.hpp"
|
||||
|
||||
//common
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
#include "base_monster.hpp"
|
||||
#include "local_character.hpp"
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_net.h"
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
//STL
|
||||
#include <map>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class World: public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
World(int* const argClientIndex, int* const argAccountIndex);
|
||||
~World();
|
||||
|
||||
void RenderFrame(SDL_Renderer* renderer) override;
|
||||
|
||||
private:
|
||||
//frame phases
|
||||
void FrameStart() override;
|
||||
void Update() override;
|
||||
void FrameEnd() override;
|
||||
|
||||
//input events
|
||||
void QuitEvent();
|
||||
void MouseMotion(SDL_MouseMotionEvent const& event) override;
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseWheel(SDL_MouseWheelEvent const& event) override;
|
||||
void KeyDown(SDL_KeyboardEvent const& event) override;
|
||||
void KeyUp(SDL_KeyboardEvent const& event) override;
|
||||
|
||||
//handle incoming traffic
|
||||
void HandlePacket(SerialPacket* const);
|
||||
|
||||
//heartbeat system
|
||||
void hPing(ServerPacket* const);
|
||||
void hPong(ServerPacket* const);
|
||||
|
||||
void CheckHeartBeat();
|
||||
|
||||
//basic connections
|
||||
void SendLogoutRequest();
|
||||
void SendDisconnectRequest();
|
||||
void SendAdminDisconnectForced();
|
||||
void SendAdminShutdownRequest();
|
||||
|
||||
void hLogoutResponse(ClientPacket* const);
|
||||
void hDisconnectResponse(ClientPacket* const);
|
||||
void hAdminDisconnectForced(ClientPacket* const);
|
||||
|
||||
//map management
|
||||
void SendRegionRequest(int roomIndex, int x, int y);
|
||||
void hRegionContent(RegionPacket* const);
|
||||
void UpdateMap();
|
||||
|
||||
//character management
|
||||
void hCharacterUpdate(CharacterPacket* const);
|
||||
void hCharacterCreate(CharacterPacket* const);
|
||||
void hCharacterDelete(CharacterPacket* const);
|
||||
void hQueryCharacterExists(CharacterPacket* const);
|
||||
void hQueryCharacterStats(CharacterPacket* const);
|
||||
void hQueryCharacterLocation(CharacterPacket* const);
|
||||
void hCharacterMovement(CharacterPacket* const);
|
||||
void hCharacterAttack(CharacterPacket* const);
|
||||
void hCharacterDamage(CharacterPacket* const);
|
||||
|
||||
//monster management
|
||||
void hMonsterCreate(MonsterPacket* const);
|
||||
void hMonsterDelete(MonsterPacket* const);
|
||||
void hQueryMonsterExists(MonsterPacket* const);
|
||||
void hQueryMonsterStats(MonsterPacket* const);
|
||||
void hQueryMonsterLocation(MonsterPacket* const);
|
||||
void hMonsterMovement(MonsterPacket* const);
|
||||
void hMonsterAttack(MonsterPacket* const);
|
||||
void hMonsterDamage(MonsterPacket* const);
|
||||
|
||||
//chat
|
||||
void hTextBroadcast(TextPacket* const);
|
||||
void hTextSpeech(TextPacket* const);
|
||||
void hTextWhisper(TextPacket* const);
|
||||
|
||||
//general gameplay
|
||||
void SendLocalCharacterMovement();
|
||||
std::list<BoundingBox> GenerateCollisionGrid(Entity*, int tileWidth, int tileHeight);
|
||||
|
||||
//indexes
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
int characterIndex = -1;
|
||||
int roomIndex = -1;
|
||||
|
||||
//graphics
|
||||
TileSheet tileSheet;
|
||||
|
||||
//map
|
||||
RegionPagerBase regionPager;
|
||||
|
||||
//UI
|
||||
Image buttonImage;
|
||||
TTF_Font* font = nullptr;
|
||||
Button disconnectButton;
|
||||
Button shutdownButton;
|
||||
FrameRate fps;
|
||||
TextLine fpsTextLine;
|
||||
|
||||
//the camera structure
|
||||
struct {
|
||||
int x = 0, y = 0;
|
||||
int width = 0, height = 0;
|
||||
int marginX = 0, marginY = 0;
|
||||
} camera;
|
||||
|
||||
//entities
|
||||
std::map<int, BaseCharacter> characterMap;
|
||||
std::map<int, BaseMonster> monsterMap;
|
||||
LocalCharacter* localCharacter = nullptr;
|
||||
|
||||
//heartbeat
|
||||
//TODO: (2) Heartbeat needs it's own utility
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
Clock::time_point lastBeat = Clock::now();
|
||||
int attemptedBeats = 0;
|
||||
|
||||
//ugly references; I hate this
|
||||
ConfigUtility& config = ConfigUtility::GetSingleton();
|
||||
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
|
||||
};
|
||||
@@ -0,0 +1,241 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//character management
|
||||
//-------------------------
|
||||
|
||||
//DOCS: preexisting characters will result in query responses
|
||||
//DOCS: new characters will result in create messages
|
||||
//DOCS: this client's character will exist in both (skipped)
|
||||
|
||||
void World::hCharacterUpdate(CharacterPacket* const argPacket) {
|
||||
//TODO: (1) Authentication
|
||||
//NOTE: applies to the local character too
|
||||
|
||||
//check that this character exists
|
||||
std::map<int, BaseCharacter>::iterator characterIt = characterMap.find(argPacket->characterIndex);
|
||||
if (characterIt != characterMap.end()) {
|
||||
//update the origin and motion, if there's a difference
|
||||
if (characterIt->second.GetOrigin() != argPacket->origin) {
|
||||
characterIt->second.SetOrigin(argPacket->origin);
|
||||
}
|
||||
if (characterIt->second.GetMotion() != argPacket->motion) {
|
||||
characterIt->second.SetMotion(argPacket->motion);
|
||||
characterIt->second.CorrectSprite(); //only correct the sprite if the motion changes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
||||
//prevent double message
|
||||
if (characterMap.find(argPacket->characterIndex) != characterMap.end()) {
|
||||
std::ostringstream msg;
|
||||
msg << "Double character creation event; ";
|
||||
msg << "Index: " << argPacket->characterIndex << "; ";
|
||||
msg << "Handle: " << argPacket->handle;
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//implicity create and retrieve the entity
|
||||
BaseCharacter* character = &characterMap[argPacket->characterIndex];
|
||||
|
||||
//fill the character's info
|
||||
character->SetHandle(argPacket->handle);
|
||||
character->SetAvatar(GetRenderer(), argPacket->avatar);
|
||||
character->SetOwner(argPacket->accountIndex);
|
||||
character->SetOrigin(argPacket->origin);
|
||||
character->SetMotion(argPacket->motion);
|
||||
character->SetBounds(argPacket->bounds);
|
||||
|
||||
character->CorrectSprite();
|
||||
|
||||
//check for this player's character
|
||||
if (character->GetOwner() == accountIndex) {
|
||||
localCharacter = static_cast<LocalCharacter*>(character);
|
||||
|
||||
//focus the camera on this character's sprite
|
||||
camera.marginX = (camera.width / 2 - localCharacter->GetSprite()->GetClipW() / 2);
|
||||
camera.marginY = (camera.height/ 2 - localCharacter->GetSprite()->GetClipH() / 2);
|
||||
|
||||
//focus on this character's info
|
||||
characterIndex = argPacket->characterIndex;
|
||||
roomIndex = argPacket->roomIndex;
|
||||
|
||||
//query the world state (room)
|
||||
CharacterPacket newPacket;
|
||||
memset(&newPacket, 0, MAX_PACKET_SIZE);
|
||||
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||
newPacket.roomIndex = roomIndex;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
newPacket.type = SerialPacketType::QUERY_MONSTER_EXISTS;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
}
|
||||
|
||||
//debug
|
||||
std::cout << "Character Create, total: " << characterMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void World::hCharacterDelete(CharacterPacket* const argPacket) {
|
||||
//ignore if this character doesn't exist
|
||||
std::map<int, BaseCharacter>::iterator characterIt = characterMap.find(argPacket->characterIndex);
|
||||
if (characterIt == characterMap.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//check for this player's character
|
||||
if ((*characterIt).second.GetOwner() == accountIndex) {
|
||||
localCharacter = nullptr;
|
||||
|
||||
//clear the camera
|
||||
camera.marginX = 0;
|
||||
camera.marginY = 0;
|
||||
|
||||
//clear the room
|
||||
roomIndex = -1;
|
||||
regionPager.UnloadAll();
|
||||
characterMap.clear();
|
||||
monsterMap.clear();
|
||||
}
|
||||
else {
|
||||
//remove this character
|
||||
characterMap.erase(characterIt);
|
||||
}
|
||||
|
||||
//debug
|
||||
std::cout << "Character Delete, total: " << characterMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void World::hQueryCharacterExists(CharacterPacket* const argPacket) {
|
||||
//prevent a double message about this player's character
|
||||
//TODO: why is this commented out?
|
||||
// if (argPacket->accountIndex == accountIndex) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
//ignore characters in a different room (sub-optimal)
|
||||
if (argPacket->roomIndex != roomIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
//implicitly construct the character if it doesn't exist
|
||||
BaseCharacter* character = &characterMap[argPacket->characterIndex];
|
||||
|
||||
//set/update the character's info
|
||||
character->SetOrigin(argPacket->origin);
|
||||
character->SetMotion(argPacket->motion);
|
||||
character->SetBounds({CHARACTER_BOUNDS_X, CHARACTER_BOUNDS_Y, CHARACTER_BOUNDS_WIDTH, CHARACTER_BOUNDS_HEIGHT});
|
||||
character->SetHandle(argPacket->handle);
|
||||
character->SetAvatar(GetRenderer(), argPacket->avatar);
|
||||
character->SetOwner(argPacket->accountIndex);
|
||||
character->CorrectSprite();
|
||||
|
||||
//debug
|
||||
std::cout << "Character Query, total: " << characterMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void World::hQueryCharacterStats(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) World::hQueryCharacterStats()
|
||||
}
|
||||
|
||||
void World::hQueryCharacterLocation(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) World::hQueryCharacterLocation()
|
||||
}
|
||||
|
||||
void World::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||
//TODO: (1) Authentication
|
||||
if (argPacket->characterIndex == characterIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
//check that this character exists
|
||||
std::map<int, BaseCharacter>::iterator characterIt = characterMap.find(argPacket->characterIndex);
|
||||
if (characterIt != characterMap.end()) {
|
||||
//set the origin and motion
|
||||
characterIt->second.SetOrigin(argPacket->origin);
|
||||
characterIt->second.SetMotion(argPacket->motion);
|
||||
characterIt->second.CorrectSprite();
|
||||
}
|
||||
}
|
||||
|
||||
void World::hCharacterAttack(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) World::hCharacterAttack()
|
||||
}
|
||||
|
||||
void World::hCharacterDamage(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) World::hCharacterDamage()
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//player movement & collision
|
||||
//-------------------------
|
||||
|
||||
void World::SendLocalCharacterMovement() {
|
||||
CharacterPacket newPacket;
|
||||
newPacket.type = SerialPacketType::CHARACTER_MOVEMENT;
|
||||
|
||||
newPacket.accountIndex = accountIndex;
|
||||
newPacket.characterIndex = characterIndex;
|
||||
newPacket.roomIndex = roomIndex;
|
||||
newPacket.origin = localCharacter->GetOrigin();
|
||||
newPacket.motion = localCharacter->GetMotion();
|
||||
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
}
|
||||
|
||||
std::list<BoundingBox> World::GenerateCollisionGrid(Entity* ptr, int tileWidth, int tileHeight) {
|
||||
//prepare for collisions
|
||||
BoundingBox wallBounds = {0, 0, tileWidth, tileHeight};
|
||||
std::list<BoundingBox> boxList;
|
||||
|
||||
//NOTE: for loops were too dense to work with, so I've just used while loops
|
||||
|
||||
//outer loop
|
||||
wallBounds.x = snapToBase((double)wallBounds.w, ptr->GetOrigin().x);
|
||||
while(wallBounds.x < (ptr->GetOrigin() + ptr->GetBounds()).x + ptr->GetBounds().w) {
|
||||
//inner loop
|
||||
wallBounds.y = snapToBase((double)wallBounds.h, ptr->GetOrigin().y);
|
||||
while(wallBounds.y < (ptr->GetOrigin() + ptr->GetBounds()).y + ptr->GetBounds().h) {
|
||||
//check to see if this tile is solid (non-existant tiles are always false)
|
||||
if (regionPager.GetSolid(wallBounds.x / wallBounds.w, wallBounds.y / wallBounds.h)) {
|
||||
//push onto the box set
|
||||
boxList.push_front(wallBounds);
|
||||
}
|
||||
|
||||
//increment
|
||||
wallBounds.y += wallBounds.h;
|
||||
}
|
||||
|
||||
//increment
|
||||
wallBounds.x += wallBounds.w;
|
||||
}
|
||||
|
||||
return std::move(boxList);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "world.hpp"
|
||||
|
||||
//-------------------------
|
||||
//chat
|
||||
//-------------------------
|
||||
|
||||
void World::hTextBroadcast(TextPacket* const argPacket) {
|
||||
//TODO: (9) World::hTextBroadcast()
|
||||
}
|
||||
|
||||
void World::hTextSpeech(TextPacket* const argPacket) {
|
||||
//TODO: (9) World::hTextSpeech()
|
||||
}
|
||||
|
||||
void World::hTextWhisper(TextPacket* const argPacket) {
|
||||
//TODO: (9) World::hTextWhisper()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
#include "ip_operators.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//heartbeat system
|
||||
//-------------------------
|
||||
|
||||
void World::hPing(ServerPacket* const argPacket) {
|
||||
ServerPacket newPacket;
|
||||
newPacket.type = SerialPacketType::PONG;
|
||||
network.SendTo(argPacket->srcAddress, &newPacket);
|
||||
}
|
||||
|
||||
void World::hPong(ServerPacket* const argPacket) {
|
||||
if (*network.GetIPAddress(Channels::SERVER) != argPacket->srcAddress) {
|
||||
throw(std::runtime_error("Heartbeat message received from an unknown source"));
|
||||
}
|
||||
attemptedBeats = 0;
|
||||
lastBeat = Clock::now();
|
||||
}
|
||||
|
||||
void World::CheckHeartBeat() {
|
||||
//check the connection (heartbeat)
|
||||
if (Clock::now() - lastBeat > std::chrono::seconds(3)) {
|
||||
if (attemptedBeats > 2) {
|
||||
//escape to the disconnect screen
|
||||
SendDisconnectRequest();
|
||||
SetSceneSignal(SceneSignal::DISCONNECTEDSCREEN);
|
||||
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server";
|
||||
}
|
||||
else {
|
||||
ServerPacket newPacket;
|
||||
newPacket.type = SerialPacketType::PING;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
|
||||
attemptedBeats++;
|
||||
lastBeat = Clock::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Connection control
|
||||
//-------------------------
|
||||
|
||||
void World::SendLogoutRequest() {
|
||||
ClientPacket newPacket;
|
||||
|
||||
//send a logout request
|
||||
newPacket.type = SerialPacketType::LOGOUT_REQUEST;
|
||||
newPacket.accountIndex = accountIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
}
|
||||
|
||||
void World::SendDisconnectRequest() {
|
||||
ClientPacket newPacket;
|
||||
|
||||
//send a disconnect request
|
||||
newPacket.type = SerialPacketType::DISCONNECT_REQUEST;
|
||||
newPacket.clientIndex = clientIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
}
|
||||
|
||||
void World::SendAdminDisconnectForced() {
|
||||
//TODO: (9) World::SendAdminDisconnectForced()
|
||||
}
|
||||
|
||||
void World::SendAdminShutdownRequest() {
|
||||
ClientPacket newPacket;
|
||||
|
||||
//send a shutdown request
|
||||
newPacket.type = SerialPacketType::ADMIN_SHUTDOWN_REQUEST;
|
||||
newPacket.accountIndex = accountIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
}
|
||||
|
||||
void World::hLogoutResponse(ClientPacket* const argPacket) {
|
||||
if (localCharacter) {
|
||||
characterMap.erase(characterIndex);
|
||||
localCharacter = nullptr;
|
||||
}
|
||||
|
||||
accountIndex = -1;
|
||||
characterIndex = -1;
|
||||
|
||||
//reset the camera
|
||||
camera.marginX = camera.marginY = 0;
|
||||
|
||||
//because, why not? I guess...
|
||||
SendDisconnectRequest();
|
||||
}
|
||||
|
||||
void World::hDisconnectResponse(ClientPacket* const argPacket) {
|
||||
hLogoutResponse(argPacket);//shortcut
|
||||
SetSceneSignal(SceneSignal::DISCONNECTEDSCREEN);
|
||||
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have successfully logged out";
|
||||
}
|
||||
|
||||
void World::hAdminDisconnectForced(ClientPacket* const argPacket) {
|
||||
hDisconnectResponse(argPacket);//shortcut
|
||||
SetSceneSignal(SceneSignal::DISCONNECTEDSCREEN);
|
||||
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have been forcibly disconnected by the server";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,443 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
#include "terminal_error.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
World::World(int* const argClientIndex, int* const argAccountIndex):
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex)
|
||||
{
|
||||
//setup the utility objects
|
||||
buttonImage.Load(GetRenderer(), config["dir.interface"] + "button_red.png");
|
||||
font = TTF_OpenFont(config["client.font"].c_str(), 12);
|
||||
|
||||
//check that the font loaded
|
||||
if (!font) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to load a font file; " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//setup the buttons
|
||||
disconnectButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
disconnectButton.SetText(GetRenderer(), font, "Disconnect", COLOR_BLUE);
|
||||
shutdownButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
shutdownButton.SetText(GetRenderer(), font, "Shutdown", COLOR_BLUE);
|
||||
|
||||
//set the button positions
|
||||
disconnectButton.SetX(50);
|
||||
disconnectButton.SetY(50);
|
||||
shutdownButton.SetX(50);
|
||||
shutdownButton.SetY(70);
|
||||
|
||||
//load the tilesheet
|
||||
//TODO: (2) Tile size and tile sheet should be loaded elsewhere
|
||||
tileSheet.Load(GetRenderer(), config["dir.tilesets"] + "overworld.png", 32, 32);
|
||||
|
||||
//Send the character data
|
||||
CharacterPacket newPacket;
|
||||
newPacket.type = SerialPacketType::CHARACTER_LOAD;
|
||||
strncpy(newPacket.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(newPacket.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
|
||||
newPacket.accountIndex = accountIndex;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
|
||||
//set the camera's values
|
||||
SDL_RenderGetLogicalSize(GetRenderer(), &camera.width, &camera.height);
|
||||
|
||||
//debug
|
||||
//
|
||||
}
|
||||
|
||||
World::~World() {
|
||||
//unload the local data
|
||||
TTF_CloseFont(font);
|
||||
characterMap.clear();
|
||||
monsterMap.clear();
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void World::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void World::Update() {
|
||||
//create and zero the buffer
|
||||
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
|
||||
memset(packetBuffer, 0, MAX_PACKET_SIZE);
|
||||
|
||||
try {
|
||||
//suck in and process all waiting packets
|
||||
while(network.Receive(packetBuffer)) {
|
||||
HandlePacket(packetBuffer);
|
||||
}
|
||||
}
|
||||
catch(terminal_error& e) {
|
||||
throw(e);
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
//free the buffer
|
||||
delete reinterpret_cast<char*>(packetBuffer);
|
||||
|
||||
//heartbeat system
|
||||
CheckHeartBeat();
|
||||
|
||||
//update all entities
|
||||
for (auto& it : characterMap) {
|
||||
it.second.Update();
|
||||
}
|
||||
for (auto& it : monsterMap) {
|
||||
it.second.Update();
|
||||
}
|
||||
|
||||
try {
|
||||
//update the map
|
||||
UpdateMap();
|
||||
}
|
||||
catch(terminal_error& e) {
|
||||
throw(e);
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
std::cerr << "UpdateMap Error: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
//skip the rest without a local character
|
||||
if (!localCharacter) {
|
||||
return;
|
||||
}
|
||||
|
||||
//get the collidable boxes
|
||||
std::list<BoundingBox> boxList = GenerateCollisionGrid(localCharacter, tileSheet.GetTileW(), tileSheet.GetTileH());
|
||||
|
||||
//process the collisions
|
||||
if (localCharacter->ProcessCollisionGrid(boxList)) {
|
||||
localCharacter->CorrectSprite();
|
||||
SendLocalCharacterMovement();
|
||||
}
|
||||
|
||||
//update the camera
|
||||
camera.x = localCharacter->GetOrigin().x - camera.marginX;
|
||||
camera.y = localCharacter->GetOrigin().y - camera.marginY;
|
||||
}
|
||||
|
||||
void World::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void World::RenderFrame(SDL_Renderer* renderer) {
|
||||
//draw the map
|
||||
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
||||
tileSheet.DrawRegionTo(renderer, &(*it), camera.x, camera.y);
|
||||
|
||||
//debugging
|
||||
// std::ostringstream msg;
|
||||
// msg << it->GetX() << ", " << it->GetY();
|
||||
// font.DrawStringTo(msg.str(), screen, it->GetX() * tileSheet.GetImage()->GetClipW() - camera.x, it->GetY() * tileSheet.GetImage()->GetClipH() - camera.y);
|
||||
}
|
||||
|
||||
//draw the entities
|
||||
for (auto& it : characterMap) {
|
||||
//BUG: #29 Characters (and other entities) are drawn out of order
|
||||
it.second.DrawTo(renderer, camera.x, camera.y);
|
||||
}
|
||||
for (auto& it : monsterMap) {
|
||||
it.second.DrawTo(renderer, camera.x, camera.y);
|
||||
}
|
||||
|
||||
//draw UI
|
||||
disconnectButton.DrawTo(renderer);
|
||||
shutdownButton.DrawTo(renderer);
|
||||
|
||||
//FPS
|
||||
fpsTextLine.DrawTo(renderer, 0, 0);
|
||||
int fpsRet = fps.Calculate();
|
||||
if (fpsRet != -1) {
|
||||
std::ostringstream msg;
|
||||
msg << "FPS: " << fpsRet;
|
||||
fpsTextLine.SetText(renderer, font, msg.str(), {255, 255, 255, 255});
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void World::QuitEvent() {
|
||||
//two-step logout
|
||||
SendDisconnectRequest();
|
||||
SetSceneSignal(SceneSignal::QUIT);
|
||||
}
|
||||
|
||||
void World::MouseMotion(SDL_MouseMotionEvent const& event) {
|
||||
disconnectButton.MouseMotion(event);
|
||||
shutdownButton.MouseMotion(event);
|
||||
}
|
||||
|
||||
void World::MouseButtonDown(SDL_MouseButtonEvent const& event) {
|
||||
disconnectButton.MouseButtonDown(event);
|
||||
shutdownButton.MouseButtonDown(event);
|
||||
}
|
||||
|
||||
void World::MouseButtonUp(SDL_MouseButtonEvent const& event) {
|
||||
if (disconnectButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SendLogoutRequest();
|
||||
}
|
||||
if (shutdownButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SendAdminShutdownRequest();
|
||||
}
|
||||
}
|
||||
|
||||
void World::MouseWheel(SDL_MouseWheelEvent const& event) {
|
||||
//
|
||||
}
|
||||
|
||||
void World::KeyDown(SDL_KeyboardEvent const& event) {
|
||||
//BUGFIX: SDL2 introduced key repeats, so I need to ignore it
|
||||
if (event.repeat) {
|
||||
return;
|
||||
}
|
||||
|
||||
//hotkeys
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
//TODO: (3) the escape key should actually control menus and stuff
|
||||
SendLogoutRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
//character movement
|
||||
if (!localCharacter) {
|
||||
return;
|
||||
}
|
||||
Vector2 motion = localCharacter->GetMotion();
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_w:
|
||||
motion.y -= CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_a:
|
||||
motion.x -= CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_s:
|
||||
motion.y += CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_d:
|
||||
motion.x += CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
default:
|
||||
//DOCS: prevents wrong keys screwing with character movement
|
||||
return;
|
||||
}
|
||||
//handle diagonals
|
||||
if (motion.x != 0 && motion.y != 0) {
|
||||
motion *= CHARACTER_WALKING_MOD;
|
||||
}
|
||||
//set the info
|
||||
localCharacter->SetMotion(motion);
|
||||
localCharacter->CorrectSprite();
|
||||
SendLocalCharacterMovement();
|
||||
}
|
||||
|
||||
void World::KeyUp(SDL_KeyboardEvent const& event) {
|
||||
//BUGFIX: SDL2 introduced key repeats, so I need to ignore it
|
||||
if (event.repeat) {
|
||||
return;
|
||||
}
|
||||
|
||||
//character movement
|
||||
if (!localCharacter) {
|
||||
return;
|
||||
}
|
||||
Vector2 motion = localCharacter->GetMotion();
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_w:
|
||||
motion.y = std::min(0.0, motion.y += CHARACTER_WALKING_SPEED);
|
||||
break;
|
||||
case SDLK_a:
|
||||
motion.x = std::min(0.0, motion.x += CHARACTER_WALKING_SPEED);
|
||||
break;
|
||||
case SDLK_s:
|
||||
motion.y = std::max(0.0, motion.y -= CHARACTER_WALKING_SPEED);
|
||||
break;
|
||||
case SDLK_d:
|
||||
motion.x = std::max(0.0, motion.x -= CHARACTER_WALKING_SPEED);
|
||||
break;
|
||||
default:
|
||||
//DOCS: prevents wrong keys screwing with character movement
|
||||
return;
|
||||
}
|
||||
//BUGFIX: reset cardinal direction speed on key release
|
||||
if (motion.x > 0) {
|
||||
motion.x = CHARACTER_WALKING_SPEED;
|
||||
}
|
||||
else if (motion.x < 0) {
|
||||
motion.x = -CHARACTER_WALKING_SPEED;
|
||||
}
|
||||
if (motion.y > 0) {
|
||||
motion.y = CHARACTER_WALKING_SPEED;
|
||||
}
|
||||
else if (motion.y < 0) {
|
||||
motion.y = -CHARACTER_WALKING_SPEED;
|
||||
}
|
||||
//handle diagonals
|
||||
if (motion.x != 0 && motion.y != 0) {
|
||||
motion *= CHARACTER_WALKING_MOD;
|
||||
}
|
||||
//set the info
|
||||
localCharacter->SetMotion(motion);
|
||||
localCharacter->CorrectSprite();
|
||||
SendLocalCharacterMovement();
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Direct incoming traffic
|
||||
//-------------------------
|
||||
|
||||
void World::HandlePacket(SerialPacket* const argPacket) {
|
||||
switch(argPacket->type) {
|
||||
//heartbeat system
|
||||
case SerialPacketType::PING:
|
||||
hPing(static_cast<ServerPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::PONG:
|
||||
hPong(static_cast<ServerPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//game server connections
|
||||
case SerialPacketType::LOGOUT_RESPONSE:
|
||||
hLogoutResponse(static_cast<ClientPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::DISCONNECT_RESPONSE:
|
||||
hDisconnectResponse(static_cast<ClientPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::ADMIN_DISCONNECT_FORCED:
|
||||
hAdminDisconnectForced(static_cast<ClientPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//map management
|
||||
case SerialPacketType::REGION_CONTENT:
|
||||
hRegionContent(static_cast<RegionPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//character management
|
||||
case SerialPacketType::CHARACTER_UPDATE:
|
||||
hCharacterUpdate(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_CREATE:
|
||||
hCharacterCreate(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_DELETE:
|
||||
hCharacterDelete(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::QUERY_CHARACTER_EXISTS:
|
||||
hQueryCharacterExists(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::QUERY_CHARACTER_STATS:
|
||||
hQueryCharacterStats(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::QUERY_CHARACTER_LOCATION:
|
||||
hQueryCharacterLocation(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_MOVEMENT:
|
||||
hCharacterMovement(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_ATTACK:
|
||||
hCharacterAttack(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_DAMAGE:
|
||||
hCharacterDamage(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//monster management
|
||||
case SerialPacketType::MONSTER_CREATE:
|
||||
hMonsterCreate(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::MONSTER_DELETE:
|
||||
hMonsterDelete(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::QUERY_MONSTER_EXISTS:
|
||||
hQueryMonsterExists(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::QUERY_MONSTER_STATS:
|
||||
hQueryMonsterStats(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::QUERY_MONSTER_LOCATION:
|
||||
hQueryMonsterLocation(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::MONSTER_MOVEMENT:
|
||||
hMonsterMovement(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::MONSTER_ATTACK:
|
||||
hMonsterAttack(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::MONSTER_DAMAGE:
|
||||
hMonsterDamage(static_cast<MonsterPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//chat
|
||||
case SerialPacketType::TEXT_BROADCAST:
|
||||
hTextBroadcast(static_cast<TextPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::TEXT_SPEECH:
|
||||
hTextSpeech(static_cast<TextPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::TEXT_WHISPER:
|
||||
hTextWhisper(static_cast<TextPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//general rejection messages
|
||||
case SerialPacketType::REGION_REJECTION:
|
||||
case SerialPacketType::CHARACTER_REJECTION:
|
||||
case SerialPacketType::QUERY_REJECTION:
|
||||
throw(terminal_error(static_cast<TextPacket*>(argPacket)->text));
|
||||
break;
|
||||
case SerialPacketType::SHUTDOWN_REJECTION:
|
||||
throw(std::runtime_error(static_cast<TextPacket*>(argPacket)->text));
|
||||
break;
|
||||
|
||||
//errors
|
||||
default: {
|
||||
std::ostringstream msg;
|
||||
msg << "Unknown SerialPacketType encountered in World: " << static_cast<int>(argPacket->type);
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
//-------------------------
|
||||
//static functions
|
||||
//-------------------------
|
||||
|
||||
//TODO: (3) proper checksum
|
||||
static int regionChecksum(Region* const region) {
|
||||
int sum = 0;
|
||||
for(int i = 0; i < REGION_WIDTH; i++) {
|
||||
for (int j = 0; j < REGION_HEIGHT; j++) {
|
||||
for (int k = 0; k < REGION_DEPTH; k++) {
|
||||
sum |= region->GetTile(i, j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//map management
|
||||
//-------------------------
|
||||
|
||||
void World::SendRegionRequest(int roomIndex, int x, int y) {
|
||||
RegionPacket packet;
|
||||
|
||||
//pack the region's data
|
||||
packet.type = SerialPacketType::REGION_REQUEST;
|
||||
packet.roomIndex = roomIndex;
|
||||
packet.x = x;
|
||||
packet.y = y;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void World::hRegionContent(RegionPacket* const argPacket) {
|
||||
//checksum
|
||||
if (regionChecksum(argPacket->region) == 0) {
|
||||
std::ostringstream msg;
|
||||
msg << "Received region checksum failed: " << argPacket->x << ", " << argPacket->y;
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//replace existing regions
|
||||
regionPager.UnloadIf([&](Region const& region) -> bool {
|
||||
return region.GetX() == argPacket->x && region.GetY() == argPacket->y;
|
||||
});
|
||||
regionPager.PushRegion(argPacket->region);
|
||||
|
||||
//clean up after the serial code
|
||||
delete argPacket->region;
|
||||
argPacket->region = nullptr;
|
||||
}
|
||||
|
||||
void World::UpdateMap() {
|
||||
if (roomIndex == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
//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;
|
||||
|
||||
int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT;
|
||||
int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT;
|
||||
|
||||
//prune distant regions
|
||||
regionPager.GetContainer()->remove_if([&](Region const& region) -> bool {
|
||||
return region.GetX() < xStart || region.GetX() > xEnd || region.GetY() < yStart || region.GetY() > yEnd;
|
||||
});
|
||||
|
||||
//request empty regions within this zone
|
||||
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
|
||||
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
|
||||
Region* region = regionPager.FindRegion(i, j);
|
||||
if (!region) {
|
||||
//request absent region
|
||||
SendRegionRequest(roomIndex, i, j);
|
||||
}
|
||||
else if (regionChecksum(region) == 0) {
|
||||
//checksum failed
|
||||
regionPager.UnloadIf([region](Region const& ref) -> bool {
|
||||
//remove the erroneous region
|
||||
return region == &ref;
|
||||
});
|
||||
SendRegionRequest(roomIndex, i, j);
|
||||
std::ostringstream msg;
|
||||
msg << "Existing region checksum failed: " << roomIndex << ", " << i << ", " << j;
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//monster management
|
||||
//-------------------------
|
||||
|
||||
void World::hMonsterCreate(MonsterPacket* const argPacket) {
|
||||
//check for logic errors
|
||||
if (monsterMap.find(argPacket->monsterIndex) != monsterMap.end()) {
|
||||
std::ostringstream msg;
|
||||
msg << "Double monster creation event; ";
|
||||
msg << "Index: " << argPacket->monsterIndex << "; ";
|
||||
msg << "Handle: " << argPacket->handle;
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//ignore monsters from other rooms
|
||||
if (roomIndex != argPacket->roomIndex) {
|
||||
//temporary error checking
|
||||
std::ostringstream msg;
|
||||
msg << "Monster from the wrong room received: ";
|
||||
msg << "monsterIndex: " << argPacket->monsterIndex << ", roomIndex: " << argPacket->roomIndex;
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//implicitly create the element
|
||||
BaseMonster* monster = &monsterMap[argPacket->monsterIndex];
|
||||
|
||||
//fill the monster's info
|
||||
monster->SetHandle(argPacket->handle);
|
||||
monster->SetAvatar(GetRenderer(), argPacket->avatar);
|
||||
monster->SetBounds(argPacket->bounds);
|
||||
monster->SetOrigin(argPacket->origin);
|
||||
monster->SetMotion(argPacket->motion);
|
||||
|
||||
//debug
|
||||
std::cout << "Monster Create, total: " << monsterMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void World::hMonsterDelete(MonsterPacket* const argPacket) {
|
||||
//ignore if this monster doesn't exist
|
||||
std::map<int, BaseMonster>::iterator monsterIt = monsterMap.find(argPacket->monsterIndex);
|
||||
if (monsterIt == monsterMap.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove this monster
|
||||
monsterMap.erase(monsterIt);
|
||||
|
||||
//debug
|
||||
std::cout << "Monster Delete, total: " << monsterMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void World::hQueryMonsterExists(MonsterPacket* const argPacket) {
|
||||
//ignore monsters in a different room (sub-optimal)
|
||||
if (argPacket->roomIndex != roomIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
//implicitly create the element
|
||||
BaseMonster* monster = &monsterMap[argPacket->monsterIndex];
|
||||
|
||||
//fill the monster's info
|
||||
monster->SetHandle(argPacket->handle);
|
||||
monster->SetAvatar(GetRenderer(), argPacket->avatar);
|
||||
monster->SetBounds(argPacket->bounds);
|
||||
monster->SetOrigin(argPacket->origin);
|
||||
monster->SetMotion(argPacket->motion);
|
||||
|
||||
//debug
|
||||
std::cout << "Monster Query, total: " << monsterMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void World::hQueryMonsterStats(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) World::hQueryMonsterStats()
|
||||
}
|
||||
|
||||
void World::hQueryMonsterLocation(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) World::hQueryMonsterLocation()
|
||||
}
|
||||
|
||||
void World::hMonsterMovement(MonsterPacket* const argPacket) {
|
||||
//ignore if this monster doesn't exist
|
||||
std::map<int, BaseMonster>::iterator monsterIt = monsterMap.find(argPacket->monsterIndex);
|
||||
if (monsterIt == monsterMap.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
monsterIt->second.SetOrigin(argPacket->origin);
|
||||
monsterIt->second.SetOrigin(argPacket->motion);
|
||||
}
|
||||
|
||||
void World::hMonsterAttack(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) World::hMonsterAttack()
|
||||
}
|
||||
|
||||
void World::hMonsterDamage(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) World::hMonsterDamage()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,45 +19,41 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "utility.hpp"
|
||||
#include "client_application.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
//singletons
|
||||
#include "config_utility.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
int snapToBase(int base, int x) {
|
||||
//snap to a grid
|
||||
if (x < 0) {
|
||||
++x;
|
||||
return x / base * base - base;
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
try {
|
||||
//create the singletons
|
||||
ConfigUtility::CreateSingleton();
|
||||
UDPNetworkUtility::CreateSingleton();
|
||||
|
||||
//call the client's routines
|
||||
ClientApplication::CreateSingleton();
|
||||
ClientApplication& app = ClientApplication::GetSingleton();
|
||||
|
||||
app.Init(argc, argv);
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
|
||||
//control the position of the app's destructor
|
||||
ClientApplication::DeleteSingleton();
|
||||
|
||||
//delete the singletons
|
||||
ConfigUtility::DeleteSingleton();
|
||||
UDPNetworkUtility::DeleteSingleton();
|
||||
}
|
||||
return x / base * base;
|
||||
}
|
||||
|
||||
double snapToBase(double base, double x) {
|
||||
return floor(x / base) * base;
|
||||
}
|
||||
|
||||
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;
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include directories
|
||||
INCLUDES+=. client_utilities entities gameplay_scenes menu_scenes ../common/debugging ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet_types ../common/ui ../common/utilities
|
||||
|
||||
#libraries
|
||||
#the order of the $(LIBS) is important, at least for MinGW
|
||||
LIBS+=client.a ../common/libcommon.a -lSDL2_net
|
||||
ifeq ($(OS),Windows_NT)
|
||||
LIBS+=-lwsock32 -liphlpapi -lmingw32
|
||||
endif
|
||||
LIBS+=-lSDL2main -lSDL2 -lSDL2_image -lSDL2_ttf
|
||||
|
||||
#flags
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
ifeq ($(shell uname), Linux)
|
||||
#read data about the current install
|
||||
CXXFLAGS+=$(shell sdl-config --cflags --static-libs)
|
||||
endif
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../out
|
||||
OUT=$(addprefix $(OUTDIR)/,client)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
$(MAKE) -C client_utilities
|
||||
$(MAKE) -C entities
|
||||
$(MAKE) -C gameplay_scenes
|
||||
$(MAKE) -C menu_scenes
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
$(RM) *.o *.a *.exe
|
||||
else ifeq ($(shell uname), Linux)
|
||||
find . -type f -name *.o -exec rm -f -r -v {} \;
|
||||
find . -type f -name *.a -exec rm -f -r -v {} \;
|
||||
rm -f -v out/client out/server
|
||||
endif
|
||||
|
||||
rebuild: clean all
|
||||
@@ -0,0 +1,130 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "disconnected_screen.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
#include "config_utility.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
DisconnectedScreen::DisconnectedScreen() {
|
||||
ConfigUtility& config = ConfigUtility::GetSingleton();
|
||||
|
||||
//setup the utility objects
|
||||
//TODO: (1) resource tool, to prevent reloading like this
|
||||
image.Load(GetRenderer(), config["dir.interface"] + "button_red.png");
|
||||
font = TTF_OpenFont(config["client.font"].c_str(), 12);
|
||||
|
||||
//check that the font loaded
|
||||
if (!font) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to load a font file; " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//setup the button
|
||||
backButton.SetBackgroundTexture(GetRenderer(), image.GetTexture());
|
||||
backButton.SetText(GetRenderer(), font, "Back", COLOR_BLUE);
|
||||
|
||||
//set the button positions
|
||||
backButton.SetX(50);
|
||||
backButton.SetY(50);
|
||||
|
||||
//set the disconnection message text
|
||||
textLine.SetText(GetRenderer(), font, config["client.disconnectMessage"], {255, 255, 255, 255});
|
||||
|
||||
//full reset
|
||||
UDPNetworkUtility::GetSingleton().Unbind(Channels::SERVER);
|
||||
|
||||
//auto return
|
||||
startTick = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
DisconnectedScreen::~DisconnectedScreen() {
|
||||
TTF_CloseFont(font);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void DisconnectedScreen::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void DisconnectedScreen::Update() {
|
||||
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(10)) {
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
}
|
||||
|
||||
//Eat incoming packets
|
||||
while(UDPNetworkUtility::GetSingleton().Receive());
|
||||
}
|
||||
|
||||
void DisconnectedScreen::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void DisconnectedScreen::RenderFrame(SDL_Renderer* renderer) {
|
||||
backButton.DrawTo(renderer);
|
||||
textLine.DrawTo(renderer, 50, 30);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void DisconnectedScreen::MouseMotion(SDL_MouseMotionEvent const& event) {
|
||||
backButton.MouseMotion(event);
|
||||
}
|
||||
|
||||
void DisconnectedScreen::MouseButtonDown(SDL_MouseButtonEvent const& event) {
|
||||
backButton.MouseButtonDown(event);
|
||||
}
|
||||
|
||||
void DisconnectedScreen::MouseButtonUp(SDL_MouseButtonEvent const& event) {
|
||||
if (backButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectedScreen::MouseWheel(SDL_MouseWheelEvent const& event) {
|
||||
//
|
||||
}
|
||||
|
||||
void DisconnectedScreen::KeyDown(SDL_KeyboardEvent const& event) {
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectedScreen::KeyUp(SDL_KeyboardEvent const& event) {
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base_scene.hpp"
|
||||
#include "button.hpp"
|
||||
#include "image.hpp"
|
||||
#include "text_line.hpp"
|
||||
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class DisconnectedScreen : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
DisconnectedScreen();
|
||||
~DisconnectedScreen();
|
||||
|
||||
void RenderFrame(SDL_Renderer* renderer) override;
|
||||
|
||||
protected:
|
||||
//frame phases
|
||||
void FrameStart() override;
|
||||
void Update() override;
|
||||
void FrameEnd() override;
|
||||
|
||||
//input events
|
||||
void MouseMotion(SDL_MouseMotionEvent const& event) override;
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseWheel(SDL_MouseWheelEvent const& event) override;
|
||||
void KeyDown(SDL_KeyboardEvent const& event) override;
|
||||
void KeyUp(SDL_KeyboardEvent const& event) override;
|
||||
|
||||
//graphics
|
||||
Image image;
|
||||
TTF_Font* font = nullptr;
|
||||
Button backButton;
|
||||
TextLine textLine;
|
||||
|
||||
//auto return
|
||||
std::chrono::steady_clock::time_point startTick;
|
||||
};
|
||||
@@ -0,0 +1,314 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "lobby_menu.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex):
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex)
|
||||
{
|
||||
//preemptive reset
|
||||
clientIndex = -1;
|
||||
accountIndex = -1;
|
||||
|
||||
//setup the utility objects
|
||||
buttonImage.Load(GetRenderer(), config["dir.interface"] + "button_red.png");
|
||||
font = TTF_OpenFont(config["client.font"].c_str(), 12);
|
||||
|
||||
//check that the font loaded
|
||||
if (!font) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to load a font file; " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//setup the buttons
|
||||
searchButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
searchButton.SetText(GetRenderer(), font, "Search", COLOR_BLUE);
|
||||
joinButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
joinButton.SetText(GetRenderer(), font, "Join", COLOR_BLUE);
|
||||
backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
backButton.SetText(GetRenderer(), font, "Back", COLOR_BLUE);
|
||||
|
||||
//set the button positions (assumed)
|
||||
searchButton.SetX(50);
|
||||
searchButton.SetY(50);
|
||||
joinButton.SetX(50);
|
||||
joinButton.SetY(70);
|
||||
backButton.SetX(50);
|
||||
backButton.SetY(90);
|
||||
|
||||
//pseudo-list selection
|
||||
boundingBox = {300, 50, 200, 12};
|
||||
|
||||
//hacked together a highlight box
|
||||
highlightImage.Create(GetRenderer(), 300, 12, {49, 150, 5, 255});
|
||||
|
||||
//Eat incoming packets
|
||||
while(network.Receive());
|
||||
|
||||
//Initial broadcast
|
||||
SendBroadcastRequest();
|
||||
}
|
||||
|
||||
LobbyMenu::~LobbyMenu() {
|
||||
TTF_CloseFont(font);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void LobbyMenu::Update() {
|
||||
//suck in and process all waiting packets
|
||||
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
|
||||
while(network.Receive(packetBuffer)) {
|
||||
HandlePacket(packetBuffer);
|
||||
}
|
||||
delete reinterpret_cast<char*>(packetBuffer);
|
||||
}
|
||||
|
||||
void LobbyMenu::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void LobbyMenu::RenderFrame(SDL_Renderer* renderer) {
|
||||
//TODO: (2) I need a proper UI system for the entire client and the editor
|
||||
|
||||
//UI
|
||||
searchButton.DrawTo(renderer);
|
||||
joinButton.DrawTo(renderer);
|
||||
backButton.DrawTo(renderer);
|
||||
|
||||
//TODO: (3) draw headers for the server list
|
||||
//TODO: (3) ping/delay displayed in the server list
|
||||
for (int i = 0; i < serverVector.size(); i++) {
|
||||
//draw the selected server's highlight
|
||||
if (selection == &serverVector[i]) {
|
||||
highlightImage.DrawTo(renderer, boundingBox.x, boundingBox.y + boundingBox.h * i);
|
||||
}
|
||||
|
||||
//draw the server's info
|
||||
serverVector[i].nameImage.DrawTo(renderer, boundingBox.x, boundingBox.y + boundingBox.h * i);
|
||||
serverVector[i].playerCountImage.DrawTo(renderer, boundingBox.x+300, boundingBox.y + boundingBox.h * i);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::MouseMotion(SDL_MouseMotionEvent const& event) {
|
||||
searchButton.MouseMotion(event);
|
||||
joinButton.MouseMotion(event);
|
||||
backButton.MouseMotion(event);
|
||||
}
|
||||
|
||||
void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& event) {
|
||||
searchButton.MouseButtonDown(event);
|
||||
joinButton.MouseButtonDown(event);
|
||||
backButton.MouseButtonDown(event);
|
||||
}
|
||||
|
||||
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& event) {
|
||||
if (searchButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SendBroadcastRequest();
|
||||
}
|
||||
if (joinButton.MouseButtonUp(event) == Button::State::RELEASED && selection && selection->compatible) {
|
||||
SendJoinRequest();
|
||||
}
|
||||
if (backButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
}
|
||||
|
||||
//has the user selected a server on the list?
|
||||
BoundingBox tmpBox = boundingBox;
|
||||
tmpBox.h *= serverVector.size(); //within the list bounds
|
||||
if (tmpBox.CheckOverlap({event.x, event.y})) {
|
||||
//NOTE: this memory trick requires a vector
|
||||
selection = &serverVector[(event.y - boundingBox.y)/boundingBox.h];
|
||||
}
|
||||
else {
|
||||
selection = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyMenu::MouseWheel(SDL_MouseWheelEvent const& event) {
|
||||
//
|
||||
}
|
||||
|
||||
void LobbyMenu::KeyDown(SDL_KeyboardEvent const& event) {
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyMenu::KeyUp(SDL_KeyboardEvent const& event) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::HandlePacket(SerialPacket* const argPacket) {
|
||||
switch(argPacket->type) {
|
||||
//responses
|
||||
case SerialPacketType::BROADCAST_RESPONSE:
|
||||
HandleBroadcastResponse(static_cast<ServerPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::JOIN_RESPONSE:
|
||||
HandleJoinResponse(static_cast<ClientPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::LOGIN_RESPONSE:
|
||||
HandleLoginResponse(static_cast<ClientPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//rejections
|
||||
case SerialPacketType::JOIN_REJECTION:
|
||||
HandleJoinRejection(static_cast<TextPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::LOGIN_REJECTION:
|
||||
HandleLoginRejection(static_cast<TextPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
//handle errors
|
||||
default: {
|
||||
std::ostringstream msg;
|
||||
msg << "Unknown SerialPacketType encountered in LobbyMenu: " << static_cast<int>(argPacket->type);
|
||||
throw(std::runtime_error( msg.str() ));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyMenu::HandleBroadcastResponse(ServerPacket* const argPacket) {
|
||||
//extract the data
|
||||
ServerInfo newServer;
|
||||
|
||||
newServer.address = argPacket->srcAddress;
|
||||
newServer.name = argPacket->name;
|
||||
newServer.playerCount = argPacket->playerCount;
|
||||
newServer.version = argPacket->version;
|
||||
newServer.compatible = newServer.version == NETWORK_VERSION;
|
||||
|
||||
//push
|
||||
serverVector.push_back(newServer);
|
||||
|
||||
//BUGFIX: since TextLine lacks the memory management of Image, I'll wait until after the line is in the vector to handle these
|
||||
|
||||
//fancy colors
|
||||
SDL_Color color;
|
||||
if (newServer.compatible) {
|
||||
color = {255, 255, 255, 255};
|
||||
}
|
||||
else {
|
||||
color = {255, 0, 0, 255};
|
||||
}
|
||||
|
||||
//fancy itoa
|
||||
auto itoa_base10 = [](int i) -> std::string {
|
||||
char str[20];
|
||||
sprintf(str, "%d", i);
|
||||
return std::string(str);
|
||||
};
|
||||
|
||||
//text graphics
|
||||
serverVector.back().nameImage.SetText(GetRenderer(), font, newServer.name, color);
|
||||
serverVector.back().playerCountImage.SetText(GetRenderer(), font, itoa_base10(newServer.playerCount), color);
|
||||
}
|
||||
|
||||
void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) {
|
||||
//save the server's data
|
||||
clientIndex = argPacket->clientIndex;
|
||||
network.Bind(argPacket->srcAddress, Channels::SERVER);
|
||||
|
||||
//request login data
|
||||
SendLoginRequest();
|
||||
}
|
||||
|
||||
void LobbyMenu::HandleLoginResponse(ClientPacket* const argPacket) {
|
||||
if (argPacket->clientIndex != clientIndex) {
|
||||
throw(std::runtime_error("Client index invalid during login"));
|
||||
}
|
||||
accountIndex = argPacket->accountIndex;
|
||||
SetSceneSignal(SceneSignal::WORLD);
|
||||
}
|
||||
|
||||
void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) {
|
||||
//TODO: (9) LobbyMenu::HandleJoinRejection()
|
||||
}
|
||||
|
||||
void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) {
|
||||
//TODO: (9) LobbyMenu::HandleLoginRejection
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//server control
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::SendBroadcastRequest() {
|
||||
//broadcast to the network, or a specific server
|
||||
ClientPacket packet;
|
||||
packet.type = SerialPacketType::BROADCAST_REQUEST;
|
||||
network.SendTo(config["server.host"].c_str(), config.Int("server.port"), &packet);
|
||||
|
||||
//reset the server list
|
||||
serverVector.clear();
|
||||
selection = nullptr;
|
||||
}
|
||||
|
||||
void LobbyMenu::SendJoinRequest() {
|
||||
//pack the packet
|
||||
ClientPacket packet;
|
||||
packet.type = SerialPacketType::JOIN_REQUEST;
|
||||
|
||||
//join the selected server
|
||||
network.SendTo(selection->address, &packet);
|
||||
selection = nullptr;
|
||||
}
|
||||
|
||||
void LobbyMenu::SendLoginRequest() {
|
||||
//NOTE: high cohesion
|
||||
//TODO: (9) have a separate login screen
|
||||
ClientPacket packet;
|
||||
packet.type = SerialPacketType::LOGIN_REQUEST;
|
||||
packet.clientIndex = clientIndex;
|
||||
strncpy(packet.username, config["client.username"].c_str(), PACKET_STRING_SIZE+1);
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//graphics & ui
|
||||
#include "image.hpp"
|
||||
#include "button.hpp"
|
||||
#include "bounding_box.hpp"
|
||||
#include "text_line.hpp"
|
||||
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
//utilities
|
||||
#include "config_utility.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "serial_packet.hpp"
|
||||
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
|
||||
//STL
|
||||
#include <vector>
|
||||
|
||||
class LobbyMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
LobbyMenu(int* const argClientIndex, int* const argAccountIndex);
|
||||
~LobbyMenu();
|
||||
|
||||
void RenderFrame(SDL_Renderer* renderer) override;
|
||||
|
||||
protected:
|
||||
//frame phases
|
||||
void FrameStart() override;
|
||||
void Update() override;
|
||||
void FrameEnd() override;
|
||||
|
||||
//input events
|
||||
void MouseMotion(SDL_MouseMotionEvent const& event) override;
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseWheel(SDL_MouseWheelEvent const& event) override;
|
||||
void KeyDown(SDL_KeyboardEvent const& event) override;
|
||||
void KeyUp(SDL_KeyboardEvent const& event) override;
|
||||
|
||||
//Network handlers
|
||||
void HandlePacket(SerialPacket* const);
|
||||
void HandleBroadcastResponse(ServerPacket* const);
|
||||
void HandleJoinResponse(ClientPacket* const);
|
||||
void HandleLoginResponse(ClientPacket* const);
|
||||
void HandleJoinRejection(TextPacket* const);
|
||||
void HandleLoginRejection(TextPacket* const);
|
||||
|
||||
//server control
|
||||
void SendBroadcastRequest();
|
||||
void SendJoinRequest();
|
||||
void SendLoginRequest();
|
||||
|
||||
//shared parameters
|
||||
ConfigUtility& config = ConfigUtility::GetSingleton();
|
||||
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
|
||||
//define the list object
|
||||
struct ServerInfo {
|
||||
//graphics
|
||||
TextLine nameImage;
|
||||
TextLine playerCountImage;
|
||||
|
||||
//networking
|
||||
IPaddress address;
|
||||
std::string name;
|
||||
int playerCount;
|
||||
int version;
|
||||
bool compatible;
|
||||
};
|
||||
|
||||
//members
|
||||
Image buttonImage;
|
||||
Image highlightImage;
|
||||
TTF_Font* font = nullptr;
|
||||
Button searchButton;
|
||||
Button joinButton;
|
||||
Button backButton;
|
||||
|
||||
std::vector<ServerInfo> serverVector;
|
||||
ServerInfo* selection = nullptr;
|
||||
|
||||
BoundingBox boundingBox;
|
||||
};
|
||||
@@ -0,0 +1,146 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "main_menu.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
MainMenu::MainMenu() {
|
||||
ConfigUtility& config = ConfigUtility::GetSingleton();
|
||||
|
||||
//setup the utility objects
|
||||
buttonImage.Load(GetRenderer(), config["dir.interface"] + "button_red.png");
|
||||
font = TTF_OpenFont(config["client.font"].c_str(), 12);
|
||||
|
||||
//check that the font loaded
|
||||
if (!font) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to load a font file; " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//setup the buttons
|
||||
startButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
startButton.SetText(GetRenderer(), font, "Start", COLOR_BLUE);
|
||||
optionsButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
optionsButton.SetText(GetRenderer(), font, "Options", COLOR_BLUE);
|
||||
quitButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
quitButton.SetText(GetRenderer(), font, "Quit", COLOR_BLUE);
|
||||
|
||||
//set the button positions
|
||||
startButton.SetX(50);
|
||||
startButton.SetY(50 + 20 * 0);
|
||||
optionsButton.SetX(50);
|
||||
optionsButton.SetY(50 + 20 * 1);
|
||||
quitButton.SetX(50);
|
||||
quitButton.SetY(50 + 20 * 2);
|
||||
|
||||
//text box
|
||||
textBox.PushLine(GetRenderer(), font, "Thanks for playing!", {255, 255, 255, 255});
|
||||
textBox.PushLine(GetRenderer(), font, "You can get the latest version at: ", {255, 255, 255, 255});
|
||||
textBox.PushLine(GetRenderer(), font, "krgamestudios.com", {255, 255, 255, 255}); //TODO: (9) click to open the website/update
|
||||
|
||||
//debug
|
||||
//
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu() {
|
||||
TTF_CloseFont(font);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void MainMenu::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::Update() {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::RenderFrame(SDL_Renderer* renderer) {
|
||||
startButton.DrawTo(renderer);
|
||||
optionsButton.DrawTo(renderer);
|
||||
quitButton.DrawTo(renderer);
|
||||
|
||||
int h = -1;
|
||||
SDL_RenderGetLogicalSize(GetRenderer(), nullptr, &h);
|
||||
|
||||
textBox.DrawTo(renderer, 50, h-50, -12);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void MainMenu::MouseMotion(SDL_MouseMotionEvent const& event) {
|
||||
startButton.MouseMotion(event);
|
||||
optionsButton.MouseMotion(event);
|
||||
quitButton.MouseMotion(event);
|
||||
}
|
||||
|
||||
void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& event) {
|
||||
startButton.MouseButtonDown(event);
|
||||
optionsButton.MouseButtonDown(event);
|
||||
quitButton.MouseButtonDown(event);
|
||||
}
|
||||
|
||||
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& event) {
|
||||
//TODO: (2) Buttons should only register as "selected" when the left button is used
|
||||
if (startButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SetSceneSignal(SceneSignal::LOBBYMENU);
|
||||
}
|
||||
if (optionsButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SetSceneSignal(SceneSignal::OPTIONSMENU);
|
||||
}
|
||||
if (quitButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
QuitEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::MouseWheel(SDL_MouseWheelEvent const& event) {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::KeyDown(SDL_KeyboardEvent const& event) {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::KeyUp(SDL_KeyboardEvent const& event) {
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,46 +19,42 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef MAINMENU_HPP_
|
||||
#define MAINMENU_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
#include "image.hpp"
|
||||
#include "text_box.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
class MainMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
MainMenu(lua_State* L);
|
||||
MainMenu();
|
||||
~MainMenu();
|
||||
|
||||
void RenderFrame(SDL_Renderer* renderer) override;
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void Render(SDL_Surface* const);
|
||||
//frame phases
|
||||
void FrameStart() override;
|
||||
void Update() override;
|
||||
void FrameEnd() override;
|
||||
|
||||
//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&);
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
//input events
|
||||
void MouseMotion(SDL_MouseMotionEvent const& event) override;
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseWheel(SDL_MouseWheelEvent const& event) override;
|
||||
void KeyDown(SDL_KeyboardEvent const& event) override;
|
||||
void KeyUp(SDL_KeyboardEvent const& event) override;
|
||||
|
||||
//members
|
||||
Image image;
|
||||
RasterFont font;
|
||||
Image buttonImage;
|
||||
TTF_Font* font = nullptr;
|
||||
Button startButton;
|
||||
Button optionsButton;
|
||||
Button quitButton;
|
||||
TextBox textBox;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../client_utilities ../../common/graphics ../../common/map ../../common/network ../../common/network/packet_types ../../common/ui ../../common/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)/,client.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 $@ $<
|
||||
@@ -0,0 +1,116 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "options_menu.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
OptionsMenu::OptionsMenu() {
|
||||
ConfigUtility& config = ConfigUtility::GetSingleton();
|
||||
|
||||
//setup the utility objects
|
||||
buttonImage.Load(GetRenderer(), config["dir.interface"] + "button_red.png");
|
||||
font = TTF_OpenFont(config["client.font"].c_str(), 12);
|
||||
|
||||
//check that the font loaded
|
||||
if (!font) {
|
||||
std::ostringstream msg;
|
||||
msg << "Failed to load a font file; " << SDL_GetError();
|
||||
throw(std::runtime_error(msg.str()));
|
||||
}
|
||||
|
||||
//setup the button
|
||||
backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
|
||||
backButton.SetText(GetRenderer(), font, "Back", COLOR_BLUE);
|
||||
|
||||
//set the button positions
|
||||
backButton.SetX(50);
|
||||
backButton.SetY(50);
|
||||
|
||||
//text line
|
||||
textLine.SetText(GetRenderer(), font, "This code is fucking hard to refactor.", {255, 255, 255, 255});
|
||||
}
|
||||
|
||||
OptionsMenu::~OptionsMenu() {
|
||||
TTF_CloseFont(font);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void OptionsMenu::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void OptionsMenu::Update() {
|
||||
//
|
||||
}
|
||||
|
||||
void OptionsMenu::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void OptionsMenu::RenderFrame(SDL_Renderer* renderer) {
|
||||
backButton.DrawTo(renderer);
|
||||
textLine.DrawTo(renderer, 50, 30);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void OptionsMenu::MouseMotion(SDL_MouseMotionEvent const& event) {
|
||||
backButton.MouseMotion(event);
|
||||
}
|
||||
|
||||
void OptionsMenu::MouseButtonDown(SDL_MouseButtonEvent const& event) {
|
||||
backButton.MouseButtonDown(event);
|
||||
}
|
||||
|
||||
void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& event) {
|
||||
if (backButton.MouseButtonUp(event) == Button::State::RELEASED) {
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsMenu::MouseWheel(SDL_MouseWheelEvent const& event) {
|
||||
//
|
||||
}
|
||||
|
||||
void OptionsMenu::KeyDown(SDL_KeyboardEvent const& event) {
|
||||
switch(event.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsMenu::KeyUp(SDL_KeyboardEvent const& event) {
|
||||
//
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,45 +19,40 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef OPTIONSMENU_HPP_
|
||||
#define OPTIONSMENU_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "button.hpp"
|
||||
#include "image.hpp"
|
||||
#include "text_line.hpp"
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
//TODO: The options screen needs to be USED
|
||||
//NOTE: The options screen needs to be USED
|
||||
class OptionsMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
OptionsMenu(lua_State* L);
|
||||
OptionsMenu();
|
||||
~OptionsMenu();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void Render(SDL_Surface* const);
|
||||
void RenderFrame(SDL_Renderer* renderer) override;
|
||||
|
||||
//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&);
|
||||
private:
|
||||
//frame phases
|
||||
void FrameStart() override;
|
||||
void Update() override;
|
||||
void FrameEnd() override;
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
//input events
|
||||
void MouseMotion(SDL_MouseMotionEvent const& event) override;
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const& event) override;
|
||||
void MouseWheel(SDL_MouseWheelEvent const& event) override;
|
||||
void KeyDown(SDL_KeyboardEvent const& event) override;
|
||||
void KeyUp(SDL_KeyboardEvent const& event) override;
|
||||
|
||||
//members
|
||||
Image image;
|
||||
RasterFont font;
|
||||
Image buttonImage;
|
||||
TTF_Font* font = nullptr;
|
||||
Button backButton;
|
||||
TextLine textLine;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -21,38 +21,44 @@
|
||||
*/
|
||||
#include "splash_screen.hpp"
|
||||
|
||||
#include <string>
|
||||
#include "config_utility.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
SplashScreen::SplashScreen(lua_State* L): lua(L) {
|
||||
//get the config info
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, -1, "dir");
|
||||
lua_getfield(lua, -1, "logos");
|
||||
std::string logos = lua_tostring(lua, -1);
|
||||
lua_pop(lua, 3);
|
||||
SplashScreen::SplashScreen(SDL_Window* w) {
|
||||
//fit the screen to the logo
|
||||
//NOTE: not using this window trick
|
||||
window = w;
|
||||
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
|
||||
|
||||
logo.Load(GetRenderer(), ConfigUtility::GetSingleton()["dir.logos"] + "krstudios.png");
|
||||
|
||||
// SDL_SetWindowSize(window, logo.GetClipW(), logo.GetClipH());
|
||||
// SDL_RenderSetLogicalSize(GetRenderer(), logo.GetClipW(), logo.GetClipH());
|
||||
|
||||
logo.LoadSurface(logos + "krstudios.bmp");
|
||||
startTick = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
SplashScreen::~SplashScreen() {
|
||||
//
|
||||
// SDL_SetWindowSize(window, windowWidth, windowHeight);
|
||||
// SDL_RenderSetLogicalSize(GetRenderer(), windowWidth, windowHeight);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void SplashScreen::Update(double delta) {
|
||||
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(1)) {
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
void SplashScreen::FrameStart() {
|
||||
//TODO: (0) config flag to change the delay
|
||||
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(3)) {
|
||||
SetSceneSignal(SceneSignal::MAINMENU);
|
||||
}
|
||||
}
|
||||
|
||||
void SplashScreen::Render(SDL_Surface* const screen) {
|
||||
logo.DrawTo(screen, (screen->w - logo.GetClipW()) / 2, (screen->h - logo.GetClipH()) / 2);
|
||||
void SplashScreen::RenderFrame(SDL_Renderer* renderer) {
|
||||
int w = 0, h = 0;
|
||||
SDL_RenderGetLogicalSize(renderer, &w, &h);
|
||||
logo.DrawTo(renderer, (w - logo.GetClipW()) / 2, (h - logo.GetClipH()) / 2);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,34 +19,30 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SPLASHSCREEN_HPP_
|
||||
#define SPLASHSCREEN_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "image.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class SplashScreen : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
SplashScreen(lua_State* L);
|
||||
SplashScreen(SDL_Window*);
|
||||
~SplashScreen();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void Update(double delta);
|
||||
void Render(SDL_Surface* const);
|
||||
void RenderFrame(SDL_Renderer* renderer) override;
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
private:
|
||||
//Frame loop
|
||||
void FrameStart() override;
|
||||
|
||||
//members
|
||||
std::chrono::steady_clock::time_point startTick;
|
||||
Image logo;
|
||||
};
|
||||
|
||||
#endif
|
||||
//screws with the window
|
||||
SDL_Window* window = nullptr;
|
||||
int windowWidth, windowHeight;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,20 +19,19 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SCENELIST_HPP_
|
||||
#define SCENELIST_HPP_
|
||||
#pragma once
|
||||
|
||||
enum class SceneList {
|
||||
//these are reserved
|
||||
QUIT,
|
||||
CONTINUE,
|
||||
FIRST,
|
||||
enum SceneSignal {
|
||||
//reserved members for internal use
|
||||
QUIT = -1,
|
||||
CONTINUE = 0,
|
||||
FIRST = 1,
|
||||
|
||||
//custom indexes
|
||||
//custom scenes
|
||||
SPLASHSCREEN,
|
||||
MAINMENU,
|
||||
OPTIONSMENU,
|
||||
INWORLD,
|
||||
};
|
||||
|
||||
#endif
|
||||
LOBBYMENU,
|
||||
WORLD,
|
||||
DISCONNECTEDSCREEN,
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
Future versions (to be determined) may be released under a modified version of the Uplink Developer's License.
|
||||
|
||||
The current version of Tortuga is released under the zlib license.
|
||||
|
||||
Copyright (c) 2013-2015 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.
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,35 @@
|
||||
This is the README for Tortuga's demo build. The source code is available at:
|
||||
|
||||
https://github.com/Ratstail91/Tortuga
|
||||
|
||||
The current build may have bugs, missing features, bugs masquerading as
|
||||
features, etc. You can report a bug/feature here:
|
||||
|
||||
https://github.com/Ratstail91/Tortuga/issues
|
||||
|
||||
Please note that this game requires a functioning server to operate correctly.
|
||||
Both a game server and game client are included in this package.
|
||||
|
||||
-------------------------
|
||||
Instructions For Setup
|
||||
-------------------------
|
||||
|
||||
1. To create a server, simply run server.exe
|
||||
(a public server is provided by default)
|
||||
2. To join a server, your player information must be input into rsc/config.cfg
|
||||
(NOTE: This process will be streamlined later)
|
||||
3. To change the config settings, open rsc/config.cfg
|
||||
4. These settings must be unique for each player:
|
||||
|
||||
* client.username
|
||||
* client.handle
|
||||
|
||||
5. There are currently two options for 'client.avatar':
|
||||
|
||||
* client.avatar = character1.png #male
|
||||
* client.avatar = character2.png #female
|
||||
|
||||
6. When you've correctly set these values, run client.exe, and select 'Start'
|
||||
from the main menu; this displays the list of available servers.
|
||||
7. Select the name of a server (default is 'Public') and select 'Join'.
|
||||
8. Welcome to Tortuga, enjoy your stay.
|
||||
@@ -1,22 +1,49 @@
|
||||
#for use on Windows:
|
||||
|
||||
#MKDIR=mkdir
|
||||
#Windows 7:
|
||||
#RM=del /y
|
||||
|
||||
#CXXFLAGS+=-static-libgcc -static-libstdc++ -g -fno-inline-functions -Wall
|
||||
#CXXFLAGS+=-static-libgcc -static-libstdc++
|
||||
|
||||
#export
|
||||
#Windows 8.1:
|
||||
#RM=del /S
|
||||
|
||||
OUTDIR=out
|
||||
BINDIR=bin
|
||||
|
||||
all: $(OUTDIR)
|
||||
$(MAKE) -C src
|
||||
all: $(OUTDIR) binary
|
||||
$(MAKE) -C common
|
||||
$(MAKE) -C server
|
||||
$(MAKE) -C client
|
||||
|
||||
debug: export CXXFLAGS+=-g
|
||||
debug: clean all
|
||||
|
||||
release: export CXXFLAGS+=-static-libgcc -static-libstdc++
|
||||
release: clean all package
|
||||
|
||||
#For use on my machine ONLY
|
||||
package:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
rar a -r -ep Tortuga-win.rar $(OUTDIR)/*.exe $(BINDIR)/*.dll
|
||||
rar a -r Tortuga-win.rar rsc/* copyright.txt instructions.txt
|
||||
else ifeq ($(shell uname), Linux)
|
||||
tar -C $(OUTDIR) -zcvf Tortuga-linux.tar client server ../rsc ../copyright.txt ../instructions.txt
|
||||
endif
|
||||
|
||||
binary:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
copy /B /Y $(BINDIR) $(OUTDIR)
|
||||
endif
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
ifeq ($(OS),Windows_NT)
|
||||
del /s *.o *.a *.exe $(OUTDIR)\*.dll
|
||||
rmdir $(OUTDIR)
|
||||
else ifeq ($(shell uname), Linux)
|
||||
find . -type f -name '*.o' -exec rm -f -r -v {} \;
|
||||
find . -type f -name '*.a' -exec rm -f -r -v {} \;
|
||||
rm $(OUTDIR)/* -f
|
||||
find . -empty -type d -delete
|
||||
endif
|
||||
|
||||
rebuild: clean all
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
--reroute the program while in development
|
||||
config = {debug = true}
|
||||
dofile("../rsc/setup.lua")
|
||||
@@ -0,0 +1,2 @@
|
||||
--enable admin privileges for everyone, for debugging purposes
|
||||
UPDATE OR FAIL UserAccounts SET admin = 1;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- simply dump all characters at (0,0) in room 0, for debugging purposes
|
||||
UPDATE OR FAIL LiveCharacters SET roomIndex = 0, originX = 0, originY = 0;
|
||||
@@ -0,0 +1,34 @@
|
||||
#configuration of the programs
|
||||
#TODO: (9) split this file in two, one for each program
|
||||
|
||||
#server specific settings
|
||||
server.host = 255.255.255.255
|
||||
server.port = 21795
|
||||
server.name = local
|
||||
|
||||
server.dbname = database.db
|
||||
|
||||
#client specific settings
|
||||
#client.screen.w = 800
|
||||
#client.screen.h = 600
|
||||
#client.screen.f = false #NOTE: fullscreen option is currently disabled
|
||||
|
||||
#set this to overwrite the default fonts (platform issues)
|
||||
#client.font = /path/to/font/file.ttf
|
||||
|
||||
client.username = username
|
||||
client.handle = handle
|
||||
client.avatar = character2.png
|
||||
|
||||
#directories
|
||||
dir.logos = rsc/graphics/logos/
|
||||
dir.sprites = rsc/graphics/sprites/
|
||||
dir.tilesets = rsc/graphics/tilesets/
|
||||
dir.interface = rsc/graphics/interface/
|
||||
dir.scripts = rsc/scripts/
|
||||
dir.maps = rsc/maps/
|
||||
|
||||
#map system
|
||||
map.savename = servermap
|
||||
|
||||
#debugging
|
||||
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 321 B |
|
Before Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 323 B |
|
Before Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 916 B |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 861 B |
|
After Width: | Height: | Size: 706 B |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 768 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 540 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 108 KiB |
@@ -0,0 +1,89 @@
|
||||
--[[
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
--]]
|
||||
|
||||
--DOCS: a placeholder door utility
|
||||
|
||||
local doorUtility = {}
|
||||
|
||||
roomAPI = require("room")
|
||||
regionPagerAPI = require("region_pager")
|
||||
|
||||
triggerAPI = require("trigger")
|
||||
triggerManagerAPI = require("trigger_manager")
|
||||
|
||||
entityAPI = require("entity")
|
||||
characterAPI = require("character")
|
||||
|
||||
networkAPI = require("network")
|
||||
|
||||
function doorUtility.createTrigger(handle, room, x, y, script)
|
||||
local pager = roomAPI.GetPager(room)
|
||||
|
||||
--place the indicator tile
|
||||
regionPagerAPI.SetTile(pager, x / 32, y / 32, 0, mapMaker.dirt)
|
||||
regionPagerAPI.SetTile(pager, x / 32, y / 32, 1, mapMaker.blank)
|
||||
regionPagerAPI.SetTile(pager, x / 32, y / 32, 2, mapMaker.blank)
|
||||
|
||||
--create the trigger object
|
||||
triggerManagerAPI.Create(
|
||||
roomAPI.GetTriggerMgr(room), handle, x, y,
|
||||
0, 0, 32, 32, --size of the tiles
|
||||
script
|
||||
)
|
||||
end
|
||||
|
||||
function doorUtility.createDoorPair(handle, roomOne, Xone, Yone, roomTwo, Xtwo, Ytwo)
|
||||
--create the scripts
|
||||
local function scriptOne(entity)
|
||||
if entityAPI.GetType(entity) ~= "character" then return end
|
||||
|
||||
--move the character
|
||||
characterAPI.SetRoom(entity, roomTwo)
|
||||
characterAPI.SetOrigin(entity, Xtwo, Ytwo-16)
|
||||
networkAPI.PumpCharacterUpdate(entity)
|
||||
|
||||
--disable the other trigger
|
||||
local triggerTwo = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomTwo), handle)
|
||||
triggerAPI.PushExclusionEntity(triggerTwo, entity)
|
||||
end
|
||||
|
||||
local function scriptTwo(entity)
|
||||
if entityAPI.GetType(entity) ~= "character" then return end
|
||||
|
||||
--move the character
|
||||
characterAPI.SetRoom(entity, roomOne)
|
||||
characterAPI.SetOrigin(entity, Xone, Yone-16) --NOTE: the 16 pixel margin for presentation
|
||||
networkAPI.PumpCharacterUpdate(entity)
|
||||
|
||||
--disable the other trigger
|
||||
local triggerOne = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomOne), handle)
|
||||
triggerAPI.PushExclusionEntity(triggerOne, entity)
|
||||
end
|
||||
|
||||
--create the triggers proper
|
||||
doorUtility.createTrigger(handle, roomOne, Xone, Yone, scriptOne)
|
||||
doorUtility.createTrigger(handle, roomTwo, Xtwo, Ytwo, scriptTwo)
|
||||
end
|
||||
|
||||
return doorUtility
|
||||
@@ -1,9 +0,0 @@
|
||||
--overwriting the existing hard coded methods
|
||||
function Region.Load(region)
|
||||
--the return value signals if this succeeded or failed
|
||||
return false
|
||||
end
|
||||
|
||||
function Region.Save(region)
|
||||
--
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
--uber lazy declarations
|
||||
function math.sqr(x) return x*x end
|
||||
function math.dist(x, y, i, j) return math.sqrt(math.sqr(x-i) + math.sqr(y-j)) end
|
||||
|
||||
--define these
|
||||
function Region.Create(region)
|
||||
for i = 1, Region.GetWidth() do
|
||||
for j = 1, Region.GetHeight() do
|
||||
Region.SetTile(region, i, j, 1, 1) --to show the basics are working
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Region.Unload(region)
|
||||
--
|
||||
end
|
||||
@@ -1,33 +0,0 @@
|
||||
local sheet = TileSheet.GetTileSheet()
|
||||
local pager = RegionPager.GetRegionPager()
|
||||
|
||||
--the selected tilesheet
|
||||
TileSheet.Load(sheet, config.dir.tilesets .. "terrain.bmp", 32, 32)
|
||||
|
||||
--tile macros, mapped to this tilesheet
|
||||
local base = 14
|
||||
local shift = 36
|
||||
tiles = {
|
||||
plains = base + shift * 0,
|
||||
grass = base + shift * 1,
|
||||
dirt = base + shift * 2,
|
||||
sand = base + shift * 3,
|
||||
water = base + shift * 4
|
||||
}
|
||||
|
||||
--could set custom generation systems here, that differ from the global generators, etc.
|
||||
function Region.Create(region)
|
||||
for i = 1, Region.GetWidth() do
|
||||
for j = 1, Region.GetHeight() do
|
||||
local dist = math.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1)
|
||||
if dist < 10 then
|
||||
Region.SetTile(region, i, j, 1, tiles.plains)
|
||||
elseif dist < 12 then
|
||||
Region.SetTile(region, i, j, 1, tiles.sand)
|
||||
else
|
||||
Region.SetTile(region, i, j, 1, tiles.water)
|
||||
Region.SetSolid(region, i, j, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,141 @@
|
||||
--[[
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
--]]
|
||||
|
||||
--DOCS: a placeholder map generator
|
||||
|
||||
local regionAPI = require("region")
|
||||
|
||||
local mapMaker = {}
|
||||
|
||||
--utility functions
|
||||
function mapMaker.Sqr(x) return x*x end
|
||||
function mapMaker.Dist(x, y, i, j) return math.sqrt(mapMaker.Sqr(x - i) + mapMaker.Sqr(y - j)) end
|
||||
|
||||
--tile macros, mapped to the tilesheet "overworld.bmp"
|
||||
mapMaker.blank = 0
|
||||
mapMaker.water = 18 + 3 * 0
|
||||
mapMaker.sand = 18 + 3 * 1
|
||||
mapMaker.plains = 18 + 3 * 2
|
||||
mapMaker.grass = 18 + 3 * 3
|
||||
mapMaker.dirt = 18 + 3 * 4
|
||||
|
||||
--"edge" macros
|
||||
mapMaker.edges = {}
|
||||
mapMaker.edges.north = -16
|
||||
mapMaker.edges.south = 16
|
||||
mapMaker.edges.east = 1
|
||||
mapMaker.edges.west = -1
|
||||
|
||||
--TODO: (1) path system
|
||||
--use these macros (mapped to "overworld.bmp" for now) to smooth the region's edges
|
||||
function mapMaker.SmoothEdgesSimple(r)
|
||||
--make and pad an array to use
|
||||
local shiftArray = {}
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
shiftArray[i] = {}
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
shiftArray[i][j] = 0
|
||||
end
|
||||
end
|
||||
|
||||
--build the array
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
--if (not regionAPI edge) and (west tile < this tile), etc.
|
||||
if i > 1 and regionAPI.GetTile(r, i - 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.west
|
||||
end
|
||||
if j > 1 and regionAPI.GetTile(r, i, j - 1, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.north
|
||||
end
|
||||
if i < regionAPI.GetWidth(r) and regionAPI.GetTile(r, i + 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.east
|
||||
end
|
||||
if j < regionAPI.GetHeight(r) and regionAPI.GetTile(r, i, j + 1, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.south
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--finally apply this
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
if shiftArray[i][j] ~= 0 then
|
||||
regionAPI.SetTile(r, i, j, 2, regionAPI.GetTile(r, i, j, 1) + shiftArray[i][j])
|
||||
regionAPI.SetTile(r, i, j, 1, regionAPI.GetTile(r, i, j, 1) - 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--custom generation systems here
|
||||
function mapMaker.DebugIsland(r)
|
||||
--debug
|
||||
io.write("map_maker:DebugIsland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n")
|
||||
|
||||
--basic distance check for each tile, placing an island around the world origin
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
local dist = mapMaker.Dist(0, 0, i + regionAPI.GetX(r) -1, j + regionAPI.GetY(r) -1)
|
||||
if dist < 10 then
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.plains)
|
||||
elseif dist < 12 then
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.sand)
|
||||
else
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.water)
|
||||
regionAPI.SetSolid(r, i, j, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--examples of the smoothing function NOT working correctly
|
||||
--[[
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
regionAPI.SetTile(r, 3, j, 1, mapMaker.dirt)
|
||||
regionAPI.SetTile(r, 4, j, 1, mapMaker.dirt)
|
||||
|
||||
regionAPI.SetTile(r, 10, j, 1, mapMaker.dirt)
|
||||
end
|
||||
--]]
|
||||
|
||||
--A generic edge system
|
||||
mapMaker.SmoothEdgesSimple(r)
|
||||
end
|
||||
|
||||
function mapMaker.DebugGrassland(r)
|
||||
--debug
|
||||
io.write("map_maker:DebugGrassland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n")
|
||||
|
||||
--all dirt
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.grass)
|
||||
end
|
||||
end
|
||||
|
||||
--A generic edge system
|
||||
-- mapMaker.SmoothEdgesSimple(r)
|
||||
end
|
||||
|
||||
return mapMaker
|
||||
@@ -0,0 +1,39 @@
|
||||
--[[
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
--]]
|
||||
|
||||
local region = require("region")
|
||||
|
||||
local mapSaver = {}
|
||||
|
||||
function mapSaver.Load(r)
|
||||
--empty
|
||||
-- io.write("map_saver:Load(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
||||
end
|
||||
function mapSaver.Save(r)
|
||||
--empty
|
||||
-- io.write("map_saver:Save(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
||||
end
|
||||
|
||||
--TODO: (3) create a flexible saving & loading system
|
||||
return mapSaver
|
||||
@@ -0,0 +1,61 @@
|
||||
--[[
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
--]]
|
||||
|
||||
--DOCS: This script is run by the server on startup
|
||||
|
||||
print("Lua script check")
|
||||
|
||||
--requirements
|
||||
roomManagerAPI = require("room_manager")
|
||||
roomAPI = require("room")
|
||||
|
||||
mapMaker = require("map_maker")
|
||||
mapSaver = require("map_saver")
|
||||
|
||||
doorUtility = require("door_utility")
|
||||
|
||||
--test the room hooks
|
||||
roomManagerAPI.SetOnCreate(function(room, index)
|
||||
print("", "Creating room: ", roomAPI.GetName(room), index)
|
||||
|
||||
roomAPI.SetOnTick(room, function(room)
|
||||
roomAPI.ForEachCharacter(room, function(character)
|
||||
--
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
roomManagerAPI.SetOnUnload(function(room, index)
|
||||
print("", "Unloading room: ", roomAPI.GetName(room), index)
|
||||
end)
|
||||
|
||||
--NOTE: room 0 is the first that the client asks for, therefore it must exist
|
||||
local overworld, uidOne = roomManagerAPI.CreateRoom("overworld", "overworld.bmp")
|
||||
roomAPI.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save)
|
||||
|
||||
local underworld, uidTwo = roomManagerAPI.CreateRoom("underworld", "overworld.bmp")
|
||||
roomAPI.Initialize(underworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugGrassland, mapSaver.Save)
|
||||
|
||||
--call the monstrosity
|
||||
doorUtility.createDoorPair("pair 1", overworld, -64, -64, underworld, 64, 64)
|
||||
@@ -0,0 +1,158 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
CREATE TABLE IF NOT EXISTS UserAccounts (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username varchar(100) UNIQUE, --TODO: (3) Swap username for email address
|
||||
|
||||
--server-client security
|
||||
-- passhash varchar(100),
|
||||
-- passsalt varchar(100),
|
||||
|
||||
--server controls
|
||||
blacklisted BIT DEFAULT 0,
|
||||
whitelisted BIT DEFAULT 1,
|
||||
mod BIT DEFAULT 0,
|
||||
admin BIT DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS LiveCharacters (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
--metadata
|
||||
owner INTEGER REFERENCES Accounts(uid),
|
||||
handle varchar(100) UNIQUE,
|
||||
avatar varchar(100),
|
||||
birth timestamp NOT NULL DEFAULT (datetime()),
|
||||
|
||||
--physically exists in the world
|
||||
roomIndex INTEGER DEFAULT 0,
|
||||
originX INTEGER DEFAULT 0,
|
||||
originY INTEGER DEFAULT 0,
|
||||
boundsX INTEGER DEFAULT 0,
|
||||
boundsY INTEGER DEFAULT 0,
|
||||
boundsW INTEGER DEFAULT 0,
|
||||
boundsH INTEGER DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DeadCharacters (
|
||||
uid INTEGER PRIMARY KEY,
|
||||
|
||||
--metadata
|
||||
owner INTEGER REFERENCES Accounts(uid),
|
||||
handle varchar(100),
|
||||
avatar varchar(100),
|
||||
birth timestamp NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS LiveMonsters (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
--metadata
|
||||
handle varchar(100) UNIQUE,
|
||||
avatar varchar(100),
|
||||
|
||||
--actions
|
||||
-- script
|
||||
|
||||
--physically exists in the world
|
||||
roomIndex INTEGER DEFAULT 0,
|
||||
originX INTEGER DEFAULT 0,
|
||||
originY INTEGER DEFAULT 0,
|
||||
boundsX INTEGER DEFAULT 0,
|
||||
boundsY INTEGER DEFAULT 0,
|
||||
boundsW INTEGER DEFAULT 0,
|
||||
boundsH INTEGER DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DeadMonsters (
|
||||
uid INTEGER PRIMARY KEY,
|
||||
|
||||
--metadata
|
||||
handle varchar(100) UNIQUE,
|
||||
avatar varchar(100)
|
||||
);
|
||||
|
||||
-------------------------
|
||||
--Utility tables
|
||||
-------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS StatisticSets (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
--general use 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
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS InWorldItems (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
itemType INTEGER,
|
||||
|
||||
--position in the world
|
||||
roomIndex INTEGER DEFAULT 0,
|
||||
originX INTEGER DEFAULT 0,
|
||||
originY INTEGER DEFAULT 0,
|
||||
|
||||
--unique information
|
||||
stackSize INTEGER DEFAULT 0,
|
||||
durability INTEGER DEFAULT 0,
|
||||
stats INTEGER REFERENCES StatisticSets(uid)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS InventoryItems (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
owner INTEGER REFERENCES Characters(uid),
|
||||
itemType INTEGER,
|
||||
|
||||
--unique information
|
||||
stackSize INTEGER DEFAULT 0,
|
||||
durability INTEGER DEFAULT 0,
|
||||
stats INTEGER REFERENCES StatisticSets(uid)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS WornEquipment (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
owner INTEGER REFERENCES Characters(uid),
|
||||
itemType INTEGER,
|
||||
|
||||
--unique information
|
||||
durability INTEGER DEFAULT 0,
|
||||
stats INTEGER REFERENCES StatisticSets(uid)
|
||||
--attached script?
|
||||
);
|
||||
@@ -1,42 +0,0 @@
|
||||
--[[
|
||||
--reroute the program while in development
|
||||
config = {debug = true}
|
||||
dofile("../rsc/setup.lua")
|
||||
--]]
|
||||
|
||||
--catch the debug signal if the program was rerouted
|
||||
local debug = false
|
||||
if config ~= nil then
|
||||
debug = config.debug
|
||||
end
|
||||
|
||||
--the program's configuration
|
||||
config = {
|
||||
debug = debug,
|
||||
screen = {
|
||||
width = 800,
|
||||
height = 600,
|
||||
fullscreen = false
|
||||
},
|
||||
dir = {
|
||||
fonts = "rsc/graphics/fonts/",
|
||||
logos = "rsc/graphics/logos/",
|
||||
sprites = "rsc/graphics/sprites/",
|
||||
tilesets = "rsc/graphics/tilesets/",
|
||||
interface = "rsc/graphics/interface/",
|
||||
scripts = "rsc/scripts/",
|
||||
maps = "rsc/maps/"
|
||||
},
|
||||
mapname = "mapname"
|
||||
}
|
||||
|
||||
--development environment
|
||||
if config.debug then
|
||||
for k, v in pairs(config.dir) do
|
||||
config.dir[k] = string.format("../%s", v)
|
||||
end
|
||||
end
|
||||
|
||||
--"load" the scripted systems
|
||||
dofile(config.dir.scripts .. "file_format.lua")
|
||||
dofile(config.dir.scripts .. "generator.lua")
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "account_data.hpp"
|
||||
|
||||
int AccountData::SetClientIndex(int i) {
|
||||
return clientIndex = i;
|
||||
}
|
||||
|
||||
int AccountData::GetClientIndex() {
|
||||
return clientIndex;
|
||||
}
|
||||
|
||||
std::string AccountData::SetUsername(std::string s) {
|
||||
return username = s;
|
||||
}
|
||||
|
||||
std::string AccountData::GetUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
bool AccountData::GetBlackListed() {
|
||||
return blackListed;
|
||||
}
|
||||
|
||||
bool AccountData::GetWhiteListed() {
|
||||
return whiteListed;
|
||||
}
|
||||
|
||||
bool AccountData::GetModerator() {
|
||||
return mod;
|
||||
}
|
||||
|
||||
bool AccountData::GetAdministrator() {
|
||||
return admin;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class AccountData {
|
||||
public:
|
||||
AccountData() = default;
|
||||
~AccountData() = default;
|
||||
|
||||
//accessors and mutators
|
||||
int SetClientIndex(int i);
|
||||
int GetClientIndex();
|
||||
|
||||
std::string SetUsername(std::string s);
|
||||
std::string GetUsername();
|
||||
|
||||
//database stuff
|
||||
bool GetBlackListed();
|
||||
bool GetWhiteListed();
|
||||
bool GetModerator();
|
||||
bool GetAdministrator();
|
||||
|
||||
private:
|
||||
friend class AccountManager;
|
||||
|
||||
int clientIndex;
|
||||
std::string username;
|
||||
//password/auth token
|
||||
|
||||
//bit fields?
|
||||
bool blackListed = false;
|
||||
bool whiteListed = true;
|
||||
bool mod = false;
|
||||
bool admin = false;
|
||||
};
|
||||
@@ -0,0 +1,279 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "account_manager.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Define the queries
|
||||
//-------------------------
|
||||
|
||||
static const char* CREATE_USER_ACCOUNT = "INSERT INTO UserAccounts (username) VALUES (?);";
|
||||
|
||||
static const char* LOAD_USER_ACCOUNT = "SELECT "
|
||||
"uid, "
|
||||
"blacklisted, "
|
||||
"whitelisted, "
|
||||
"mod, "
|
||||
"admin "
|
||||
" FROM UserAccounts WHERE username = ?;";
|
||||
|
||||
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL UserAccounts SET "
|
||||
"blacklisted = ?2, "
|
||||
"whitelisted = ?3, "
|
||||
"mod = ?4, "
|
||||
"admin = ?5 "
|
||||
"WHERE uid = ?1;";
|
||||
|
||||
static const char* DELETE_USER_ACCOUNT = "DELETE FROM UserAccounts WHERE uid = ?;";
|
||||
|
||||
static const char* COUNT_USER_ACCOUNT_RECORDS = "SELECT COUNT(*) FROM UserAccounts;";
|
||||
|
||||
//-------------------------
|
||||
//Define the public methods
|
||||
//-------------------------
|
||||
|
||||
//TODO: (1) block blacklisted accounts
|
||||
int AccountManager::Create(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 Load(username, clientIndex);
|
||||
}
|
||||
|
||||
int AccountManager::Load(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 (elementMap.find(uid) != elementMap.end()) {
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//extract the data into memory
|
||||
AccountData& newAccount = elementMap[uid];
|
||||
newAccount.username = username;
|
||||
newAccount.blackListed = sqlite3_column_int(statement, 1);
|
||||
newAccount.whiteListed = sqlite3_column_int(statement, 2);
|
||||
newAccount.mod = sqlite3_column_int(statement, 3);
|
||||
newAccount.admin = sqlite3_column_int(statement, 4);
|
||||
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 Create(username, clientIndex);
|
||||
}
|
||||
|
||||
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadAccount: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
|
||||
int AccountManager::Save(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 (elementMap.find(uid) == elementMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
AccountData& account = elementMap[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;
|
||||
ret |= sqlite3_bind_int(statement, 4, account.mod) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 5, account.admin) != 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 AccountManager::Unload(int uid) {
|
||||
//save this user account, and then unload it
|
||||
//NOTE: the associated characters are unloaded externally
|
||||
Save(uid);
|
||||
elementMap.erase(uid);
|
||||
}
|
||||
|
||||
void AccountManager::Delete(int uid) {
|
||||
//delete a user account from the database, and remove it from memory
|
||||
//NOTE: the associated characters should be deleted 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);
|
||||
elementMap.erase(uid);
|
||||
}
|
||||
|
||||
void AccountManager::UnloadAll() {
|
||||
for (auto& it : elementMap) {
|
||||
Save(it.first);
|
||||
}
|
||||
elementMap.clear();
|
||||
}
|
||||
|
||||
void AccountManager::UnloadIf(std::function<bool(std::pair<const int, AccountData const&>)> fn) {
|
||||
//replicate std::remove_if, using custom code
|
||||
std::map<int, AccountData>::iterator it = elementMap.begin();
|
||||
while (it != elementMap.end()) {
|
||||
if (fn(*it)) {
|
||||
Save(it->first);
|
||||
it = elementMap.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Define the accessors and mutators
|
||||
//-------------------------
|
||||
|
||||
AccountData* AccountManager::Get(int uid) {
|
||||
std::map<int, AccountData>::iterator it = elementMap.find(uid);
|
||||
|
||||
if (it == elementMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
int AccountManager::GetLoadedCount() {
|
||||
return elementMap.size();
|
||||
}
|
||||
|
||||
int AccountManager::GetTotalCount() {
|
||||
//a lot just to count something.
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, COUNT_USER_ACCOUNT_RECORDS, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute & retrieve the result
|
||||
sqlite3_step(statement);
|
||||
int ret = sqlite3_column_int(statement, 0);
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::map<int, AccountData>* AccountManager::GetContainer() {
|
||||
return &elementMap;
|
||||
}
|
||||
|
||||
sqlite3* AccountManager::SetDatabase(sqlite3* db) {
|
||||
return database = db;
|
||||
}
|
||||
|
||||
sqlite3* AccountManager::GetDatabase() {
|
||||
return database;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "account_data.hpp"
|
||||
#include "singleton.hpp"
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
class AccountManager: public Singleton<AccountManager> {
|
||||
public:
|
||||
//common public methods
|
||||
int Create(std::string username, int clientIndex);
|
||||
int Load(std::string username, int clientIndex);
|
||||
int Save(int uid);
|
||||
void Unload(int uid);
|
||||
void Delete(int uid);
|
||||
|
||||
void UnloadAll();
|
||||
void UnloadIf(std::function<bool(std::pair<const int, AccountData const&>)> fn);
|
||||
|
||||
//accessors and mutators
|
||||
AccountData* Get(int uid);
|
||||
int GetLoadedCount();
|
||||
int GetTotalCount();
|
||||
std::map<int, AccountData>* GetContainer();
|
||||
|
||||
sqlite3* SetDatabase(sqlite3* db);
|
||||
sqlite3* GetDatabase();
|
||||
|
||||
private:
|
||||
friend Singleton<AccountManager>;
|
||||
|
||||
AccountManager() = default;
|
||||
~AccountManager() = default;
|
||||
|
||||
//members
|
||||
std::map<int, AccountData> elementMap;
|
||||
sqlite3* database = nullptr;
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
INCLUDES+=. ../server_utilities ../../common/utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
@@ -12,7 +12,7 @@ OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
OUT=$(addprefix $(OUTDIR)/,server.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -0,0 +1,129 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "character_api.hpp"
|
||||
|
||||
#include "character_data.hpp"
|
||||
#include "character_manager.hpp"
|
||||
#include "entity_api.hpp"
|
||||
#include "room_manager.hpp"
|
||||
#include "server_utilities.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
static int setRoom(lua_State* L) {
|
||||
//reverse engineer the character index
|
||||
int characterIndex = -1;
|
||||
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||
|
||||
for (auto& it : *characterMgr.GetContainer()) {
|
||||
if (character == &it.second) {
|
||||
characterIndex = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//error checking
|
||||
if (characterIndex == -1) {
|
||||
throw(std::runtime_error("Lua Error: Failed to find character index by reference"));
|
||||
}
|
||||
|
||||
//get the room index, depending on the parameter type
|
||||
int roomIndex = -1;
|
||||
RoomManager& roomMgr = RoomManager::GetSingleton();
|
||||
switch(lua_type(L, 2)) {
|
||||
case LUA_TNUMBER:
|
||||
roomIndex = lua_tointeger(L, 2);
|
||||
break;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
//reverse engineer the room index
|
||||
for (auto& it : *roomMgr.GetContainer()) {
|
||||
if (lua_touserdata(L, 2) == &it.second) {
|
||||
roomIndex = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//error checking
|
||||
if (roomIndex == -1) {
|
||||
throw(std::runtime_error("Lua Error: Failed to find room index by reference"));
|
||||
}
|
||||
|
||||
//send the delete & create messages
|
||||
pumpAndChangeRooms(character, roomIndex, characterIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getOwner(lua_State* L) {
|
||||
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, character->GetOwner());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getHandle(lua_State* L) {
|
||||
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||
lua_pushstring(L, character->GetHandle().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getAvatar(lua_State* L) {
|
||||
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||
lua_pushstring(L, character->GetAvatar().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg characterLib[] = {
|
||||
{"SetRoom", setRoom},
|
||||
// {"GetOwner", getOwner}, //unusable without account API
|
||||
{"GetHandle", getHandle},
|
||||
{"GetAvatar", getAvatar},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openCharacterAPI(lua_State* L) {
|
||||
//get the parent table
|
||||
luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false);
|
||||
|
||||
//the local table
|
||||
luaL_newlib(L, characterLib);
|
||||
|
||||
//merge the local table into the parent table
|
||||
lua_pushnil(L); //first key
|
||||
while(lua_next(L, -2)) {
|
||||
//copy the key-value pair
|
||||
lua_pushvalue(L, -2);
|
||||
lua_pushvalue(L, -2);
|
||||
|
||||
//push the copy to the parent table
|
||||
lua_settable(L, -6);
|
||||
|
||||
//pop the original value before continuing
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
//remove the local table, leaving the expanded parent table
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,12 +19,9 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONAPI_HPP_
|
||||
#define REGIONAPI_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_REGION_NAME "Region"
|
||||
LUAMOD_API int openRegionAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
#define TORTUGA_CHARACTER_API "character"
|
||||
LUAMOD_API int openCharacterAPI(lua_State* L);
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "character_data.hpp"
|
||||
|
||||
CharacterData::CharacterData(): Entity("character") {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
int CharacterData::GetOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
std::string CharacterData::GetHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
std::string CharacterData::GetAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,31 +19,30 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef APPLICATION_HPP_
|
||||
#define APPLICATION_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "scene_list.hpp"
|
||||
#include "base_scene.hpp"
|
||||
//components
|
||||
#include "character_defines.hpp"
|
||||
#include "entity.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
//std namespace
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
class Application {
|
||||
class CharacterData: public Entity {
|
||||
public:
|
||||
Application() = default;
|
||||
~Application() = default;
|
||||
CharacterData();
|
||||
~CharacterData() = default;
|
||||
|
||||
void Init(int argc, char** argv);
|
||||
void Proc();
|
||||
void Quit();
|
||||
//database stuff
|
||||
int GetOwner();
|
||||
std::string GetHandle();
|
||||
std::string GetAvatar();
|
||||
|
||||
private:
|
||||
//Private access members
|
||||
void LoadScene(SceneList sceneIndex);
|
||||
void UnloadScene();
|
||||
friend class CharacterManager;
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
|
||||
lua_State* lua = nullptr;
|
||||
int owner = -1;
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,348 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "character_manager.hpp"
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#include "character_defines.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Define the queries
|
||||
//-------------------------
|
||||
|
||||
//NOTE: Programmer set variables are NOT zero-indexed
|
||||
//NOTE: SQLite3 returned variables (i.e. loading) ARE zero-indexed
|
||||
|
||||
static const char* CREATE_CHARACTER = "INSERT INTO LiveCharacters ("
|
||||
"owner, "
|
||||
"handle, "
|
||||
"avatar, "
|
||||
"boundsX, "
|
||||
"boundsY, "
|
||||
"boundsW, "
|
||||
"boundsH"
|
||||
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
|
||||
|
||||
static const char* LOAD_CHARACTER = "SELECT "
|
||||
"uid, "
|
||||
"owner, "
|
||||
"handle, "
|
||||
"avatar, "
|
||||
"roomIndex, "
|
||||
"originX, "
|
||||
"originY, "
|
||||
"boundsX, "
|
||||
"boundsY, "
|
||||
"boundsW, "
|
||||
"boundsH "
|
||||
"FROM LiveCharacters WHERE handle = ?;";
|
||||
|
||||
static const char* SAVE_CHARACTER = "UPDATE OR FAIL LiveCharacters SET "
|
||||
"roomIndex = ?2, "
|
||||
"originX = ?3, "
|
||||
"originY = ?4, "
|
||||
"boundsX = ?5, "
|
||||
"boundsY = ?6, "
|
||||
"boundsW = ?7, "
|
||||
"boundsH = ?8 "
|
||||
"WHERE uid = ?1;";
|
||||
|
||||
static const char* DELETE_CHARACTER = "DELETE FROM LiveCharacters WHERE uid = ?;";
|
||||
|
||||
static const char* COUNT_CHARACTER_RECORDS = "SELECT COUNT(*) FROM LiveCharacters;";
|
||||
|
||||
//-------------------------
|
||||
//Define the methods
|
||||
//-------------------------
|
||||
|
||||
//NOTE: default baseStats as a parameter would be good for different beggining states or multiple classes
|
||||
int CharacterManager::Create(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);
|
||||
ret |= sqlite3_bind_int(statement, 4, CHARACTER_BOUNDS_X);
|
||||
ret |= sqlite3_bind_int(statement, 5, CHARACTER_BOUNDS_Y);
|
||||
ret |= sqlite3_bind_int(statement, 6, CHARACTER_BOUNDS_WIDTH);
|
||||
ret |= sqlite3_bind_int(statement, 7, CHARACTER_BOUNDS_HEIGHT);
|
||||
|
||||
//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 Load(owner, handle, avatar);
|
||||
}
|
||||
|
||||
int CharacterManager::Load(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 (elementMap.find(uid) != elementMap.end()) {
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check the owner
|
||||
if (owner != sqlite3_column_int(statement, 1)) {
|
||||
sqlite3_finalize(statement);
|
||||
//unload the already loaded character
|
||||
Unload(uid);
|
||||
return -2;
|
||||
}
|
||||
|
||||
//extract the data into memory
|
||||
CharacterData& newChar = elementMap[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 origin
|
||||
newChar.roomIndex = sqlite3_column_int(statement, 4);
|
||||
newChar.origin.x = (double)sqlite3_column_int(statement, 5);
|
||||
newChar.origin.y = (double)sqlite3_column_int(statement, 6);
|
||||
//bounds
|
||||
newChar.bounds.x = (int)sqlite3_column_int(statement, 7);
|
||||
newChar.bounds.y = (int)sqlite3_column_int(statement, 8);
|
||||
newChar.bounds.w = (int)sqlite3_column_int(statement, 9);
|
||||
newChar.bounds.h = (int)sqlite3_column_int(statement, 10);
|
||||
|
||||
//gameplay components: equipment, items, buffs, debuffs...
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
return uid;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
if (ret == SQLITE_DONE) {
|
||||
//create the non-existant character instead
|
||||
return Create(owner, handle, avatar);
|
||||
}
|
||||
|
||||
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
|
||||
int CharacterManager::Save(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 (elementMap.find(uid) == elementMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CharacterData& character = elementMap[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.roomIndex) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 5, character.bounds.x) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 6, character.bounds.y) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 7, character.bounds.w) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 8, character.bounds.h) != SQLITE_OK;
|
||||
|
||||
//gameplay components: equipment, items, buffs, debuffs...
|
||||
|
||||
//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 a character: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//successful execution
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CharacterManager::Unload(int uid) {
|
||||
//save this character, then unload it
|
||||
Save(uid);
|
||||
elementMap.erase(uid);
|
||||
}
|
||||
|
||||
void CharacterManager::Delete(int uid) {
|
||||
//TODO: (9) when deleting a character, move it to an archive table
|
||||
//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 a character: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
elementMap.erase(uid);
|
||||
}
|
||||
|
||||
void CharacterManager::UnloadAll() {
|
||||
for (auto& it : elementMap) {
|
||||
Save(it.first);
|
||||
}
|
||||
elementMap.clear();
|
||||
}
|
||||
|
||||
void CharacterManager::UnloadIf(std::function<bool(std::pair<const int, CharacterData const&>)> fn) {
|
||||
std::map<int, CharacterData>::iterator it = elementMap.begin();
|
||||
while (it != elementMap.end()) {
|
||||
if (fn(*it)) {
|
||||
Save(it->first);
|
||||
it = elementMap.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Define the accessors and mutators
|
||||
//-------------------------
|
||||
|
||||
CharacterData* CharacterManager::Get(int uid) {
|
||||
std::map<int, CharacterData>::iterator it = elementMap.find(uid);
|
||||
|
||||
if (it == elementMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
CharacterData* CharacterManager::Get(std::string handle) {
|
||||
for (std::map<int, CharacterData>::iterator it = elementMap.begin(); it != elementMap.end(); ++it) {
|
||||
if (it->second.GetHandle() == handle) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int CharacterManager::GetLoadedCount() {
|
||||
return elementMap.size();
|
||||
}
|
||||
|
||||
int CharacterManager::GetTotalCount() {
|
||||
//a lot just to count something.
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, COUNT_CHARACTER_RECORDS, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute & retrieve the result
|
||||
sqlite3_step(statement);
|
||||
int ret = sqlite3_column_int(statement, 0);
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::map<int, CharacterData>* CharacterManager::GetContainer() {
|
||||
return &elementMap;
|
||||
}
|
||||
|
||||
sqlite3* CharacterManager::SetDatabase(sqlite3* db) {
|
||||
return database = db;
|
||||
}
|
||||
|
||||
sqlite3* CharacterManager::GetDatabase() {
|
||||
return database;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "character_data.hpp"
|
||||
#include "singleton.hpp"
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
class CharacterManager: public Singleton<CharacterManager> {
|
||||
public:
|
||||
//common public methods
|
||||
int Create(int owner, std::string handle, std::string avatar);
|
||||
int Load(int owner, std::string handle, std::string avatar);
|
||||
int Save(int uid);
|
||||
void Unload(int uid);
|
||||
void Delete(int uid);
|
||||
|
||||
void UnloadAll();
|
||||
void UnloadIf(std::function<bool(std::pair<const int, CharacterData const&>)> fn);
|
||||
|
||||
//accessors and mutators
|
||||
CharacterData* Get(int uid);
|
||||
CharacterData* Get(std::string handle);
|
||||
int GetLoadedCount();
|
||||
int GetTotalCount();
|
||||
std::map<int, CharacterData>* GetContainer();
|
||||
|
||||
//API interface
|
||||
sqlite3* SetDatabase(sqlite3* db);
|
||||
sqlite3* GetDatabase();
|
||||
|
||||
//hooks
|
||||
//TODO: character hooks
|
||||
|
||||
private:
|
||||
friend Singleton<CharacterManager>;
|
||||
|
||||
CharacterManager() = default;
|
||||
~CharacterManager() = default;
|
||||
|
||||
//members
|
||||
std::map<int, CharacterData> elementMap;
|
||||
sqlite3* database = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,114 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "character_manager_api.hpp"
|
||||
|
||||
#include "character_manager.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//TODO: (1) character hooks?
|
||||
|
||||
static int setOnCreate(lua_State* L) {
|
||||
//TODO: (9) setOnCreate()
|
||||
}
|
||||
|
||||
static int setOnLoad(lua_State* L) {
|
||||
//TODO: (9) setOnLoad()
|
||||
}
|
||||
|
||||
static int setOnSave(lua_State* L) {
|
||||
//TODO: (9) setOnSave()
|
||||
}
|
||||
|
||||
static int setOnUnload(lua_State* L) {
|
||||
//TODO: (9) setOnUnload()
|
||||
}
|
||||
|
||||
static int setOnDelete(lua_State* L) {
|
||||
//TODO: (9) setOnDelete()
|
||||
}
|
||||
|
||||
static int getCharacter(lua_State* L) {
|
||||
//integer vs name
|
||||
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||
CharacterData* characterData = nullptr;
|
||||
|
||||
switch(lua_type(L, 1)) {
|
||||
case LUA_TNUMBER:
|
||||
characterData = characterMgr.Get(lua_tointeger(L, 1));
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
//access characters via their handles
|
||||
characterData = characterMgr.Get(lua_tostring(L, 1));
|
||||
break;
|
||||
}
|
||||
|
||||
if (characterData) {
|
||||
lua_pushlightuserdata(L, static_cast<void*>(characterData));
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getLoadedCount(lua_State* L) {
|
||||
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||
lua_pushinteger(L, characterMgr.GetLoadedCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int forEach(lua_State* L) {
|
||||
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||
//pass each character to the given function
|
||||
for (auto& it : *characterMgr.GetContainer()) {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushlightuserdata(L, static_cast<void*>(&it.second));
|
||||
//call each iteration, throwing an exception if something happened
|
||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||
std::ostringstream os;
|
||||
os << "Lua error: ";
|
||||
os << lua_tostring(L, -1);
|
||||
throw(std::runtime_error(os.str()));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg characterManagerLib[] = {
|
||||
// {"SetOnCreate", setOnCreate},
|
||||
// {"SetOnLoad", setOnLoad},
|
||||
// {"SetOnSave", setOnSave},
|
||||
// {"SetOnUnload", setOnUnload},
|
||||
// {"SetOnDelete", setOnDelete},
|
||||
{"GetCharacter", getCharacter},
|
||||
{"GetLoadedCount", getLoadedCount},
|
||||
{"ForEach", forEach},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openCharacterManagerAPI(lua_State* L) {
|
||||
luaL_newlib(L, characterManagerLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_CHARACTER_MANAGER_API "character_manager"
|
||||
LUAMOD_API int openCharacterManagerAPI(lua_State* L);
|
||||
@@ -0,0 +1,32 @@
|
||||
#config
|
||||
INCLUDES+=. ../entities ../monsters ../rooms ../server_utilities ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/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)/,server.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 $@ $<
|
||||