├── .earthignore ├── .gitattributes ├── .github ├── goreleaser-for-darwin.yaml ├── goreleaser-for-linux.yaml ├── goreleaser-release.yaml ├── watch └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── .gitignore ├── .ignore ├── README.md ├── archive ├── base.list ├── base.py ├── build ├── build-base ├── cbor2.pyi ├── ci ├── dump-source.py ├── package.py ├── quadropolis.py ├── requirements.txt ├── setup ├── setup-quad ├── shims │ ├── 0096dc89086a719a46673375008c3d0fb0c28924b73ec7d710a3a0c50fd7ae7c │ ├── 015fccd0f901512ac085d7dae9ed640fa58654e5f97983ab83a4593a63f9fe5f │ ├── 01fd176f9fb47a0674aaeb3239aada6e6c181f53f5ebedad3a55b8501f154044 │ ├── 070c7ab17d183c8142e807312f74976f7462000bd36a28441647f12cd4284cdc │ ├── 0bc7310b445c329ab72488376a5036bf81fa9656227b4a81bb24be8bd4c14311 │ ├── 0c4569d63fb6f794c838e2186a45a72b249b9dd04a2b9b371cf3b5ab2ec695e5 │ ├── 0c54fb80e7846c702af9b1aab7d740d366b0ea3521a5a42a104536f59304e484 │ ├── 0c86cf6e9c8576d4e1801b926155c32ba002be743976f41edd5afe95efe0cf13 │ ├── 0d4021ee258308176f434eca06c482a50eae89b93b64a13aaac7b59c4a1be3c4 │ ├── 0de22217476089e1ee5c375fe62fd05ca9ea18a2804166e693cf60fc8e550d71 │ ├── 0e10166cefd4240d957859e79f83f837800e99a48ac27734c6ba72df74ff0961 │ ├── 0e9e769e2e046a7369ccd0c7b37d5d551255f66d39e2ca8d46b61e461e860b80 │ ├── 0ee68647a2b67d15e88dac285aa97418409d3f76c0b1164782cba2637ef75756 │ ├── 0f8891010c077cff0a7efeea17a7900d99045c0ef96dc9c0e611affb1388d2ba │ ├── 0f898e2dc43604d84cbd9b256c5da5124844859d76c331945b51b29dc43f1401 │ ├── 11032c248520000eb913d28f8d436f257460d9b1ce0550d2f50efa62b2c9cf63 │ ├── 11498a75b2c35aea1ac33cacaa40cc3aff89a322e5cb1eb779cb75165e087fe7 │ ├── 1410b9704b3527c41e96f4505de11f4b2525e38780418d14ad62bac3057b05b3 │ ├── 172dad215b26ba42dd8ff7b412e5cc5d107d7097ddb4fd3ac60a646dcfaf14fc │ ├── 1a487d500b50df580f4583d6c5794b614cf6d69d53cfd842c06f10caaf68675a │ ├── 1a5a7410827f2c558cae37ee0a9e30b5705a6714341f6203333557d00aeff97f │ ├── 1d83cec97b9942af6d6c6b68c74c4b845bb57b7a4ac56f5f807451511e07a239 │ ├── 20f72a837babe4a9908757271249f6f021afb582d30b61aa562128648f621254 │ ├── 2306c587bd0e037c386327ae632836a532cb9b8d9df965e430e8e8b818f75806 │ ├── 238b9d2a8b155854c345e182ed5bb93fde663f38a41991747c4b6976bb1977de │ ├── 23bb569608dbf5d5ef3b8c791ae1f6987f0cbfc754cc17e7443cda4459cdc8ee │ ├── 2674dabf11f22067ca7ac632bd3a23daf26945a45f20c043cdda00c06db944b2 │ ├── 26d24b2c55df45b4228f8b92a0a37fe77f31e20931bf48b0cb43899d161e6619 │ ├── 2881fa2b95c13ff636e3e4344991f9bdcbcb1731afacbd56e3f1a0e626daef88 │ ├── 2baacd05ea5d29855b6cd8d7983f526b5b7bc430fa1338fc95aa6b81188a86ea │ ├── 2d4178d6ea809e4ec0e60b62ec20d2f8daa8e447945c8234fda0f53899ec8608 │ ├── 2f01d00cbe00419ed2abd6adce9cd503c5e49d139b32e4d85001d98e5c5f3b2f │ ├── 30055b16bcb5ac33019a5c54ead52234b7031cdf656eb95049afef2deec74379 │ ├── 31a904e8bb66687602766299b0c77462f9eedc0673fe651f13356675ea72e0b4 │ ├── 364aa634efb78ef2c33434b108e0fe83b1d23809a61bf231f2db39421bf664d3 │ ├── 38d421857d85ad26359e6ec5e0acc706638f6bb801ea2c17e0e1a5b3e0de6d8f │ ├── 3a8a78a881ac67f8a50fbb8926e18cc91b5e0d39aa56885c2a4f746d25bbe19a │ ├── 3a9f828d5acef78c560530048e3898967174cd15c7d36f7110b599ecdd89fb47 │ ├── 3a9fb8f4d61bee1dffc496e2e091732d4f93c47b4df92df53c1821aca1f470f6 │ ├── 3ec37b35f3542a430e674de28323011e5b53185e24510594ef18b0ff19685e93 │ ├── 402df4155d0c95809d239006a9e0bb7b01728dac25d51dd94abe774193700690 │ ├── 4084cdcd9bc00b56bcf66962d6f05de5cef7816bca82eb98224c8f27fce09121 │ ├── 40989c335af1b23ffcae52f453fb96d5a343d2ec40f6fd93682b993b1c9fcf62 │ ├── 419791318064460de7d8c5da5c75f35848c023f4e354d5e579df2c366e2340fa │ ├── 44fe565b76527beb49ee0d87448343e79c835ae6814a03d320366492c7b0b956 │ ├── 4634339e9ab2678838c136b3f0c4fc6234dfb8776481d30132bea5cbef007146 │ ├── 46bda65124b64e0af1ffa20d11f1c30a9a0148c61f79bfc760174136468654b2 │ ├── 46e4506971b6348ce09c9cd9af62f2f78f7ad18f4e79288ddbd378bfe00d4f70 │ ├── 47baccb1917e893b5519d6e967b47c841abddcafce38d0e92c0e70b301f09209 │ ├── 4e7608ac389d05f02897d0358f3664d2cb5c5348d827ce240bd8265639061061 │ ├── 4e9e86e7a2c7e9f0ef3aa570ca007c1b71ff95bde339c396c3340bb602ad8dce │ ├── 4eded720be99fd3b601de0f0401c5c46234d4231c32487feb273f259dfcbc8df │ ├── 518176382c8bfbe7b0d9e3becc5ff0c593463041b47500a10c7a24aafcadf32b │ ├── 534b1649b5190794976fbc0f79eaf3b393ee486302b4012304a9b8194e579ab7 │ ├── 536ebf977fb25a0a307c8689d4e81810775aaeb689f39d8c4acd6745adc400d0 │ ├── 53c31c279e0a36040444ede86282171894fb121061c5ec07fcd93ddf06a7b76a │ ├── 54472386276871d373863544c9931bfb92c4ad03574b14542d1d091d7c544460 │ ├── 577188c84bd70718d3b7c1b7b01bdb97354d5ab9465d895c18a1efba9771ff14 │ ├── 5797b4a20df4131dfe8ccfe11191c6cc5d5be3f094bd285a4bd9ff2c56c9bd8a │ ├── 5c25220936d9002e75d4594437f7de64ec1edf6a18db0323d397c1bc26720280 │ ├── 5d1708894e903e38be1d82f4ecc7efe2a3ef1c7c4755c2d714c2b0db92edc6c3 │ ├── 601ececdf21f0c0d9cf07d31da13c510273f92b0332875a5261863390c5ea08c │ ├── 608f107a6ee3be7cbb70f900ec4c609d43a7248b9d2194d7ccc73cbf733fef13 │ ├── 60b89e83057e9f4b636aa2976542dc2ffb742a6e135442526a50808908885137 │ ├── 61e7835d25625dc73936d3342451615b3067510fa4f49004fd083423c3a53c09 │ ├── 6210a4889190951adef6e22071e8363a701e8fcd4f753b47897880eeb4a863ef │ ├── 6546d29854a444d88e4940847d2697cd96906ceb7c5dfbe9457154a5e948b8dd │ ├── 67ac0f2050f62bc61691c25e397d9002f945d6adfab03acc1b299888e22e9d37 │ ├── 684d6b7c7ccb7a13f41611bc42ae172b531b36924978ee6987c5883335acc99a │ ├── 6b465bd4c49c1c22e4cde3093d21b019153d2dc4a9a1cdef25f66661a479dd59 │ ├── 6b675b857fefad9dc4141bc1814d38329e67ecd0f17e4271119fe69065264f4e │ ├── 6b6fad45d0efd68727289dba37658b41af7b7a609b5ac18c500136e0b9e786ba │ ├── 6deae9f0900147b5c3b6772a1121a579fcab215029ad1941af6c5041c1d0bb56 │ ├── 6ed2fd9bc2813e98df6995e17bf14274859ce22f5a2e9bf6b429839c1295d1cc │ ├── 74d51107c77db2cbad454be2e40c07a82d26da7bef52399c60b9a21fd60c347e │ ├── 78c9df9f7a10efe67e5a666cf7072ad3730d1e7fd6a39ab4296e1e84c206331f │ ├── 78eade6ded0eddf4d52e67d017258b1701eff5606157a41fc88a5535d5af6ed3 │ ├── 78f98103e1afd0671c3b7d98e7c74b20e911397e59d37bddd0c197c41b0b8ed7 │ ├── 79958066355c53408602c25f23be2b405e77ab05c205df8b709e2fcc1ab15275 │ ├── 7a92ff40540c1226ca897cc70256794e89c416498c22e6605cd4e454a37eb80a │ ├── 7c41c7363191e26bd695cce906da1c8a59eee7e288f2ef79c8ab2b66062f059b │ ├── 7f2db2ac187eb3fabd1c33946026dbac76f50fa47237a44bfa1850b691ef4984 │ ├── 7febbe186a9f9b1ba1ca8da30003618602257f7b1ad6020d6a4125ea0b67a483 │ ├── 80ed75d2a6861c9d1f52691ab90520c4cf657596ee8736edd85b3d65ca234730 │ ├── 846899b83399db2b0d0f21155d19d53b82f04602f3396af515654759b7859157 │ ├── 8509fa695f7299d81e1f1051127d0743061962d11cd58fecf9e3a1663a631a12 │ ├── 87c85583f2a9983d0f4d064eb6644d0c12992908d5db23a8d3b512006f16e449 │ ├── 89f2be9c62e35b78a88a7165d54681c2fade406daa367e406d21f9167f9e95c9 │ ├── 8aa23e342059b2e44a560d3bc0a0356a47ec22e3022b2f33612b67ee5cbe8c8c │ ├── 8b1efc1b0d24347bae5ec1442a495359df60c22c410334f53b88579137934617 │ ├── 8e8096913a48276d77e519c93e037dc4312befb4953e7f0abdf3fd6989628b61 │ ├── 921402a6e4fa68b26750bb7f12300792bf53dbfdc972db95e3b03fb57a9fb668 │ ├── 9297641e25ef4822c2a474a6fe12b645287bdbcf29776312bbb6a7e11b677722 │ ├── 932999c779be85b6d62174d68a34c2399f1e5c509a285d2ada02c41abbd8668b │ ├── 97e17ea6912eb145eafe2e81f28e1b0f2756e500a2e3379e48ed784f43601fb5 │ ├── 994cc6e26358811fae1ffba218abf94c7898600391008a63b7a23b26d4c71f1f │ ├── 999e61e0057290b9cfe37371b41ea396be1eb6453751d943e34f85018a65414d │ ├── 9cb3d3eeba5ce57cfdafc14b0dc44fe34c68073bbff316e25f42915fb0d14c08 │ ├── a08a89303012ad39dd8d86009972393d3b5f2d6225b79d36212476d98f3e32c2 │ ├── a0c3fcb65a0629967b3ebaa4a3989960ce1fa30dd6a42dc728c43f851ebae3b5 │ ├── a141bb3e1e6581b4cce262342025cf22ca6e44945047385e5a4995096698736b │ ├── a4c2e7346e2896b1806ea20b0e07c326c5c33840918e0c128076c70c9d66ec49 │ ├── a561886320cdfd7cea0a53e29b6336996d9c1bca04bfb445942dc511bbe82cb8 │ ├── a752f8bc75470de884553e34aba1e8356ae7232c7c60615bf9a5d57a4535a968 │ ├── a99faba74e40ea2656e3a0aab6cc897b9b2d5718684b7113ccf7f0106d1abe28 │ ├── a9f100e7301c5e0373caf4c8458753f30d9b9ad9ffcb10d1e1d0a213ad8b2e5a │ ├── aa72dbf8e55454fd93014e0badac97fe3fd89dabc9960a7b157b6c56807ef547 │ ├── aac16cda84d303e530bd61ea8b38f9094f192769e84b8edd5c177a14fec1800f │ ├── abf5107bf10ab1e6563812a0a551058a9487ada3b0a428e76f311ac7a20f35f9 │ ├── ac004205c1b050cff366a79f22ad317bcfd3ff8d97af8eda2fb1f2f1120fb1fc │ ├── accfa6d33af22137682f53e393327a7467258fa5d7ceff24882f395ac694f50f │ ├── ae71d662c0da44590a1e4a3018550f74f2743c2aa845211c869dcc3e7a9cd313 │ ├── b26a48eebeb2277a0624e1896b735de830cba89aebc669ba2e1883f3899bb48b │ ├── b28b004f4ff7e805db1ae614bd528182ebe36debddae6332d8e945eb97b2ac47 │ ├── b5be8e3d8c0775056030b9c90b48d589951b4a7d3ad030881e40c5f489acb75b │ ├── b6117b0fdd101a4ef34f2a1b8e735a9858c308d2b36018bae9cf6f7f61e76145 │ ├── b62f6f7dcd1516d2136653d501760bc1507813dcf4e7b4672353761aff213131 │ ├── b634f311e3a13d76c4b94e54897f26427c1f69ffac52f450c27ce9c3b25a9056 │ ├── b7a3b5d824331a2132ac15933b6329e261672ab937c7415006936e8a251c8ced │ ├── b800a1950799c897961193b81095b075d92b8c01727ce5192097befd3c857513 │ ├── b9dde5438931f5b25e07c83f22d0ddca169082c636f932b2f0398df597e7e774 │ ├── bac460c6ce3c5ca92e45e13a0a5d335e8130a37002dd20a4c20e471b434ccd61 │ ├── bb001e9478210c3d93dbf8c2a48434a4b9cefab6b841694805fedb1e358942cc │ ├── c0052d3373d729a1327c0af5baa30f0aa7cc965ebbef3d8a61235c07f61696e7 │ ├── c63d24b8dc82b97fcb837bffcd8deaee99f8d4904fa14174eb46ab3073f1e286 │ ├── c67560ac14d188780faf3f5414aa7d23739c38707c5c9d42e12a7c2e497437a0 │ ├── c6764f47d48be60e6ff89d9b8c04fbae1ed83446b0f8fc451af5a2d9c6f31f28 │ ├── ca15018eb35551aff571a9a5c97930a15ad6e216727b531574e8e97e624968e5 │ ├── cb54aed125cd03336cdc12d650c40eaf496e7780b6e4123bf0c0d134f9eec253 │ ├── cb5c70cfd0a8c55fe2c0bfb57afb2e678fb75775a2a413bf4ab87c37b36cfeac │ ├── cb69ac7c3ed897958be255adce83a26a40f9362e99e5c5d9f26b17ef80bfdd0a │ ├── cc787cd08ecb21f3f723f6d1a2e979e8dc59956cde8f872e6eb3a95b8c998824 │ ├── ccedee6c00016e14787cc03e1311b62266f4bb7919cb5bb1329f73cf2bf5e07a │ ├── cdbcf7cf072fb3dcf0ea43484047927684f61f0b96e12bc6d9ec2a3c2f8ce822 │ ├── ce6ed017cb3cccb7b95577810355d5c09324d4cae562b88a271d40a8452c3ea4 │ ├── cfbfe7bee6558af6c1ead418ff9ff88cf8fad6a8fd8e14c56cb3fda8888108b8 │ ├── d0385029744717bd23ef43ec2549b7082de55f676f17dc7af505a222dce22198 │ ├── d0def7908ea07e848cdeca6a757711f099405ffa67113287114da02280d6fc98 │ ├── d922b17c61ea580cd1adc60dd5d385db7056b3ad7a0697a688f7c831a6c394b4 │ ├── db21ed026968dba58c6e2e60a1a1fbbbd45217904748ec0a30e5e191deef8dd4 │ ├── db3bfef1eed0069001002c243ce790357938e9701a7c45852d75b524a68d0e30 │ ├── db8ea4f269c006ec82bf3b921f96e13b419d32e44418732d024f7049296b384e │ ├── dcd66a7d466e3431916ae25bb773cca1569199733b8be4a92430310e3ecb0eed │ ├── df8877ee3e1f9ea5f7e67c8138a99e87d6e0f3e549e31b39a6ab84212ae6d084 │ ├── e011fbf70660ebcea0e0370b3e1813c9a6f5ee073b6a94dd0e6e0bc192fac121 │ ├── e0c661944b99eae04a4ff5823769f4c40ed0766aac25277be6d322cc513fb8d7 │ ├── e46d93092657081027e793037d11f72ac528de72942f593bbb9b9edc5a86ec13 │ ├── e764164c4d2c7029700c7f43b622880b41c7ed195ebee77238df2ac65066ebd4 │ ├── e7ab50479666c5e49d9df1f4ca259f1051de7b316d6f7818122b55fff457d809 │ ├── e881b7a80ee78c79ab1414641677a03205f5d90f3b3cb498b9a2405015279fb3 │ ├── e96b6dd08106270a8ef3c818f2926fce4de6baba320863c54b28e30c3b8a5e39 │ ├── e9907a24e0140beb6ce385df6ed6fcd95c2044e17d05700d41f9e2085099926b │ ├── ea1f25f04d4eab15600fc9df46385e318eae3543b68968783313424eb92e073d │ ├── ea692d8f059afbd68ffea7105bd473f65b7210684f996b9bfec89c2fa19f6d1d │ ├── ec71004af47e3de67eb3a6402cd0028badd5959e7c320af8b74c31c3e78b0fad │ ├── ed84369d80eacbbafa7dfdab5ebbc882ae3cec75e42bd19697cdc3ed44b1de13 │ ├── ee0add7389e054d037034c15d63821e5276dc8721fca15e2d051dd5a84ed3b03 │ ├── f06f72ddb711caa7e9a404b560427eb436c6eaa70a8efc7e530ad1e5ca832bad │ ├── f0c66d6e8f4c2f57773d3464c0a099a60761175a768aa605c12e0c4c21c93a86 │ ├── f1e84014e4777732f70c23d0a40c4c920b0887d1af94706da96375b0ebec51a3 │ ├── f204549fac6991cc09f8ece7bb5c7b8a8fa06ac9afe47f961dba250030c55900 │ ├── f2cb78c36981809fb5c02036e3b4af52412f54b7a4417f6239b2bcca0ce0ace3 │ ├── f651ad9f356e46deda244cb8538d7e8169db30f932ba21df6bc1dfd3625d01f8 │ └── fcee7f345df8d4880de5de2a5154a6f1be48b186d12f73d61f396b673d5053fd ├── sour │ ├── data │ │ └── menus.cfg │ └── packages │ │ ├── base │ │ └── xmwhub.ogz │ │ └── textures │ │ └── downloading.png ├── split-base.py └── split-quad.py ├── client ├── .gitignore ├── .prettierignore ├── .prettierrc ├── build ├── definitions │ ├── global.d.ts │ └── nipple.d.ts ├── package.json ├── scripts │ └── serve ├── src │ ├── FileDropper.tsx │ ├── Loading.tsx │ ├── MobileControls.tsx │ ├── assets │ │ ├── hook.ts │ │ ├── storage.ts │ │ ├── types.ts │ │ ├── utils.ts │ │ └── worker.ts │ ├── background.png │ ├── config.ts │ ├── discord.ts │ ├── favicon.ico │ ├── game.ts │ ├── index.html │ ├── index.tsx │ ├── logging.ts │ ├── names.ts │ ├── protocol.ts │ ├── static │ │ ├── action.jpg │ │ ├── arrow_bw.jpg │ │ ├── arrow_fw.jpg │ │ ├── blank.png │ │ ├── brush_1c.png │ │ ├── brush_21c.png │ │ ├── brush_3s.png │ │ ├── brush_421c.png │ │ ├── brush_5s.png │ │ ├── brush_7s.png │ │ ├── captaincannon.jpg │ │ ├── captaincannon_blue.jpg │ │ ├── captaincannon_red.jpg │ │ ├── chat.jpg │ │ ├── checkbox_off.jpg │ │ ├── checkbox_on.jpg │ │ ├── chest.jpg │ │ ├── coins.jpg │ │ ├── cube.jpg │ │ ├── exit.jpg │ │ ├── grenade.png │ │ ├── hand.jpg │ │ ├── info.jpg │ │ ├── inky.jpg │ │ ├── inky_blue.jpg │ │ ├── inky_red.jpg │ │ ├── machinegun.png │ │ ├── map.jpg │ │ ├── menu.jpg │ │ ├── mrfixit.jpg │ │ ├── mrfixit_blue.jpg │ │ ├── mrfixit_red.jpg │ │ ├── ogro.jpg │ │ ├── ogro_blue.jpg │ │ ├── ogro_red.jpg │ │ ├── pistol.png │ │ ├── radio_off.jpg │ │ ├── radio_on.jpg │ │ ├── readme.txt │ │ ├── rifle.png │ │ ├── rocket.png │ │ ├── sauer.jpg │ │ ├── saw.png │ │ ├── server.jpg │ │ ├── serverfull.jpg │ │ ├── serverlock.jpg │ │ ├── serverpriv.jpg │ │ ├── serverunk.jpg │ │ ├── shotgun.png │ │ ├── snoutx10k.jpg │ │ ├── snoutx10k_blue.jpg │ │ ├── snoutx10k_red.jpg │ │ ├── spectator.jpg │ │ └── sword.jpg │ ├── types.ts │ ├── unsafe-startup.d.ts │ ├── unsafe-startup.js │ └── utils.ts ├── tsconfig.json └── yarn.lock ├── cmd ├── client │ └── main.go ├── cs │ └── main.go ├── demo │ └── main.go ├── ogz │ └── main.go ├── sour │ ├── http.go │ ├── main.go │ └── serve.go └── sourdump │ └── main.go ├── game ├── .agignore ├── .gitignore ├── README.markdown ├── arbitrary_ws.patch ├── build ├── file_create.patch ├── game │ └── gl-matrix.js ├── js │ ├── api.js │ └── main.js ├── resolve_wasm.patch ├── src │ ├── Makefile │ ├── enet │ │ ├── .gitignore │ │ ├── ChangeLog │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README │ │ ├── autom4te.cache │ │ │ ├── output.0 │ │ │ ├── requests │ │ │ └── traces.0 │ │ ├── callbacks.c │ │ ├── check_cflags.sh │ │ ├── compress.c │ │ ├── host.c │ │ ├── include │ │ │ └── enet │ │ │ │ ├── callbacks.h │ │ │ │ ├── enet.h │ │ │ │ ├── list.h │ │ │ │ ├── protocol.h │ │ │ │ ├── time.h │ │ │ │ ├── types.h │ │ │ │ ├── unix.h │ │ │ │ ├── utility.h │ │ │ │ └── win32.h │ │ ├── list.c │ │ ├── packet.c │ │ ├── peer.c │ │ ├── protocol.c │ │ ├── unix.c │ │ └── win32.c │ ├── engine │ │ ├── 3dgui.cpp │ │ ├── animmodel.h │ │ ├── bih.cpp │ │ ├── bih.h │ │ ├── blend.cpp │ │ ├── blob.cpp │ │ ├── client.cpp │ │ ├── command.cpp │ │ ├── console.cpp │ │ ├── cubeloader.cpp │ │ ├── decal.cpp │ │ ├── depthfx.h │ │ ├── dynlight.cpp │ │ ├── engine.h │ │ ├── explosion.h │ │ ├── glare.cpp │ │ ├── grass.cpp │ │ ├── iqm.h │ │ ├── lensflare.h │ │ ├── lightmap.cpp │ │ ├── lightmap.h │ │ ├── lightning.h │ │ ├── main.cpp │ │ ├── master.cpp │ │ ├── material.cpp │ │ ├── md2.h │ │ ├── md3.h │ │ ├── md5.h │ │ ├── menus.cpp │ │ ├── model.h │ │ ├── movie.cpp │ │ ├── mpr.h │ │ ├── normal.cpp │ │ ├── obj.h │ │ ├── octa.cpp │ │ ├── octa.h │ │ ├── octaedit.cpp │ │ ├── octarender.cpp │ │ ├── pch.cpp │ │ ├── physics.cpp │ │ ├── pvs.cpp │ │ ├── ragdoll.h │ │ ├── rendergl.cpp │ │ ├── rendermodel.cpp │ │ ├── renderparticles.cpp │ │ ├── rendersky.cpp │ │ ├── rendertarget.h │ │ ├── rendertext.cpp │ │ ├── renderva.cpp │ │ ├── server.cpp │ │ ├── serverbrowser.cpp │ │ ├── shader.cpp │ │ ├── shadowmap.cpp │ │ ├── skelmodel.h │ │ ├── smd.h │ │ ├── sound.cpp │ │ ├── textedit.h │ │ ├── texture.cpp │ │ ├── texture.h │ │ ├── vertmodel.h │ │ ├── water.cpp │ │ ├── world.cpp │ │ ├── world.h │ │ └── worldio.cpp │ ├── fpsgame │ │ ├── ai.cpp │ │ ├── ai.h │ │ ├── aiman.h │ │ ├── capture.h │ │ ├── client.cpp │ │ ├── collect.h │ │ ├── ctf.h │ │ ├── entities.cpp │ │ ├── extinfo.h │ │ ├── fps.cpp │ │ ├── game.h │ │ ├── monster.cpp │ │ ├── movable.cpp │ │ ├── pch.cpp │ │ ├── render.cpp │ │ ├── scoreboard.cpp │ │ ├── server.cpp │ │ ├── waypoint.cpp │ │ └── weapon.cpp │ ├── include │ │ ├── SDL.h │ │ ├── SDL_assert.h │ │ ├── SDL_atomic.h │ │ ├── SDL_audio.h │ │ ├── SDL_bits.h │ │ ├── SDL_blendmode.h │ │ ├── SDL_clipboard.h │ │ ├── SDL_config.h │ │ ├── SDL_config.h.cmake │ │ ├── SDL_config.h.in │ │ ├── SDL_config_android.h │ │ ├── SDL_config_iphoneos.h │ │ ├── SDL_config_macosx.h │ │ ├── SDL_config_minimal.h │ │ ├── SDL_config_os2.h │ │ ├── SDL_config_pandora.h │ │ ├── SDL_config_psp.h │ │ ├── SDL_config_win32.h │ │ ├── SDL_config_windows.h │ │ ├── SDL_config_winrt.h │ │ ├── SDL_config_wiz.h │ │ ├── SDL_copying.h │ │ ├── SDL_cpuinfo.h │ │ ├── SDL_egl.h │ │ ├── SDL_endian.h │ │ ├── SDL_error.h │ │ ├── SDL_events.h │ │ ├── SDL_filesystem.h │ │ ├── SDL_gamecontroller.h │ │ ├── SDL_gesture.h │ │ ├── SDL_haptic.h │ │ ├── SDL_hints.h │ │ ├── SDL_image.h │ │ ├── SDL_joystick.h │ │ ├── SDL_keyboard.h │ │ ├── SDL_keycode.h │ │ ├── SDL_loadso.h │ │ ├── SDL_log.h │ │ ├── SDL_main.h │ │ ├── SDL_messagebox.h │ │ ├── SDL_metal.h │ │ ├── SDL_mixer.h │ │ ├── SDL_mouse.h │ │ ├── SDL_mutex.h │ │ ├── SDL_name.h │ │ ├── SDL_opengl.h │ │ ├── SDL_opengl_glext.h │ │ ├── SDL_opengles.h │ │ ├── SDL_opengles2.h │ │ ├── SDL_opengles2_gl2.h │ │ ├── SDL_opengles2_gl2ext.h │ │ ├── SDL_opengles2_gl2platform.h │ │ ├── SDL_opengles2_khrplatform.h │ │ ├── SDL_pixels.h │ │ ├── SDL_platform.h │ │ ├── SDL_power.h │ │ ├── SDL_quit.h │ │ ├── SDL_rect.h │ │ ├── SDL_render.h │ │ ├── SDL_revision.h │ │ ├── SDL_rwops.h │ │ ├── SDL_scancode.h │ │ ├── SDL_sensor.h │ │ ├── SDL_shape.h │ │ ├── SDL_stdinc.h │ │ ├── SDL_surface.h │ │ ├── SDL_system.h │ │ ├── SDL_syswm.h │ │ ├── SDL_thread.h │ │ ├── SDL_timer.h │ │ ├── SDL_touch.h │ │ ├── SDL_types.h │ │ ├── SDL_version.h │ │ ├── SDL_video.h │ │ ├── SDL_vulkan.h │ │ ├── begin_code.h │ │ ├── close_code.h │ │ ├── zconf.h │ │ └── zlib.h │ ├── native │ │ ├── Makefile │ │ ├── engine │ │ │ └── keepalive │ │ ├── fpsgame │ │ │ └── keepalive │ │ └── shared │ │ │ └── keepalive │ ├── readme_source.txt │ ├── shared │ │ ├── command.h │ │ ├── crypto.cpp │ │ ├── cube.h │ │ ├── cube2font.c │ │ ├── ents.h │ │ ├── geom.cpp │ │ ├── geom.h │ │ ├── glemu.cpp │ │ ├── glemu.h │ │ ├── glexts.h │ │ ├── iengine.h │ │ ├── igame.h │ │ ├── pch.cpp │ │ ├── stream.cpp │ │ ├── tools.cpp │ │ ├── tools.h │ │ └── zip.cpp │ └── web │ │ ├── .agignore │ │ ├── engine │ │ └── keepalive │ │ ├── fpsgame │ │ └── keepalive │ │ └── shared │ │ └── keepalive └── websocket_hook.patch ├── gh-assets ├── .gitattributes ├── header.gif └── header.png ├── go.mod ├── go.sum ├── pkg ├── assets │ ├── cache.go │ ├── module.go │ ├── roots.go │ ├── types.go │ └── utils.go ├── chanlock │ ├── LICENSE │ ├── README.md │ ├── module.go │ └── stacktraces.go ├── config │ ├── config_test.go │ ├── default.yaml │ ├── dev.yaml │ ├── module.go │ ├── schema.cue │ └── types.go ├── cs │ ├── command.cpp │ ├── command.h │ ├── cs.go │ ├── cs.swigcxx │ └── wrap.h ├── enet │ ├── LICENSE │ ├── README.md │ ├── disconnect_reasons.go │ ├── enet │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── Makefile.am │ │ ├── Makefile.in │ │ ├── README │ │ ├── aclocal.m4 │ │ ├── callbacks.c │ │ ├── compile │ │ ├── compress.c │ │ ├── config.guess │ │ ├── config.log │ │ ├── config.status │ │ ├── config.sub │ │ ├── configure │ │ ├── configure.ac │ │ ├── depcomp │ │ ├── enet.dsp │ │ ├── enet_dll.cbp │ │ ├── host.c │ │ ├── include │ │ │ └── enet │ │ │ │ ├── callbacks.h │ │ │ │ ├── enet.h │ │ │ │ ├── list.h │ │ │ │ ├── protocol.h │ │ │ │ ├── time.h │ │ │ │ ├── types.h │ │ │ │ ├── unix.h │ │ │ │ ├── utility.h │ │ │ │ └── win32.h │ │ ├── install-sh │ │ ├── libenet.pc │ │ ├── libenet.pc.in │ │ ├── libtool │ │ ├── list.c │ │ ├── missing │ │ ├── packet.c │ │ ├── peer.c │ │ ├── protocol.c │ │ ├── unix.c │ │ └── win32.c │ ├── event.go │ ├── host.go │ ├── packet.go │ ├── peer.go │ └── socket.go ├── game │ ├── colors.go │ ├── commands │ │ ├── command_test.go │ │ └── module.go │ ├── constants │ │ └── module.go │ ├── io │ │ ├── buffer.go │ │ ├── conversion.go │ │ ├── packet.go │ │ ├── sanitize.go │ │ ├── serde.go │ │ └── serde_test.go │ ├── protocol │ │ ├── constants.go │ │ ├── editing.go │ │ ├── intercept.go │ │ ├── io.go │ │ ├── module.go │ │ └── physics.go │ └── variables │ │ └── module.go ├── gameserver │ ├── LICENSE │ ├── README.md │ ├── auth.go │ ├── client.go │ ├── clients.go │ ├── config.go │ ├── game.go │ ├── game │ │ ├── capture.go │ │ ├── clock.go │ │ ├── coop.go │ │ ├── ctf.go │ │ ├── deathmatch.go │ │ ├── flags.go │ │ ├── flags_ctf.go │ │ ├── game_test.go │ │ ├── mode.go │ │ ├── pickups.go │ │ ├── player.go │ │ ├── player_state.go │ │ ├── server.go │ │ ├── team.go │ │ └── team_mode.go │ ├── geom │ │ └── vector.go │ ├── module.go │ ├── net │ │ └── packet │ │ │ └── packet.go │ ├── packet_handling.go │ ├── pausableticker │ │ └── pausable_ticker.go │ ├── protocol │ │ ├── armour │ │ │ └── armour.go │ │ ├── cubecode │ │ │ ├── README.md │ │ │ ├── colors.go │ │ │ ├── conversion.go │ │ │ └── sanitize.go │ │ ├── disconnectreason │ │ │ └── disconnect_reasons.go │ │ ├── entity │ │ │ ├── entities.go │ │ │ └── pickups.go │ │ ├── gamemode │ │ │ └── game_mode.go │ │ ├── mastermode │ │ │ └── master_mode.go │ │ ├── nmc │ │ │ └── network_message_codes.go │ │ ├── packet.go │ │ ├── playerstate │ │ │ └── player_state.go │ │ ├── role │ │ │ └── role.go │ │ ├── sound │ │ │ └── sound.go │ │ ├── version.go │ │ └── weapon │ │ │ └── weapon.go │ ├── relay │ │ ├── publisher.go │ │ └── relay.go │ ├── server_commands.go │ ├── state.go │ └── timer │ │ ├── LICENSE │ │ ├── README.md │ │ └── module.go ├── maps │ ├── api │ │ ├── entities │ │ │ ├── module.go │ │ │ ├── particles.go │ │ │ ├── serde.go │ │ │ └── serde_test.go │ │ └── module.go │ ├── decode.go │ ├── default.textures │ ├── edit.go │ ├── encode.go │ ├── translate.go │ ├── types.go │ └── worldio │ │ ├── blend.cpp │ │ ├── command.h │ │ ├── cube.h │ │ ├── engine.h │ │ ├── entities.cpp │ │ ├── ents.h │ │ ├── game.h │ │ ├── geom.h │ │ ├── iengine.h │ │ ├── igame.h │ │ ├── lightmap.cpp │ │ ├── lightmap.h │ │ ├── octa.cpp │ │ ├── octa.h │ │ ├── octaedit.cpp │ │ ├── pvs.cpp │ │ ├── state.h │ │ ├── texture.h │ │ ├── tools.h │ │ ├── world.cpp │ │ ├── world.h │ │ ├── worldio.cpp │ │ ├── worldio.go │ │ ├── worldio.h │ │ ├── worldio.swigcxx │ │ └── wrap.h ├── min │ ├── commands.go │ ├── index.go │ ├── model.go │ ├── module.go │ └── textures.go ├── mmr │ └── module.go ├── server │ ├── ingress │ │ ├── enet.go │ │ ├── module.go │ │ └── ws.go │ ├── module.go │ ├── servers │ │ ├── gameserver.go │ │ ├── module.go │ │ └── serverinfo.go │ ├── service │ │ ├── api.go │ │ ├── auth.go │ │ ├── commands.go │ │ ├── cs.go │ │ ├── elo.go │ │ ├── events.go │ │ ├── maps.go │ │ ├── matchmaking.go │ │ ├── module.go │ │ ├── purgatory.ogz │ │ ├── sessions.go │ │ └── users.go │ ├── static │ │ ├── .gitignore │ │ └── module.go │ ├── verse │ │ └── spaces.go │ └── watcher │ │ └── module.go ├── utils │ ├── colors.go │ ├── hash.go │ ├── pubsub.go │ └── session.go └── version │ └── module.go └── proxy ├── .gitignore ├── Makefile ├── README.md ├── base64.c ├── build ├── md5.c ├── md5.h ├── sha1.c ├── sha1.h ├── websocket.c ├── websocket.h └── websockify.c /.earthignore: -------------------------------------------------------------------------------- 1 | services/server/CMakeCache.txt 2 | services/server/CMakeFiles/** 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ogz filter=lfs diff=lfs merge=lfs -text 2 | *.wav filter=lfs diff=lfs merge=lfs -text 3 | *.iqm filter=lfs diff=lfs merge=lfs -text 4 | *.dds filter=lfs diff=lfs merge=lfs -text 5 | *.jpg filter=lfs diff=lfs merge=lfs -text 6 | *.png filter=lfs diff=lfs merge=lfs -text 7 | *.ogg filter=lfs diff=lfs merge=lfs -text 8 | *.ico filter=lfs diff=lfs merge=lfs -text 9 | *.textures filter=lfs diff=lfs merge=lfs -text 10 | -------------------------------------------------------------------------------- /.github/goreleaser-release.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022-present Bytebase (Hong Kong) Limited. 2 | # 3 | # Portions of this software are licensed as follows: 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | builds: 23 | - skip: true 24 | changelog: 25 | sort: asc 26 | filters: 27 | exclude: 28 | - "^docs:" 29 | - "^test:" 30 | release: 31 | draft: true 32 | mode: append 33 | extra_files: 34 | - glob: ./sour-build/**/* 35 | - glob: ./sour-build/checksums.txt 36 | name_template: "Release {{.Tag}}" 37 | header: | 38 | # What's Changed 39 | 40 | ## Features 41 | 42 | ## Code Diff 43 | -------------------------------------------------------------------------------- /.github/watch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | path="$1" 6 | shift 1 7 | 8 | cd "$path" 9 | 10 | run_build() { 11 | "$path/build" 12 | } 13 | 14 | run_build 15 | 16 | job_id="" 17 | 18 | repl() { 19 | if ! [ -z "$job_id" ]; then 20 | kill -SIGINT "$job_id" 21 | wait "$job_id" 22 | sleep 1 23 | job_id="" 24 | fi 25 | 26 | if ! run_build; then 27 | echo "Building $path failed." 28 | return 1 29 | fi 30 | 31 | if [ -z "$CONFIG" ]; then 32 | export SOUR_CONFIG="$(cat $SCRIPT_DIR/config/config.json)" 33 | fi 34 | $@ & 35 | result="$?" 36 | job_id="$!" 37 | echo "Ran service with pid=$job_id" 38 | if [ "$result" -gt 0 ]; then 39 | echo "Running $path failed." 40 | job_id="" 41 | return 1 42 | fi 43 | return 0 44 | } 45 | 46 | paths="$path" 47 | 48 | if [ -z "$CONFIG" ]; then 49 | paths+=" $SCRIPT_DIR/config/config.json" 50 | fi 51 | 52 | repl $@ 53 | 54 | while true; do 55 | inotifywait -qr $paths -e MODIFY 56 | repl $@ 57 | done 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /appendonlydir 2 | build/** 3 | *CMakeFiles* 4 | earthly/** 5 | **.o.tmp 6 | /dump.rdb 7 | /state.db 8 | /sour 9 | /sourdump 10 | /sour-build 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Caleb Foust 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/.gitignore: -------------------------------------------------------------------------------- 1 | working/** 2 | output/** 3 | roots/** 4 | __pycache__ 5 | /sourdump 6 | quadropolis 7 | *.tar.gz 8 | cache/** 9 | /dist 10 | -------------------------------------------------------------------------------- /assets/.ignore: -------------------------------------------------------------------------------- 1 | /shims 2 | -------------------------------------------------------------------------------- /assets/archive: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Clones Sauerbraten from SVN and creates an archive of its data/ and packages/ 3 | # directories. 4 | 5 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | 7 | set -e 8 | 9 | cd /tmp 10 | svn checkout svn://svn.code.sf.net/p/sauerbraten/code/ sauerbraten-code 11 | cd sauerbraten-code 12 | svn up -r$1 13 | archive_target="sauerbraten-$(svn info --show-item revision).tar.gz" 14 | tar czvf "$archive_target" data/ packages/ 15 | cp "$archive_target" "$SCRIPT_DIR" 16 | echo "$archive_target" 17 | -------------------------------------------------------------------------------- /assets/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | cd "$SCRIPT_DIR" 6 | 7 | set -e 8 | 9 | if ! pip3 list | grep "cbor2" > /dev/null 2>&1; then 10 | pip3 install -r requirements.txt 11 | fi 12 | 13 | mkdir -p cache 14 | 15 | outdir=${ASSET_OUTPUT_DIR:-output} 16 | 17 | ./setup 18 | 19 | echo "building desktop" 20 | python3 base.py \ 21 | --root https://static.sourga.me/blobs/6481/.index.source \ 22 | --models \ 23 | --textures \ 24 | --outdir $outdir/desktop \ 25 | complex dust2 turbine 26 | 27 | echo "building mobile" 28 | python3 base.py \ 29 | --root https://static.sourga.me/blobs/6481/.index.source \ 30 | --mobile \ 31 | --outdir $outdir/mobile \ 32 | none 33 | -------------------------------------------------------------------------------- /assets/build-base: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | cd "$SCRIPT_DIR" 6 | 7 | set -e 8 | 9 | ./setup 10 | 11 | rm -r output 12 | 13 | short=$(git rev-parse --short HEAD) 14 | 15 | python3 base.py \ 16 | --prefix $short \ 17 | --root https://static.sourga.me/blobs/6481/.index.source \ 18 | --models \ 19 | --textures 20 | 21 | cd output 22 | 23 | docker run -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY --rm -it -v ~/.aws:/root/.aws -v $(pwd):$(pwd) -w $(pwd) amazon/aws-cli s3 sync --region us-west-2 . s3://static.sourga.me/blobs/indices/ 24 | -------------------------------------------------------------------------------- /assets/cbor2.pyi: -------------------------------------------------------------------------------- 1 | def dump(a, b): pass 2 | -------------------------------------------------------------------------------- /assets/ci: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | cd "$SCRIPT_DIR" 6 | 7 | set -e 8 | 9 | if ! pip3 list | grep "cbor2" > /dev/null 2>&1; then 10 | pip3 install -r requirements.txt 11 | fi 12 | 13 | mkdir -p cache 14 | 15 | ./setup 16 | 17 | outdir=${ASSET_OUTPUT_DIR:-output} 18 | 19 | python3 base.py \ 20 | --root https://static.sourga.me/blobs/6481/.index.source \ 21 | --models \ 22 | --download \ 23 | --outdir dist \ 24 | complex dust2 turbine 25 | -------------------------------------------------------------------------------- /assets/dump-source.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from pathlib import Path 3 | import package 4 | import sys 5 | import glob 6 | import json 7 | import cbor2 8 | from os import path 9 | import os 10 | from typing import NamedTuple, Optional, Tuple, List, Dict, Set, Union, Sequence, Iterable, TypeVar 11 | import subprocess 12 | 13 | 14 | if __name__ == "__main__": 15 | parser = argparse.ArgumentParser(description='Dump a source to JSON.') 16 | parser.add_argument('source') 17 | args = parser.parse_args() 18 | 19 | with open(args.source, 'rb') as f: 20 | with open(args.source + '.json', 'w') as g: 21 | g.write(json.dumps(cbor2.load(f), indent=4)) 22 | -------------------------------------------------------------------------------- /assets/requirements.txt: -------------------------------------------------------------------------------- 1 | cbor2==5.4.6 2 | -------------------------------------------------------------------------------- /assets/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | cd "$SCRIPT_DIR" 6 | 7 | set -e 8 | 9 | mkdir -p cache 10 | 11 | if ! pip3 list | grep "cbor2" > /dev/null 2>&1; then 12 | pip3 install -r requirements.txt 13 | fi 14 | 15 | #sauer_archive="sauerbraten-6481.tar.gz" 16 | 17 | #mkdir -p roots/base/ 18 | 19 | #if ! [ -f "roots/base/$sauer_archive" ]; then 20 | #wget "https://static.sourga.me/archives/$sauer_archive" 21 | #mv "$sauer_archive" roots/base/ 22 | #fi 23 | 24 | #if ! [ -f "roots/base/data/default_map_settings.cfg" ]; then 25 | #tar xvf "roots/base/$sauer_archive" -C "roots/base" 26 | #fi 27 | 28 | if ! [ -f "sourdump" ]; then 29 | cd .. 30 | go build -o assets/sourdump cmd/sourdump/main.go 31 | cd assets 32 | fi 33 | -------------------------------------------------------------------------------- /assets/setup-quad: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | sauer_archive="06-01-23-quadropolis.tar.gz" 6 | 7 | mkdir -p quadropolis 8 | 9 | if ! [ -f "quadropolis/nodes.json" ]; then 10 | wget "https://static.sourga.me/archives/$sauer_archive" 11 | tar xvf "$sauer_archive" -C "quadropolis" 12 | fi 13 | 14 | -------------------------------------------------------------------------------- /assets/shims/070c7ab17d183c8142e807312f74976f7462000bd36a28441647f12cd4284cdc: -------------------------------------------------------------------------------- 1 | // Origional Portal Test code by Tentus 2 | // End GUI inspired by DTurbokiller 3 | // Map by KillHour 4 | 5 | setpixelparam 0 4 // detail texture scale 6 | setpixelparam 1 1 // detail texture power 7 | 8 | setshader detailworld 9 | 10 | setpixelparam 1 .65 11 | 12 | texture 0 egyptsoc/block10c.jpg 13 | texture u noctua/stone16.jpg 14 | 15 | texture 0 rorschach/2_floor02.jpg 16 | texture u noctua/plast06.jpg 17 | -------------------------------------------------------------------------------- /assets/shims/0bc7310b445c329ab72488376a5036bf81fa9656227b4a81bb24be8bd4c14311: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/0bc7310b445c329ab72488376a5036bf81fa9656227b4a81bb24be8bd4c14311 -------------------------------------------------------------------------------- /assets/shims/0de22217476089e1ee5c375fe62fd05ca9ea18a2804166e693cf60fc8e550d71: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////// 2 | // 3 | // 4B :: Distraction : by MeatROme 4 | // 5 | ////////////////////////////////////////////////////////////////////////// 6 | loadsky "4b/sky/stars" 1.0 7 | // additional textures 8 | texture 0 "tech1soc/half_grill_wall03b.jpg" 1 9 | texture 0 "than_ind/light03.jpg" 1 10 | texture 0 "4b/ABCD.jpg" 11 | texture 0 "4b/EFGH.jpg" 12 | texture 0 "4b/ABCD.jpg" 4 13 | setshader glowworld 14 | setpixelparam 0 0.4 0.4 1.2 15 | texture 0 "tech1soc/032lig12bb.jpg" 16 | texture g "4b/032lig12bb_glow.jpg" 17 | setshader glowworld 18 | setvertexparam 0 1 1 1 19 | texture 0 "than_ind/light03.jpg" 20 | texture g "4b/light03_g.jpg" 21 | texture 0 "than_ind/light03.jpg" 1 22 | texture g "4b/light03_g.jpg" 1 23 | setshader stdworld 24 | // additional models 25 | mmodel 4b/floppy/gold/silver 26 | mmodel 4b/floppy/gold 27 | -------------------------------------------------------------------------------- /assets/shims/0e10166cefd4240d957859e79f83f837800e99a48ac27734c6ba72df74ff0961: -------------------------------------------------------------------------------- 1 | loadsky "staffy/staffy" 2 | gamespeed 1000 3 | -------------------------------------------------------------------------------- /assets/shims/0e9e769e2e046a7369ccd0c7b37d5d551255f66d39e2ca8d46b61e461e860b80: -------------------------------------------------------------------------------- 1 | loadsky rnr/eclipse 2 | fog 3600 3 | -------------------------------------------------------------------------------- /assets/shims/0f898e2dc43604d84cbd9b256c5da5124844859d76c331945b51b29dc43f1401: -------------------------------------------------------------------------------- 1 | // Room names: 2 | // 3 | // 1. Antechamber 4 | // 2. The Boxes 5 | // 3. The Gates 6 | // 4. The Torch 7 | // 5. The Octagon 8 | // 6. The Infinite Fall 9 | // 7. The Porthole 10 | // 8. The Portal of Revealing 11 | // 9. The Leap of Faith 12 | // 10. The Labyrinth 13 | // 11. The Mirror 14 | // 12. The Gallery 15 | // 13. The Pool 16 | // 14. The Door 17 | // 15. The Lake 18 | // 16. The Bridges 19 | // 17. The End 20 | 21 | // Easter Egg puzzle room names: 22 | // 23 | // The Window 24 | // The Eye 25 | 26 | skybox mayhem/eclipse 27 | yawsky 150 28 | -------------------------------------------------------------------------------- /assets/shims/11498a75b2c35aea1ac33cacaa40cc3aff89a322e5cb1eb779cb75165e087fe7: -------------------------------------------------------------------------------- 1 | // ------------------------ 2 | // by MeatROme 2006-09-16 3 | // ------------------------ 4 | -------------------------------------------------------------------------------- /assets/shims/1410b9704b3527c41e96f4505de11f4b2525e38780418d14ad62bac3057b05b3: -------------------------------------------------------------------------------- 1 | alias money 0 2 | alias armor 0 3 | -------------------------------------------------------------------------------- /assets/shims/1a5a7410827f2c558cae37ee0a9e30b5705a6714341f6203333557d00aeff97f: -------------------------------------------------------------------------------- 1 | loadsky socksky\nightball 2 | -------------------------------------------------------------------------------- /assets/shims/20f72a837babe4a9908757271249f6f021afb582d30b61aa562128648f621254: -------------------------------------------------------------------------------- 1 | //Obidarids By Poum\\ 2 | 3 | //Ambience\\ 4 | loadsky penguins/arid 5 | fog 4000 6 | skylight 0x39302A 7 | -------------------------------------------------------------------------------- /assets/shims/2306c587bd0e037c386327ae632836a532cb9b8d9df965e430e8e8b818f75806: -------------------------------------------------------------------------------- 1 | loadsky "socksky\mars" 2 | 3 | 4 | exec "packages\base\fanatic_quake.cfg" 5 | setshader bumpspecmapparallaxworld 6 | setpixelparam 1 4 4 4 7 | setpixelparam 2 0.02 -0.01 8 | texture 0 gor\GR_GK_001_cc.jpg 9 | texture n gor\GR_GK_001_nm.jpg 10 | texture s gor\GR_GK_001_sc.jpg 11 | 12 | texture 0 gor\ST_GK_011_cc.jpg 13 | texture n gor\ST_GK_011_nm.jpg 14 | texture s gor\ST_GK_011_sc.jpg 15 | 16 | mmodel "makke/moon" 17 | mmodel "makke/earth" 18 | fog 1000024 19 | echo 20 | echo 21 | echo "Ancient Martian Base" 22 | echo "Map made by Conor Kirkpatrick" 23 | 24 | mapsound "kaiser/fx/computer1" 150 1 25 | mapsound "kaiser/fx/hum1" 130 1mapsound "kaiser/fx/hum2" 130 1 26 | mapsound "kaiser/fx/hum3" 230 1 27 | mapsound "kaiser/fx/hum4" 60 1 28 | -------------------------------------------------------------------------------- /assets/shims/238b9d2a8b155854c345e182ed5bb93fde663f38a41991747c4b6976bb1977de: -------------------------------------------------------------------------------- 1 | loadsky "dash/moon" 2 | 3 | 4 | mapsound "ddb/gr.wav" 30 -1 5 | mapsound "ddb/gr.wav" 40 -1 6 | mapsound "ddb/gr.wav" 50 -1 7 | mapsound "ddb/gr.wav" 60 -1 8 | mapsound "ddb/gr.wav" 70 -1 9 | 10 | 11 | -------------------------------------------------------------------------------- /assets/shims/26d24b2c55df45b4228f8b92a0a37fe77f31e20931bf48b0cb43899d161e6619: -------------------------------------------------------------------------------- 1 | // BigBadBase config by MeatROme 2 | // DO NOT modify below this line, that's my stuff :) 3 | loadsky "staffy/staffy" 4 | -------------------------------------------------------------------------------- /assets/shims/2baacd05ea5d29855b6cd8d7983f526b5b7bc430fa1338fc95aa6b81188a86ea: -------------------------------------------------------------------------------- 1 | 2 | loadsky dash/moon 3 | music "fanatic/22.ogg" 4 | -------------------------------------------------------------------------------- /assets/shims/2d4178d6ea809e4ec0e60b62ec20d2f8daa8e447945c8234fda0f53899ec8608: -------------------------------------------------------------------------------- 1 | fog 1000024 2 | -------------------------------------------------------------------------------- /assets/shims/30055b16bcb5ac33019a5c54ead52234b7031cdf656eb95049afef2deec74379: -------------------------------------------------------------------------------- 1 | texture 0 trak5\floor2a.jpg 2 | texscroll 6 0 3 | 4 | texture 0 textures\nieb\metal-door.jpg 5 | texrotate 3 6 | texscale 0.25 7 | texrotate 3 8 | 9 | texture 0 trak5\trim6e.jpg 10 | texrotate 3 11 | texscale 0.5 12 | 13 | texture 0 trak5\trim6e.jpg 14 | texcolor 0 0 0 15 | 16 | setshader bumpenvspecworld 17 | 18 | setshaderparam "specscale" .7 .15 .15 19 | setshaderparam "envscale" .9 .5 .1 20 | texture 0 "textures\nieb\metal-orange.jpg" 0 0 0 .75 21 | texcolor 1 1 0 22 | texture n "argh/flat.png" 23 | texffenv 1 24 | 25 | 26 | setshaderparam "specscale" .7 .15 .15 27 | setshaderparam "envscale" .35 .35 .4 28 | texture 0 "trak5\pipe1c.jpg" 0 0 0 .75 29 | texcolor 0 0 1 30 | texture n "argh/flat.png" 31 | texffenv 1 32 | 33 | 34 | setshaderparam "specscale" .7 .15 .15 35 | setshaderparam "envscale" .5 .1 .1 36 | texture 0 "textures\nieb\concrete-red.jpg" 0 0 0 .75 37 | texcolor 1 0 0 38 | texture n "argh/flat.png" 39 | texffenv 1 40 | 41 | setshaderparam "specscale" .7 .15 .15 42 | setshaderparam "envscale" .7 .7 .7 43 | texture 0 "textures\nieb\garden\base.png" 0 0 0 .75 44 | texcolor 1 1 1 45 | texture n "argh/flat.png" 46 | texffenv 1 47 | 48 | mapmodel 4 12 0 "monster/slith" 49 | mapmodel 4 12 0 "monster/rat" 50 | 51 | mapsound soundsnap/fan 300 -1 52 | mapsound soundsnap/fan 1000 -1 53 | 54 | mapsound ambience/fire_light 300 -1 55 | 56 | mapsound awesund/cg2 200 -1 57 | 58 | mapsound ambience/wind 3000 -1 59 | 60 | mapsound soundtransit/distant_storm 1000 -1 61 | -------------------------------------------------------------------------------- /assets/shims/3a8a78a881ac67f8a50fbb8926e18cc91b5e0d39aa56885c2a4f746d25bbe19a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/3a8a78a881ac67f8a50fbb8926e18cc91b5e0d39aa56885c2a4f746d25bbe19a -------------------------------------------------------------------------------- /assets/shims/3a9f828d5acef78c560530048e3898967174cd15c7d36f7110b599ecdd89fb47: -------------------------------------------------------------------------------- 1 | 2 | fog 3000 3 | texture 0 dg/f_p2_v.jpg 4 | texture 0 dg/mur013.jpg 5 | texture 0 dg/mur109.jpg 6 | texture 0 dg/mot001.jpg 7 | texture 0 dg/mad064.jpg 8 | texture 0 dg/mot190.jpg 9 | texture 0 dg/mot088.jpg 10 | texture 0 golgotha/lava.jpg 11 | texture 0 dg/mur063.jpg 12 | texture 0 dg/mad065.jpg 1 13 | texture 0 dg/mot067.jpg 14 | texture 0 dg/mur088.jpg 15 | texture 0 gor/ST_GK_005_zu_001_cc.jpg 2 16 | texture 0 dg/mur000.jpg 17 | texture 0 dg/mur054.jpg 18 | texture 0 dg/muv030.jpg 19 | texture 0 dg/muv032.jpg 20 | mapmodel 0 0 0 objects/millblade 21 | -------------------------------------------------------------------------------- /assets/shims/3ec37b35f3542a430e674de28323011e5b53185e24510594ef18b0ff19685e93: -------------------------------------------------------------------------------- 1 | //models 2 | mapmodelreset 3 | mmodel "dcp/blade_y/fast" 4 | mmodel "dcp/blade_y/big" 5 | mmodel "crow" 6 | -------------------------------------------------------------------------------- /assets/shims/40989c335af1b23ffcae52f453fb96d5a343d2ec40f6fd93682b993b1c9fcf62: -------------------------------------------------------------------------------- 1 | mapsound "ambience/wind.ogg" 100 2 2 | 3 | loadsky "socksky/nightball" 4 | 5 | 6 | texturereset 7 | setshader stdworld 8 | 9 | texture 0 "ik2k/ik_sky_day_back.jpg" 10 | 11 | texture 0 "textures/ddb/conc1.jpg" 12 | texture n "textures/ddb/conc1_n.jpg" 13 | texture s "textures/ddb/conc1_s.jpg" 14 | 15 | exec "packages/philipk/package.cfg" 16 | exec packages\blikjebier\concrete\package.cfg 17 | exec packages\blikjebier\metal\package.cfg 18 | exec packages/subverse/package.cfg 19 | 20 | 21 | -------------------------------------------------------------------------------- /assets/shims/46e4506971b6348ce09c9cd9af62f2f78f7ad18f4e79288ddbd378bfe00d4f70: -------------------------------------------------------------------------------- 1 | 2 | texture 0 smukulu/s_poolday/blauefliese.jpg 3 | texture 0 smukulu/s_poolday/rotefliese.jpg 4 | texture 0 smukulu/s_poolday/weissefliese.jpg 5 | texture 0 smukulu/s_poolday/weissewand.jpg 6 | -------------------------------------------------------------------------------- /assets/shims/4eded720be99fd3b601de0f0401c5c46234d4231c32487feb273f259dfcbc8df: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////// 2 | // 3 | // 3B :: Ithaqua's Depot : by MeatROme 4 | // 5 | ////////////////////////////////////////////////////////////////////////// 6 | loadsky "dash/moon" 7 | // additional textures 8 | texture 0 "tech1soc/half_grill_wall03b.jpg" 1 9 | texture 0 "than_ind/light03.jpg" 1 10 | texture 0 "4b/inner.jpg" 11 | texture 0 "4b/outer.jpg" 12 | setshader glowworld 13 | setvertexparam 0 1 1 1 14 | texture 0 "than_ind/light03.jpg" 15 | texture g "4b/light03_g.jpg" 16 | texture 0 "than_ind/light03.jpg" 1 17 | texture g "4b/light03_g.jpg" 1 18 | setshader stdworld 19 | // additional models 20 | mmodel 4b/floppy/gold/silver/bronze/patch 21 | // autorun 22 | // music 23 | -------------------------------------------------------------------------------- /assets/shims/518176382c8bfbe7b0d9e3becc5ff0c593463041b47500a10c7a24aafcadf32b: -------------------------------------------------------------------------------- 1 | // MeatROme : Muybridge example of something like a cut-scene 2 | 3 | loadsky staffy/staffy 4 | -------------------------------------------------------------------------------- /assets/shims/534b1649b5190794976fbc0f79eaf3b393ee486302b4012304a9b8194e579ab7: -------------------------------------------------------------------------------- 1 | music "nomusic" 2 | loadsky "dash/moon" 3 | ambient 1 4 | -------------------------------------------------------------------------------- /assets/shims/536ebf977fb25a0a307c8689d4e81810775aaeb689f39d8c4acd6745adc400d0: -------------------------------------------------------------------------------- 1 | texturereset 2 | skybox staffy/staffy 3 | fog 10000 4 | texture 0 textures/sky.png 5 | texture 0 subverse\metal_siding_kinks.jpg 6 | exec packages/trak5/package.cfg 7 | exec packages/pyccna/recruit/recruittex.cfg 8 | exec packages/philipk/package.cfg 9 | texture 0 textures/waterfall.jpg 10 | texscroll 0 -1 11 | texture 0 textures/waterfall.jpg 12 | texscroll 0 1 13 | 14 | mapmodelreset 15 | mmodel "pyccna/fed_door" 16 | mmodel "pyccna/window" 17 | -------------------------------------------------------------------------------- /assets/shims/54472386276871d373863544c9931bfb92c4ad03574b14542d1d091d7c544460: -------------------------------------------------------------------------------- 1 | 2 | loadsky dash/moon 3 | music "fanatic/11.ogg" 4 | -------------------------------------------------------------------------------- /assets/shims/5797b4a20df4131dfe8ccfe11191c6cc5d5be3f094bd285a4bd9ff2c56c9bd8a: -------------------------------------------------------------------------------- 1 | texture 0 "lunaran\hexflr2_d.jpg" 0 0 0 1.5 2 | texture 0 "trak5\pipe1b.jpg" 0 0 0 1.5 3 | texscale 1 4 | texlayer 422 5 | 6 | texture 0 "trak5\pipe1b.jpg" 0 0 0 1.5 7 | texture 0 "tomek\snow7_d.jpg" 0 0 0 1.5 8 | texlayer -1 9 | 10 | 11 | mapsound kaiser\fx\hum6 1000 -1 12 | mapsound awesund/cg2 200 -1 13 | -------------------------------------------------------------------------------- /assets/shims/5d1708894e903e38be1d82f4ecc7efe2a3ef1c7c4755c2d714c2b0db92edc6c3: -------------------------------------------------------------------------------- 1 | 2 | 3 | music fanatic\1.ogg 4 | watercolour 003300 5 | 6 | echo "Push m to scope in and n to scope out" 7 | echo "Push F11 to see the credits" 8 | echo "Enjoy :)" 9 | 10 | -------------------------------------------------------------------------------- /assets/shims/601ececdf21f0c0d9cf07d31da13c510273f92b0332875a5261863390c5ea08c: -------------------------------------------------------------------------------- 1 | // Works in all game modes. It reads 3 z-coordinates of camera (not actual player position) periodically 2 | // and calcs speed and acceleration. 3 | // If speed falls into danger zone ( fatalv <-> 1.25 fatalv ) checking for decceleration is enabled ; once decceleration occurs, player is killed. 4 | 5 | // So any wild movement puts you in wounded state; there mild deccelarations kill. For even more realism secondary health 6 | // could be added. Once it is depleted, player is killed. 7 | 8 | // To prevent unnecessarr bugs use firstperson view and set thirdpersondistance 0. Note that fall speed ( as coded in source of game ) is 9 | // not a function of fall height but but of the time spent falling. 10 | 11 | 12 | // Most of the "bugs" are explained away by noting use of camera position (not actual player position) 13 | // and falling time. 14 | 15 | 16 | 17 | // No more unrealistic falls; unforgiving jumppads. By tweaking fatalv player can become really fragile. 18 | // Real caution needed when playing with this. 19 | 20 | 21 | echo "TERMINAL VELOCITY by Ac" 22 | 23 | thirdpersondistance 0 // otherwise death when reviving if camera is up 24 | -------------------------------------------------------------------------------- /assets/shims/608f107a6ee3be7cbb70f900ec4c609d43a7248b9d2194d7ccc73cbf733fef13: -------------------------------------------------------------------------------- 1 | loadsky "blindabuser/blindasky" 0.5 2 | 3 | mapsound "kaiser/fx/hum5.wav" 220 -1 4 | 5 | -------------------------------------------------------------------------------- /assets/shims/60b89e83057e9f4b636aa2976542dc2ffb742a6e135442526a50808908885137: -------------------------------------------------------------------------------- 1 | music doom/01.mid 2 | -------------------------------------------------------------------------------- /assets/shims/61e7835d25625dc73936d3342451615b3067510fa4f49004fd083423c3a53c09: -------------------------------------------------------------------------------- 1 | loadsky "staffy/staffy" 2 | 3 | level_trigger_1 = [ 4 | echo $COL resetting CFG 5 | echo executing $COL AUTOEXEC 6 | exec meatpak.cfg 7 | exec autoexec.cfg 8 | sleep 1500 [map metl2] 9 | ] 10 | -------------------------------------------------------------------------------- /assets/shims/6546d29854a444d88e4940847d2697cd96906ceb7c5dfbe9457154a5e948b8dd: -------------------------------------------------------------------------------- 1 | loadsky socksky/desert 2 | exec packages/smukulu/package.cfg 3 | -------------------------------------------------------------------------------- /assets/shims/6b465bd4c49c1c22e4cde3093d21b019153d2dc4a9a1cdef25f66661a479dd59: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/6b465bd4c49c1c22e4cde3093d21b019153d2dc4a9a1cdef25f66661a479dd59 -------------------------------------------------------------------------------- /assets/shims/6b6fad45d0efd68727289dba37658b41af7b7a609b5ac18c500136e0b9e786ba: -------------------------------------------------------------------------------- 1 | setshader "causticsworld1" 2 | texture 0 "brushes/square_64_hard.png" 0 0 0 2 3 | 4 | setshader "causticsworld2a" 5 | texture 0 "models/hudguns_old/nebula.jpg" 6 | texture 0 "golgotha/water2.jpg" 7 | texture 0 "dg/floor_lava2.jpg" 8 | 9 | setshader "causticsworld2b" 10 | texture 0 "models/hudguns_old/nebula.jpg" 11 | texture 0 "golgotha/water2.jpg" 12 | texture 0 "dg/floor_lava2.jpg" 13 | 14 | setshader "causticsworld2c" 15 | texture 0 "models/hudguns_old/nebula.jpg" 16 | texture 0 "golgotha/water2.jpg" 17 | texture 0 "dg/floor_lava2.jpg" 18 | 19 | setshader "causticsworld2d" 20 | texture 0 "models/hudguns_old/nebula.jpg" 21 | texture 0 "golgotha/water2.jpg" 22 | texture 0 "dg/floor_lava2.jpg" 23 | 24 | setshader "causticsworld3" 25 | texture 0 "caustics/caust00.png" 26 | texture 0 "brushes/circle_128_soft.png" 0 0 0 2 27 | -------------------------------------------------------------------------------- /assets/shims/6deae9f0900147b5c3b6772a1121a579fcab215029ad1941af6c5041c1d0bb56: -------------------------------------------------------------------------------- 1 | loadsky "dash/moon" 2 | fogcolour 10567 3 | fog 800 4 | -------------------------------------------------------------------------------- /assets/shims/6ed2fd9bc2813e98df6995e17bf14274859ce22f5a2e9bf6b429839c1295d1cc: -------------------------------------------------------------------------------- 1 | texture 0 "tomek\snow7_d.jpg" 0 0 0 1.5 2 | texture 0 "rorschach\256_gate_water02.jpg" 0 0 0 1.5 3 | texlayer 762 4 | 5 | 6 | mapsound ambience/wind 3000 -1 7 | mapsound kaiser\fx\hum4 1000 -1 8 | mapsound kaiser\fx\computer1 100 -1 9 | mapsound awesund\cg1 500 -1 10 | 11 | mapmodelreset 12 | mmodel "makke/moon" 13 | mmodel "makke/planet" 14 | mmodel "vegetation/tree02" 15 | mmodel "mapmodels/sitters/gothic/skelet1" 16 | mmodel "mapmodels/sitters/gothic/skelet2" 17 | mmodel "mapmodels/sitters/gothic/skelet3" 18 | mmodel "mapmodels/nieb/tree_dead" 19 | mmodel "dcp/groundlamp" 20 | 21 | base_1 = "the ^fs^f3Red Tank^fr" 22 | base_2 = "the ^fs^f1Blue Tank^fr" 23 | base_3 = "the ^fs^f1Blue B.T.R^fr" 24 | base_4 = "the ^fs^f1Blue Tundra^fr" 25 | base_5 = "the ^fs^f1Blue Trojan^fr" 26 | base_6 = "the ^fs^f3Red B.T.R^fr" 27 | base_7 = "the ^fs^f3Red Tundra^fr" 28 | base_8 = "the ^fs^f3Red Trojan^fr" 29 | base_9 = "the ^fs^f3Red Sandbag Emplacement^fr" 30 | base_10 = "the ^fs^f6Central Sandbag Emplacement^fr" 31 | base_11 = "the ^fs^f1Blue Sandbag Emplacement^fr" 32 | 33 | -------------------------------------------------------------------------------- /assets/shims/7a92ff40540c1226ca897cc70256794e89c416498c22e6605cd4e454a37eb80a: -------------------------------------------------------------------------------- 1 | // basic setup : 2 | actname = "map4menu" 3 | loadsky "staffy/staffy" 4 | // basic scripting : 5 | // do not edit on copy, change of actname is sufficient. 6 | gamespeed 1000 7 | -------------------------------------------------------------------------------- /assets/shims/7f2db2ac187eb3fabd1c33946026dbac76f50fa47237a44bfa1850b691ef4984: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/7f2db2ac187eb3fabd1c33946026dbac76f50fa47237a44bfa1850b691ef4984 -------------------------------------------------------------------------------- /assets/shims/8509fa695f7299d81e1f1051127d0743061962d11cd58fecf9e3a1663a631a12: -------------------------------------------------------------------------------- 1 | // Round Hell by SheeEttin 2 | 3 | fogcolour 12591120 // 0x8099B3 4 | fog 800 5 | //loadsky skyboxes/evilsky 2 6 | 7 | setshader stdworld 8 | texture 0 rorschach/5_trim02.jpg 0 32 32 9 | 10 | setshader glowworld 11 | texture 0 evil_textures/e7sbrickfloor_jump.jpg 0 0 128 .5 12 | texture g evil_textures/e7sbrickfloor_jump_glow.jpg 0 0 128 5 13 | texture 0 evil_textures/e7sbrickfloor_jump.jpg 0 128 0 .5 14 | texture g evil_textures/e7sbrickfloor_jump_glow.jpg 0 128 0 5 15 | 16 | mapsound sheeettin/whispers.ogg 255 17 | -------------------------------------------------------------------------------- /assets/shims/8aa23e342059b2e44a560d3bc0a0356a47ec22e3022b2f33612b67ee5cbe8c8c: -------------------------------------------------------------------------------- 1 | loadsky "blindabuser/blindasky" 1 2 | -------------------------------------------------------------------------------- /assets/shims/8e8096913a48276d77e519c93e037dc4312befb4953e7f0abdf3fd6989628b61: -------------------------------------------------------------------------------- 1 | // a little piece of a other project 2 | // particle.zoo 3 | // more under : lux.bleib.bunt.de 4 | 5 | 6 | 7 | 8 | // Sound 9 | 10 | mapsound "lux/ground.ogg" 200 5 11 | mapsound "lux/cock.ogg" 250 5 12 | mapsound "lux/cow.ogg" 250 5 13 | mapsound "lux/dogs.ogg" 250 5 14 | mapsound "lux/duck.ogg" 200 5 15 | mapsound "lux/pig.ogg" 250 5 16 | mapsound "lux/wal.ogg" 250 5 17 | mapsound "lux/bubble.ogg" 250 5 18 | mapsound "lux/hi.ogg" 200 5 19 | mapsound "lux/letmeoh.ogg" 250 5 20 | mapsound "lux/answer.ogg" 200 5 21 | 22 | 23 | // entre sound 24 | 25 | music "songs/lux/ground2.ogg" 26 | 27 | 28 | 29 | // Laufschrift 30 | 31 | setshader glowworld 32 | texture 0 "lux/scroll1.jpg" 0 0 200 2 33 | texture g "lux/scroll1.jpg" 34 | texscroll .2 35 | 36 | texture 0 "lux/scroll1.jpg" 4 0 200 2 37 | texture g "lux/scroll1.jpg" 38 | texscroll -.2 39 | 40 | setshader glowworld 41 | texture 0 "lux/rw.jpg" 0 0 200 2 42 | texture g "lux/rw.jpg" 43 | texscroll .2 44 | 45 | texture 0 "lux/rw.jpg" 4 0 200 2 46 | texture g "lux/rw.jpg" 47 | texscroll -.2 48 | 49 | 50 | texture 0 "lux/txt1.jpg" 0 0 200 2 51 | texture g "lux/txt1.jpg" 52 | texscroll .1 53 | 54 | texture 0 "lux/txt1.jpg" 4 0 200 2 55 | texture g "lux/txt1.jpg" 56 | texscroll -.1 57 | 58 | 59 | 60 | // Texturen aufrufen 61 | 62 | setshader stdworld 63 | exec packages/Lux/package.cfg 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /assets/shims/9297641e25ef4822c2a474a6fe12b645287bdbcf29776312bbb6a7e11b677722: -------------------------------------------------------------------------------- 1 | mapmsg "TShagger1a by TOGoS" 2 | 3 | lightprecision 64 4 | 5 | -------------------------------------------------------------------------------- /assets/shims/932999c779be85b6d62174d68a34c2399f1e5c509a285d2ada02c41abbd8668b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/932999c779be85b6d62174d68a34c2399f1e5c509a285d2ada02c41abbd8668b -------------------------------------------------------------------------------- /assets/shims/994cc6e26358811fae1ffba218abf94c7898600391008a63b7a23b26d4c71f1f: -------------------------------------------------------------------------------- 1 | setshader movie 2 | texture 0 "base/pie_2x2.png" 3 | -------------------------------------------------------------------------------- /assets/shims/9cb3d3eeba5ce57cfdafc14b0dc44fe34c68073bbff316e25f42915fb0d14c08: -------------------------------------------------------------------------------- 1 | loadsky "dash/moon" 2 | mode -2 3 | mapmsg "Suburbs by CubeMaster" 4 | -------------------------------------------------------------------------------- /assets/shims/a08a89303012ad39dd8d86009972393d3b5f2d6225b79d36212476d98f3e32c2: -------------------------------------------------------------------------------- 1 | loadsky socksky\desert 2 | watercolour 64 64 32 3 | -------------------------------------------------------------------------------- /assets/shims/a0c3fcb65a0629967b3ebaa4a3989960ce1fa30dd6a42dc728c43f851ebae3b5: -------------------------------------------------------------------------------- 1 | mmodel "pyccna/fss_pyccna/reverse" 2 | mmodel "pyccna/debris" 3 | mmodel "pyccna/debris/gun" 4 | mmodel "pyccna/snoutx10k/assault/gun" 5 | mmodel "pyccna/snoutx10k/gun_relax" 6 | mmodel "pyccna/fed_door" 7 | 8 | gamespeed 55 9 | -------------------------------------------------------------------------------- /assets/shims/a561886320cdfd7cea0a53e29b6336996d9c1bca04bfb445942dc511bbe82cb8: -------------------------------------------------------------------------------- 1 | mmodel meister/silos 2 | mapsound awesund/cg2 200 -1 3 | mapsound kaiser\fx\hum6 2000 -1 4 | mapsound q009\minigun.ogg 200 -1 5 | mapsound q009\pistol2.ogg 200 -1 6 | 7 | -------------------------------------------------------------------------------- /assets/shims/a99faba74e40ea2656e3a0aab6cc897b9b2d5718684b7113ccf7f0106d1abe28: -------------------------------------------------------------------------------- 1 | loadsky socksky/mars 2 | -------------------------------------------------------------------------------- /assets/shims/aa72dbf8e55454fd93014e0badac97fe3fd89dabc9960a7b157b6c56807ef547: -------------------------------------------------------------------------------- 1 | echo "SPATIAL TRIGGER, SILENT TELEPORT AND PROXIMITY ALERT by Ac" 2 | echo "INSTRUCTIONS: write xyz teleport coords and teledests into telepoints var in cfg file" 3 | -------------------------------------------------------------------------------- /assets/shims/aac16cda84d303e530bd61ea8b38f9094f192769e84b8edd5c177a14fec1800f: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Vanaha : by Nutnoze 4 | // 5 | ////////////////////////////////////////////////////////////////////////// 6 | loadsky "socksky/desert" 7 | 8 | -------------------------------------------------------------------------------- /assets/shims/abf5107bf10ab1e6563812a0a551058a9487ada3b0a428e76f311ac7a20f35f9: -------------------------------------------------------------------------------- 1 | //copy from defaults 2 | materialreset 3 | 4 | texture water "golgotha/water2.jpg" // water surface 5 | texture 1 "textures/waterfall.jpg" // waterfall 6 | texture 1 "textures/watern.jpg" // water normals 7 | texture 1 "textures/waterdudv.jpg" // water distortion 8 | 9 | //Using a modified version of the original lava texture as acid (dg/floor_lava2.jpg) 10 | texture lava "hirato/floor_acid2.jpg" 0 0 0 .5 // lava surface 11 | texture 1 "hirato/floor_acid2.jpg" 0 0 0 .5 // falling lava 12 | 13 | //END CP 14 | 15 | loadsky hirato/skybox/purplenebula 2 16 | music "hirato/music/dss/M-Theory 1.ogg"; echo "Now playing. M-Theory 1, by AdmiralConquistador" 17 | exec packages/hirato/dss-sounds.cfg 18 | exec packages/hirato/dss-models.cfg 19 | exec packages/hirato/dss-textures.cfg 20 | lavacolour 40 120 60 21 | lavafog 0 22 | -------------------------------------------------------------------------------- /assets/shims/b28b004f4ff7e805db1ae614bd528182ebe36debddae6332d8e945eb97b2ac47: -------------------------------------------------------------------------------- 1 | // GLITCHRACE CFG by Ac 2 | 3 | echo "WELCOME TO GLITCHRACE" 4 | echo "To get PASSWORD enter /pass NUMBER" 5 | -------------------------------------------------------------------------------- /assets/shims/b5be8e3d8c0775056030b9c90b48d589951b4a7d3ad030881e40c5f489acb75b: -------------------------------------------------------------------------------- 1 | // basic setup : 2 | actname = "map4menu" 3 | loadsky "staffy/staffy" 4 | // basic scripting : 5 | // do not edit on copy, change of actname is sufficient. 6 | gamespeed 1000 7 | -------------------------------------------------------------------------------- /assets/shims/b6117b0fdd101a4ef34f2a1b8e735a9858c308d2b36018bae9cf6f7f61e76145: -------------------------------------------------------------------------------- 1 | texturereset 2 | skybox staffy/staffy 3 | fog 10000 4 | texture 0 textures/sky.png 5 | texture 0 subverse\metal_siding_kinks.jpg 6 | exec packages/trak5/package.cfg 7 | exec packages/pyccna/recruit/recruittex.cfg 8 | exec packages/philipk/package.cfg 9 | texture 0 textures/waterfall.jpg 10 | texscroll 0 -1 11 | texture 0 textures/waterfall.jpg 12 | texscroll 0 1 13 | 14 | mmodel "pyccna/snoutx10k/body" 15 | mmodel "pyccna/snoutx10k/arms" 16 | mmodel "pyccna/snoutx10k/legs" 17 | mmodel "pyccna/snoutx10k/legs_sitting" 18 | mmodel "pyccna/snoutx10k/arms_gun" 19 | mmodel "pyccna/snoutx10k/gun" 20 | mmodel "pyccna/snoutx10k/body_lean" 21 | mmodel "pyccna/snoutx10k/arms_tense" 22 | mmodel "pyccna/snoutx10k/gun_lean" 23 | mmodel "pyccna/snoutx10k/arms_folded" 24 | mmodel "pyccna/snoutx10k/gun_relax" 25 | mmodel "pyccna/snoutx10k/legs_relax" 26 | mmodel "pyccna/snoutx10k/gun_unarmed" 27 | mmodel "pyccna/snoutx10k/arms_lean" 28 | mmodel "pyccna/snoutx10k/m390/m390_arms" 29 | mmodel "pyccna/snoutx10k/m390/m390_unarmed" 30 | mmodel "pyccna/snoutx10k/svd/svd_arms" 31 | mmodel "pyccna/snoutx10k/svd/svd_unarmed" 32 | mmodel "pyccna/snoutx10k/pistol" 33 | mmodel "pyccna/snoutx10k/mg36/mg36_arms" 34 | mmodel "pyccna/snoutx10k/mg36/mg36_unarmed" 35 | mmodel "pyccna/snoutx10k/fsr1/fsr1_arms" 36 | mmodel "pyccna/snoutx10k/fsr1/fsr1_unarmed" 37 | mmodel "pyccna/snowevergreen" 38 | mmodel "pyccna/fed_door" 39 | mmodel "pyccna/snoutx10k/sergeant" 40 | mmodel "pyccna/snoutx10k/sergeant/head" 41 | mmodel "pyccna/window" 42 | 43 | -------------------------------------------------------------------------------- /assets/shims/b62f6f7dcd1516d2136653d501760bc1507813dcf4e7b4672353761aff213131: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/b62f6f7dcd1516d2136653d501760bc1507813dcf4e7b4672353761aff213131 -------------------------------------------------------------------------------- /assets/shims/b7a3b5d824331a2132ac15933b6329e261672ab937c7415006936e8a251c8ced: -------------------------------------------------------------------------------- 1 | 2 | loadsky dash/moon 3 | music "fanatic/16.ogg" 4 | -------------------------------------------------------------------------------- /assets/shims/b800a1950799c897961193b81095b075d92b8c01727ce5192097befd3c857513: -------------------------------------------------------------------------------- 1 | mapmodelreset 2 | 3 | mapmodel -1 -1 0 "doors/door_01" 4 | mapmodel -1 -1 0 "doors/door_02" 5 | mapmodel -1 -1 0 "doors/door_03" 6 | 7 | mapmodel 0 0 0 "switch1" 8 | mapmodel 0 0 0 "switch2" 9 | mapmodel 0 0 0 "carrot" 10 | -------------------------------------------------------------------------------- /assets/shims/bac460c6ce3c5ca92e45e13a0a5d335e8130a37002dd20a4c20e471b434ccd61: -------------------------------------------------------------------------------- 1 | echo Map By Satan'sCry - Satan'sCryDM1-SCdm3 2 | -------------------------------------------------------------------------------- /assets/shims/bb001e9478210c3d93dbf8c2a48434a4b9cefab6b841694805fedb1e358942cc: -------------------------------------------------------------------------------- 1 | texture 0 "Foliage/greening01.jpg" 2 | texture 0 "Foliage/greening02.jpg" 3 | texture 0 "Foliage/greening03.jpg" 4 | texture 0 "Foliage/greening04.jpg" 5 | texture 0 "Foliage/resyeling.jpg" 6 | texture 0 "Foliage/redding.jpg" 7 | 8 | 9 | 10 | registersound Foliage/Best_Cardinal_Bird_Lazy 11 | registersound Foliage/Eaglet_Bird_2 12 | registersound Foliage/dove-Mike_Koenig-1208819046 13 | registersound Foliage/Falcon-Mark_Mattingly-169493032 14 | registersound Foliage/18_Waterfall_(00s000ms_01m02s581ms) 15 | 16 | 17 | 18 | mapsound Foliage/Best_Cardinal_Bird_Lazy 100 -1 19 | mapsound Foliage/Eaglet_Bird_2 100 -1 20 | mapsound Foliage/dove-Mike_Koenig-1208819046 100 -1 21 | mapsound Foliage/Falcon-Mark_Mattingly-169493032 100 -1 22 | mapsound Foliage/18_Waterfall_(00s000ms_01m02s581ms) 100 -1 -------------------------------------------------------------------------------- /assets/shims/c0052d3373d729a1327c0af5baa30f0aa7cc965ebbef3d8a61235c07f61696e7: -------------------------------------------------------------------------------- 1 | loadsky skyboxes\b 2 | exec packages\blikjebier\snow\package.cfg 3 | alias thundersound (registersound) 4 | thundersound = (+ $thundersound 1) 5 | registersound "viruz\t1" 6 | registersound "viruz\t2" 7 | registersound "viruz\t3" 8 | registersound "viruz\t4" 9 | registersound "viruz\t5" 10 | registersound "viruz\t6" 11 | registersound "viruz\t7" 12 | registersound "viruz\rain" 13 | alias gammabackup $gamma; 14 | 15 | texture 0 viruz\russiamap2.jpg 16 | 17 | fog 1000; 18 | fogcolour 0; 19 | -------------------------------------------------------------------------------- /assets/shims/c63d24b8dc82b97fcb837bffcd8deaee99f8d4904fa14174eb46ab3073f1e286: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/c63d24b8dc82b97fcb837bffcd8deaee99f8d4904fa14174eb46ab3073f1e286 -------------------------------------------------------------------------------- /assets/shims/c67560ac14d188780faf3f5414aa7d23739c38707c5c9d42e12a7c2e497437a0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/c67560ac14d188780faf3f5414aa7d23739c38707c5c9d42e12a7c2e497437a0 -------------------------------------------------------------------------------- /assets/shims/c6764f47d48be60e6ff89d9b8c04fbae1ed83446b0f8fc451af5a2d9c6f31f28: -------------------------------------------------------------------------------- 1 | mmodel mapmodels/khorne/trees/aspen1 2 | mmodel mapmodels/khorne/trees/aspen2 3 | mmodel mapmodels/khorne/trees/pine1 4 | mmodel mapmodels/khorne/trees/pine2 5 | mmodel mapmodels/khorne/trees/pine3 6 | mmodel mapmodels/khorne/trees/pine4 7 | mmodel mapmodels/khorne/plants/fern1 8 | mmodel mapmodels/khorne/plants/flax 9 | mmodel mapmodels/khorne/plants/flaxblue 10 | mmodel mapmodels/khorne/plants/flaxyellow 11 | mmodel mapmodels/khorne/plants/foxglove 12 | mmodel mapmodels/khorne/plants/ladymantle 13 | mmodel mapmodels/khorne/plants/heatherpink 14 | mmodel mapmodels/khorne/plants/fern2 15 | mmodel mapmodels/khorne/plants/fern3 16 | mmodel mapmodels/khorne/plants/fern4 17 | mmodel mapmodels/khorne/plants/fern5 18 | mmodel mapmodels/khorne/plants/fern6 19 | texture 0 "aard/aardograss_1.jpg" 20 | autograss "grass/khornegrass.png" 21 | grassscale 1 22 | -------------------------------------------------------------------------------- /assets/shims/cb69ac7c3ed897958be255adce83a26a40f9362e99e5c5d9f26b17ef80bfdd0a: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////// 2 | // 3 | // 4B :: Escher Space : by MeatROme 4 | // 5 | ////////////////////////////////////////////////////////////////////////// 6 | // actually waiting for png-starfield skybox 7 | loadsky "4b/sky/stars" -1.24 8 | fogcolour 0x000000 9 | fog 6250 10 | // additional textures :: 11 | texture 0 "tech1soc/half_grill_wall03b.jpg" 1 12 | setshader glowworld 13 | setvertexparam 0 1 1 1 14 | texture 0 "than_ind/light03.jpg" 15 | texture g "4b/light03_g.jpg" 16 | texture 0 "than_ind/light03.jpg" 1 17 | texture g "4b/light03_g.jpg" 1 18 | setshader glowworld 19 | setpixelparam 0 0.4 0.4 1.2 20 | texture 0 "tech1soc/032lig12bb.jpg" 21 | texture g "4b/032lig12bb_glow.jpg" 22 | setshader stdworld 23 | // music 24 | // mission objective 25 | // spring-release or earlier : this doesn't work :( 26 | // fix trigger 23,24 first! 27 | // This is the last map, ... what then you ask? 28 | // DMSP! Choose the level here! 29 | -------------------------------------------------------------------------------- /assets/shims/cdbcf7cf072fb3dcf0ea43484047927684f61f0b96e12bc6d9ec2a3c2f8ce822: -------------------------------------------------------------------------------- 1 | // Portal Tests 1-4 by Tentus 2 | // End GUI inspired by DTurbokiller 3 | 4 | //show beginning GUI at start of map 5 | showgui t_portal 6 | 7 | mapsound "ambience/hum.ogg" 8 | 9 | lightprecision 48 10 | ambient 16 11 | -------------------------------------------------------------------------------- /assets/shims/ce6ed017cb3cccb7b95577810355d5c09324d4cae562b88a271d40a8452c3ea4: -------------------------------------------------------------------------------- 1 | loadsky "meister/uzze" 2 | 3 | fog 3500 4 | 5 | cloudlayer skyboxes/clouds03 6 | cloudscrollx 0.003 7 | 8 | minimapheight 414 9 | 10 | alias base_1 "West Base" 11 | alias base_2 "West Bridge" 12 | alias base_3 "Coutrtyard Tunnel" 13 | alias base_4 "Subway" 14 | alias base_5 "East Bridge" 15 | alias base_6 "East Base" 16 | 17 | -------------------------------------------------------------------------------- /assets/shims/d0def7908ea07e848cdeca6a757711f099405ffa67113287114da02280d6fc98: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////// 2 | // 3 | // 4B :: Defense Quarters : by MeatROme 4 | // 5 | ////////////////////////////////////////////////////////////////////////// 6 | // actually waiting for PNG starfiled skybox 7 | loadsky "4b/sky/stars" -0.84 8 | // additional textures 9 | texture 0 "tech1soc/half_grill_wall03b.jpg" 1 10 | texture 0 "than_ind/light03.jpg" 1 11 | setshader glowworld 12 | setpixelparam 0 0.4 0.4 1.2 13 | texture 0 "tech1soc/032lig12bb.jpg" 14 | texture g "4b/032lig12bb_glow.jpg" 15 | setshader glowworld 16 | setvertexparam 0 1 1 1 17 | texture 0 "than_ind/light03.jpg" 18 | texture g "4b/light03_g.jpg" 19 | texture 0 "than_ind/light03.jpg" 1 20 | texture g "4b/light03_g.jpg" 1 21 | setshader stdworld 22 | // additional sounds 23 | mapsound "kaiser/fx/computer1" 120 24 | // additional models 25 | mmodel 4b/floppy/gold/silver/bronze 26 | // intro_message? 27 | -------------------------------------------------------------------------------- /assets/shims/d922b17c61ea580cd1adc60dd5d385db7056b3ad7a0697a688f7c831a6c394b4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/d922b17c61ea580cd1adc60dd5d385db7056b3ad7a0697a688f7c831a6c394b4 -------------------------------------------------------------------------------- /assets/shims/db21ed026968dba58c6e2e60a1a1fbbbd45217904748ec0a30e5e191deef8dd4: -------------------------------------------------------------------------------- 1 | 2 | loadsky dash/moon 3 | -------------------------------------------------------------------------------- /assets/shims/dcd66a7d466e3431916ae25bb773cca1569199733b8be4a92430310e3ecb0eed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/dcd66a7d466e3431916ae25bb773cca1569199733b8be4a92430310e3ecb0eed -------------------------------------------------------------------------------- /assets/shims/e0c661944b99eae04a4ff5823769f4c40ed0766aac25277be6d322cc513fb8d7: -------------------------------------------------------------------------------- 1 | mapsound kaiser\fx\hum6 1000 -1 2 | -------------------------------------------------------------------------------- /assets/shims/e764164c4d2c7029700c7f43b622880b41c7ed195ebee77238df2ac65066ebd4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/e764164c4d2c7029700c7f43b622880b41c7ed195ebee77238df2ac65066ebd4 -------------------------------------------------------------------------------- /assets/shims/e7ab50479666c5e49d9df1f4ca259f1051de7b316d6f7818122b55fff457d809: -------------------------------------------------------------------------------- 1 | music hirato/sounds/deep-space-station/syna-max/alarm_of_d00m.ogg 2 | 3 | setshader envworld 4 | 5 | setpixelparam 0 .15 .15 .15 6 | 7 | texture 0 "hirato/textures/nexuiz/defaultmetal.jpg" 0 0 0 .5 8 | -------------------------------------------------------------------------------- /assets/shims/e881b7a80ee78c79ab1414641677a03205f5d90f3b3cb498b9a2405015279fb3: -------------------------------------------------------------------------------- 1 | mapmodel 4 12 0 "monster/slith" 2 | mapmodel 4 12 0 "monster/bauul" 3 | mapmodel 4 12 0 "monster/knight" 4 | mapmodel 5 12 0 "monster/rat" 5 | mapmodel 6 12 0 "monster/spider" 6 | mapmodel 7 12 0 "monster/rhino" 7 | mmodel "mapmodels/justice/poster/1" 8 | mmodel "mapmodels/justice/poster/2" 9 | mmodel "mapmodels/justice/poster/3 10 | 11 | mapsound soundsnap/fan 1000 -1 12 | mapsound kaiser\fx\hum4 2000 0 13 | mapsound kaiser\fx\hum6 1000 -1 14 | 15 | texture 0 "textures\nieb\rock01.jpg" 0 0 0 1.5 16 | texlayer 602 17 | 18 | setshader bumpenvspecworld 19 | 20 | setshaderparam "specscale" .7 .15 .15 21 | setshaderparam "envscale" .35 .35 .4 22 | texture 0 "trak5\pipe1c.jpg" 0 0 0 .75 23 | texcolor 0 0 1 24 | texture n "argh/flat.png" 25 | texffenv 1 26 | 27 | texture 0 "textures\nieb\garden\base.png" 0 0 0 .75 28 | texcolor 0 0 0 29 | 30 | -------------------------------------------------------------------------------- /assets/shims/ea692d8f059afbd68ffea7105bd473f65b7210684f996b9bfec89c2fa19f6d1d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/ea692d8f059afbd68ffea7105bd473f65b7210684f996b9bfec89c2fa19f6d1d -------------------------------------------------------------------------------- /assets/shims/ec71004af47e3de67eb3a6402cd0028badd5959e7c320af8b74c31c3e78b0fad: -------------------------------------------------------------------------------- 1 | mapmsg "DuoCross - Twice the Flags, Twice the Fun! - By Mmeaninglez" 2 | 3 | texturereset 4 | 5 | setshader stdworld 6 | 7 | texture 0 "textures/sky.png" 8 | texture 0 "textures/default.png" 9 | 10 | texture 0 "aard/aardograss_1.jpg" 11 | autograss "textures/grass_aard.png" 12 | texture 0 "ik2k/ik_floor_brick128a.jpg" 13 | texture 0 "ik2k/ik_floor_wood128b.jpg" 14 | texture 0 "ik2k/ik_ground_cobbles128.jpg" 15 | texture 0 "ik2k/ik_brick_3216d.jpg" 16 | texture 0 "ik2k/ik_brick_6464c.jpg" 17 | 18 | exec "packages/dg/package.cfg" 19 | exec "packages/ik2k/package.cfg" 20 | exec "packages/ikbase/package.cfg" 21 | 22 | texture 0 "aard/aardfdry256_1.jpg" 23 | texture 0 "aard/aardmbr16_2.jpg" 24 | texture 0 "aard/aardmmet32_1.jpg" 25 | texture 0 "schwenz/dt_tile_check.01.jpg" 26 | 27 | exec "packages/subverse/package.cfg" 28 | exec "packages/g_pack/package.cfg" 29 | 30 | exec packages/gor/package.cfg 31 | exec packages/aftas/package.cfg 32 | exec packages/mitaman/package.cfg 33 | exec packages/g_pack/package2.cfg 34 | 35 | //Misc textures 36 | setshader stdworld 37 | texture 0 "textures/nieb/rock01.jpg" 38 | setshader bumpspecmapworld 39 | setshaderparam "specscale" 0.25 0.25 0.25 40 | texture 0 "ikbase/specialbrick.jpg" 41 | texture n "ikbase/specialbrick_normal.jpg" 42 | -------------------------------------------------------------------------------- /assets/shims/ed84369d80eacbbafa7dfdab5ebbc882ae3cec75e42bd19697cdc3ed44b1de13: -------------------------------------------------------------------------------- 1 | loadsky "socksky/mars" 2 | 3 | music "nomusic.ogg" 4 | -------------------------------------------------------------------------------- /assets/shims/f2cb78c36981809fb5c02036e3b4af52412f54b7a4417f6239b2bcca0ce0ace3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/assets/shims/f2cb78c36981809fb5c02036e3b4af52412f54b7a4417f6239b2bcca0ce0ace3 -------------------------------------------------------------------------------- /assets/sour/packages/base/xmwhub.ogz: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0268bb9b328571f453587d70294fa2699eecd1af053f1479ee802f76a423635b 3 | size 1326074 4 | -------------------------------------------------------------------------------- /assets/sour/packages/textures/downloading.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:376cee0ac874c6724071d93834bac51b2d3550b22cfb4ce0e1175b738d6c5dbf 3 | size 12992 4 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .parcel-cache 4 | index.js* 5 | -------------------------------------------------------------------------------- /client/.prettierignore: -------------------------------------------------------------------------------- 1 | sites/backseat/src/components/Renderer/os-asm.js 2 | dist 3 | node_modules 4 | -------------------------------------------------------------------------------- /client/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /client/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | cd "$SCRIPT_DIR" 6 | yarn install 7 | 8 | yarn serve 9 | -------------------------------------------------------------------------------- /client/definitions/nipple.d.ts: -------------------------------------------------------------------------------- 1 | import * as nipplejs from 'nipplejs' 2 | 3 | declare module 'nipplejs' { 4 | export class FixedJoystickManager { 5 | create(options?: JoystickManagerOptions): JoystickManager 6 | 7 | on( 8 | type: JoystickManagerEventTypes | JoystickManagerEventTypes[], 9 | handler: (evt: EventData, data: Joystick) => void 10 | ): void 11 | off( 12 | type: JoystickManagerEventTypes | JoystickManagerEventTypes[], 13 | handler: (evt: EventData, data: Joystick) => void 14 | ): void 15 | get(identifier: number): Joystick 16 | destroy(): void 17 | } 18 | 19 | export function create(options: JoystickManagerOptions): FixedJoystickManager; 20 | } 21 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "1.0.0", 4 | "description": "The \"join game\" page for sour.", 5 | "main": "index.js", 6 | "author": "cfoust@sqweebloid.com", 7 | "license": "MIT", 8 | "scripts": { 9 | "serve": "./scripts/serve", 10 | "serve:site": "yarn run parcel watch --target package -p 1239", 11 | "build": "yarn run parcel build --target default" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "^18.7.4", 15 | "@types/ramda": "0.27.44", 16 | "@types/react": "17.0.18", 17 | "@types/react-dom": "17.0.9", 18 | "parcel": "2.7.0", 19 | "process": "^0.11.10" 20 | }, 21 | "dependencies": { 22 | "@chakra-ui/react": "1.6.6", 23 | "@emotion/react": "11", 24 | "@emotion/styled": "11", 25 | "cbor-js": "0.1.0", 26 | "detect-browser": "5.3.0", 27 | "framer-motion": "4", 28 | "idb": "7.0.2", 29 | "nipplejs": "0.10.0", 30 | "ramda": "0.27.1", 31 | "react": "17.0.2", 32 | "react-dom": "17.0.2", 33 | "react-resize-detector": "6.7.6", 34 | "typescript": "4.3.5" 35 | }, 36 | "browserslist": "last 5 Chrome versions", 37 | "targets": { 38 | "default": { 39 | "source": "./src/index.tsx", 40 | "context": "browser", 41 | "distDir": "./dist" 42 | }, 43 | "package": { 44 | "source": "./src/index.tsx", 45 | "context": "browser", 46 | "distDir": "../pkg/server/static/site" 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /client/scripts/serve: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | DIST_DIR="$SCRIPT_DIR/../dist" 7 | SRC_DIR="$SCRIPT_DIR/../src" 8 | 9 | mkdir -p "$DIST_DIR" 10 | 11 | # Ensures that a symlink exists from $2 to $1. 12 | ensure_link() { 13 | if [ ! -L "$2" ] || [ ! "$(readlink $2)" -ef "$1" ]; then 14 | rm -rf "$2" 15 | ln -s "$1" "$2" 16 | fi 17 | } 18 | 19 | SITE_DIR="$SCRIPT_DIR/../../pkg/server/static/site" 20 | mkdir -p "$SITE_DIR" 21 | 22 | cd "$SCRIPT_DIR/../" 23 | 24 | cp "$SRC_DIR/index.html" "$SITE_DIR/index.html" 25 | cp "$SRC_DIR/favicon.ico" "$SITE_DIR/favicon.ico" 26 | cp "$SRC_DIR/background.png" "$SITE_DIR/background.png" 27 | cp -r "$SRC_DIR/../../game/dist/game" "$SITE_DIR" 28 | yarn serve:site 29 | -------------------------------------------------------------------------------- /client/src/Loading.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { Flex, VStack, HStack, Heading, Progress } from '@chakra-ui/react' 4 | 5 | import type { GameState, DownloadingState } from './types' 6 | import { GameStateType, DownloadingType } from './types' 7 | 8 | type Props = { 9 | state: GameState 10 | } 11 | 12 | function Downloading(props: { state: DownloadingState }) { 13 | const { 14 | state: { text, progress }, 15 | } = props 16 | 17 | return ( 18 | 19 | 20 | {text} 21 | 22 | 29 | 30 | ) 31 | } 32 | 33 | export default function StatusOverlay(props: Props) { 34 | const { state } = props 35 | return ( 36 | 37 | 38 | {state.type === GameStateType.PageLoading && ( 39 | Initializing... 40 | )} 41 | {state.type === GameStateType.Downloading && ( 42 | 43 | )} 44 | {state.type === GameStateType.Running && ( 45 | Waiting for game to start... 46 | )} 47 | {state.type === GameStateType.MapChange && ( 48 | Loading map {state.map}... 49 | )} 50 | {state.type === GameStateType.GameError && ( 51 | There was an unknown error with the game. 52 | )} 53 | 54 | 55 | ) 56 | } 57 | -------------------------------------------------------------------------------- /client/src/assets/storage.ts: -------------------------------------------------------------------------------- 1 | import type { DBSchema, IDBPDatabase } from 'idb' 2 | import { openDB } from 'idb' 3 | 4 | interface BundleDB extends DBSchema { 5 | blobs: { 6 | key: string 7 | value: ArrayBuffer 8 | } 9 | } 10 | 11 | async function initDB(): Promise> { 12 | return await openDB('sour-blobs', 1, { 13 | upgrade(db) { 14 | db.createObjectStore('blobs') 15 | }, 16 | }) 17 | } 18 | 19 | export async function haveBlob( 20 | target: string 21 | ): Promise { 22 | const db = await initDB() 23 | const keys = await db.getAllKeys('blobs') 24 | return keys.includes(target) 25 | } 26 | 27 | export async function getBlob( 28 | target: string 29 | ): Promise> { 30 | const db = await initDB() 31 | const bundle = await db.get('blobs', target) 32 | if (bundle == null) return null 33 | return bundle 34 | } 35 | 36 | export async function saveBlob( 37 | target: string, 38 | buffer: ArrayBuffer 39 | ) { 40 | const db = await initDB() 41 | await db.put('blobs', buffer, target) 42 | } 43 | -------------------------------------------------------------------------------- /client/src/assets/utils.ts: -------------------------------------------------------------------------------- 1 | import type { GameMod } from './types' 2 | 3 | const DEFAULT_IMAGE = 'data/logo_1024.png' 4 | export function getModImage(mod: GameMod): string { 5 | const { id, image } = mod 6 | if (image == null) return DEFAULT_IMAGE 7 | return `packages/textures/images/${image}` 8 | } 9 | -------------------------------------------------------------------------------- /client/src/background.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a1ed6bcfb6a6361b3795b48ef82bf6a4498011d28a723387de1e661bcaa3b8f2 3 | size 137106 4 | -------------------------------------------------------------------------------- /client/src/config.ts: -------------------------------------------------------------------------------- 1 | import * as R from 'ramda' 2 | 3 | import { BROWSER } from './utils' 4 | 5 | export type Configuration = { 6 | assets: string[] 7 | servers: string[] 8 | proxy: string 9 | menuOptions: string 10 | } 11 | 12 | export let CONFIG: Configuration = { 13 | assets: [], 14 | servers: [], 15 | proxy: '', 16 | menuOptions: '', 17 | } 18 | 19 | const REPLACED = { 20 | ORIGIN: '#origin', 21 | HOST: '#host', 22 | PROTOCOL: '#protocol', 23 | } 24 | 25 | function fillHost(url: string): string { 26 | return url 27 | .replace(REPLACED.ORIGIN, window.location.origin) 28 | .replace(REPLACED.HOST, window.location.host) 29 | .replace(REPLACED.PROTOCOL, window.location.protocol) 30 | } 31 | 32 | function fillAssetHost(url: string): string { 33 | const newHost = fillHost(url) 34 | 35 | // Don't cache asset sources pointing to this host 36 | if (url.includes(REPLACED.HOST) || url.includes(REPLACED.ORIGIN)) { 37 | return `!${newHost}` 38 | } 39 | 40 | return newHost 41 | } 42 | 43 | function getInjected(): Maybe { 44 | try { 45 | const injected = INJECTED_SOUR_CONFIG 46 | // This will never run if INJECTED_SOUR_CONFIG is not defined 47 | return injected 48 | } catch (e) { 49 | return null 50 | } 51 | } 52 | 53 | function init() { 54 | const config = getInjected() 55 | if (config != null) { 56 | CONFIG = config 57 | } else { 58 | const configStr = process.env.SOUR_CONFIG 59 | if (configStr == null) { 60 | new Error('no configuration provided') 61 | return 62 | } 63 | 64 | CONFIG = JSON.parse(configStr) 65 | } 66 | 67 | CONFIG.assets = R.chain((v): string[] => { 68 | if (v.startsWith('mobile:')) { 69 | return BROWSER.isMobile ? [fillAssetHost(v.slice(7))] : [] 70 | } 71 | if (v.startsWith('desktop:')) { 72 | return !BROWSER.isMobile ? [fillAssetHost(v.slice(8))] : [] 73 | } 74 | return [fillAssetHost(v)] 75 | }, CONFIG.assets) 76 | CONFIG.servers = R.map((v) => fillHost(v), CONFIG.servers) 77 | CONFIG.proxy = fillHost(CONFIG.proxy) 78 | } 79 | 80 | init() 81 | -------------------------------------------------------------------------------- /client/src/favicon.ico: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d23f8166836d3291e234645ab5106da6e82e70a37866623779d252572733f0d4 3 | size 15406 4 | -------------------------------------------------------------------------------- /client/src/logging.ts: -------------------------------------------------------------------------------- 1 | export enum LogLevel { 2 | Info = 1 << 0, 3 | Warn = 1 << 1, 4 | Err = 1 << 2, 5 | Debug = 1 << 3, 6 | Init = 1 << 4, 7 | Echo = 1 << 5, 8 | Chat = 1 << 8, 9 | TeamChat = 1 << 9, 10 | Gameinfo = 1 << 10, 11 | FragSelf = 1 << 11, 12 | FragOther = 1 << 12, 13 | Teamkill = 1 << 13, 14 | } 15 | 16 | export enum Color { 17 | Green = '\f0', // player talk 18 | Blue = '\f1', // "echo" command 19 | Yellow = '\f2', // gameplay messages 20 | Red = '\f3', // important errors 21 | Gray = '\f4', 22 | Magenta = '\f5', 23 | Orange = '\f6', 24 | White = '\f7', 25 | 26 | Save = '\fs', 27 | Restore = '\fr', 28 | } 29 | 30 | const wrap = (s: string, color: Color): string => 31 | `${Color.Save}${color}${s}${Color.Restore}` 32 | 33 | export const colors = { 34 | green: (s: string): string => wrap(s, Color.Green), 35 | blue: (s: string): string => wrap(s, Color.Blue), 36 | yellow: (s: string): string => wrap(s, Color.Yellow), 37 | red: (s: string): string => wrap(s, Color.Red), 38 | gray: (s: string): string => wrap(s, Color.Gray), 39 | magenta: (s: string): string => wrap(s, Color.Magenta), 40 | orange: (s: string): string => wrap(s, Color.Orange), 41 | white: (s: string): string => wrap(s, Color.White), 42 | success: (s: string): string => colors.green(s), 43 | fail: (s: string): string => colors.orange(s), 44 | error: (s: string): string => colors.red(s), 45 | } 46 | 47 | export const sour = (message: string) => `${colors.yellow('sour')} ${message}` 48 | export const info = (message: string) => 49 | BananaBread.conoutf(LogLevel.Info, sour(message)) 50 | export const chat = (message: string) => 51 | BananaBread.conoutf(LogLevel.Chat, message) 52 | export const success = (message: string) => 53 | BananaBread.conoutf(LogLevel.Info, sour(colors.success(message))) 54 | export const warn = (message: string) => 55 | BananaBread.conoutf(LogLevel.Warn, sour(colors.fail(message))) 56 | export const error = (message: string) => 57 | BananaBread.conoutf(LogLevel.Err, sour(colors.error(message))) 58 | export const vanillaError = (message: string) => 59 | BananaBread.conoutf(LogLevel.Err, message) 60 | -------------------------------------------------------------------------------- /client/src/static/action.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:15c03584e947e5edb466a63fdcde8ffdb155f0c436043179e924fad2e81b3972 3 | size 12238 4 | -------------------------------------------------------------------------------- /client/src/static/arrow_bw.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d937fa35888692bbe402cee26ca305f3a6a7623a16bdeca51e1f1e2509573ba2 3 | size 28526 4 | -------------------------------------------------------------------------------- /client/src/static/arrow_fw.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5f75c687661d2d07802683fc9790897f210992e88507ef3147c08d890741c4a3 3 | size 28609 4 | -------------------------------------------------------------------------------- /client/src/static/blank.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d263f7bd972fd64f338df8df2e002abef21112ef0b8c242fbc1f97ed5157d210 3 | size 159 4 | -------------------------------------------------------------------------------- /client/src/static/brush_1c.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d27cf8a5f2ac2524509e7521a389bbe4017eb93e635040d8d0828dc4a041137d 3 | size 249 4 | -------------------------------------------------------------------------------- /client/src/static/brush_21c.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1a094503d2b7df1ff78299151d5ac5fecffa8af9b90b82ac303e5265d028eaed 3 | size 496 4 | -------------------------------------------------------------------------------- /client/src/static/brush_3s.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:213194aed6f3a395614bfa8aa41b3e0f6c8b3574755aa31e4d3051e99cbc8f76 3 | size 282 4 | -------------------------------------------------------------------------------- /client/src/static/brush_421c.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:011fca8862a6ce803ad25ed9aa66dcf5b22364728a5ab991f164258e9fd80598 3 | size 688 4 | -------------------------------------------------------------------------------- /client/src/static/brush_5s.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a1f5ecdc69cd952cbe7d5a8b765b881237fe5fef56904c51123c0ad603904a46 3 | size 350 4 | -------------------------------------------------------------------------------- /client/src/static/brush_7s.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:13851cad24acbc8023abd3987e69755df433618bd65f1d9f21ae0ec251adef32 3 | size 202 4 | -------------------------------------------------------------------------------- /client/src/static/captaincannon.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:84d1936fb092423066e03e9e6a5da16eac9e32eb453e737d55e900530583302f 3 | size 10490 4 | -------------------------------------------------------------------------------- /client/src/static/captaincannon_blue.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4b0fd055684d756015acf721f89a9cd586ce6c77cfc65822fd84af3dec389f77 3 | size 9291 4 | -------------------------------------------------------------------------------- /client/src/static/captaincannon_red.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:54029867757f2e7a72728025913c8640442004fd976046f9e5187c75e4d00d05 3 | size 9879 4 | -------------------------------------------------------------------------------- /client/src/static/chat.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:03c02a8464630305ae491111584f0211fa471349edff7da59fdda36456e6b075 3 | size 1869 4 | -------------------------------------------------------------------------------- /client/src/static/checkbox_off.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f5c8277c2b3ca591455b8b168f56b81483aa87af190de7f71e71dd3c9ac11a2d 3 | size 11147 4 | -------------------------------------------------------------------------------- /client/src/static/checkbox_on.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:724aaf673a4c898a13b87bdacf3e5a825182964c8ba1b89feb7f7ef7227d0636 3 | size 12187 4 | -------------------------------------------------------------------------------- /client/src/static/chest.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:156123076fa5986afac1d7b1c3bae3339e13dd375d9ce14ad6a93c10a4d35642 3 | size 1848 4 | -------------------------------------------------------------------------------- /client/src/static/coins.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:58144680c18bcd14b64b8925db98bd4c7a489ef8e1c3b0d5895253fb35f04b9f 3 | size 2209 4 | -------------------------------------------------------------------------------- /client/src/static/cube.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:51a0cb381b7a047808c6fdb5596ba1b5c1b001a8c8d617c0e147eae7eee71314 3 | size 7314 4 | -------------------------------------------------------------------------------- /client/src/static/exit.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b6dcfbcae2594e4b243c07db0362eb0701e7d654812892fa4d9bb87f80d6a3cc 3 | size 13148 4 | -------------------------------------------------------------------------------- /client/src/static/grenade.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:da6fa976b7cbbf965b2c6f509ee51e66ce917539227cb37444061a8b20bf6e61 3 | size 10449 4 | -------------------------------------------------------------------------------- /client/src/static/hand.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:229a344a307e9860a1967611abe801c76d1b57d3c48348638365e1db7b5ad6e9 3 | size 1660 4 | -------------------------------------------------------------------------------- /client/src/static/info.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4818aaf61db690ba93237a84307d8756ddb765cad210a920cf6d6a55582e05d6 3 | size 13567 4 | -------------------------------------------------------------------------------- /client/src/static/inky.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:212b50d57caefdba1d955082173aa51a243755b11649bd6fdd96bf44031f4e92 3 | size 8707 4 | -------------------------------------------------------------------------------- /client/src/static/inky_blue.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bb8c30dac45eabac04c290a0efc5aec026278239a5128cb8f9e9e3e440d537de 3 | size 9577 4 | -------------------------------------------------------------------------------- /client/src/static/inky_red.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:63ab24cb7fb68b549672442b929f24cb7a0af054b43dfabab4f1f41fb9cebef9 3 | size 9519 4 | -------------------------------------------------------------------------------- /client/src/static/machinegun.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:30b4f421723adb2e36359e587bf8b6d4da77d35d08f80268f3a556618562f9dd 3 | size 9991 4 | -------------------------------------------------------------------------------- /client/src/static/map.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:77c1dd1a5ff111762d3ebfaebd4825753bb51bd3a79358c622f620de2135acd5 3 | size 21465 4 | -------------------------------------------------------------------------------- /client/src/static/menu.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f11eb11f7e2512db6522dba3ce5979f75638b90cc647a484f3558d323c9d7ebb 3 | size 12032 4 | -------------------------------------------------------------------------------- /client/src/static/mrfixit.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ddd0546f66693c250fcfa259a9076ad55a6e95d6fc50eeb9afb06f3e621f113e 3 | size 8365 4 | -------------------------------------------------------------------------------- /client/src/static/mrfixit_blue.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:63eea83086541c1270a83cbd36f5df2ceb2a3da1006afe9a53e3854f0ff71ee3 3 | size 9804 4 | -------------------------------------------------------------------------------- /client/src/static/mrfixit_red.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5bffdd23e527ccc71edd0da95df9b7df8482530cf97d7076273d3e4acb344fd9 3 | size 8832 4 | -------------------------------------------------------------------------------- /client/src/static/ogro.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9cc5761d93842baa2e6dbed43ef2b12a7051a651b69b39b371d23d71084fee1c 3 | size 8882 4 | -------------------------------------------------------------------------------- /client/src/static/ogro_blue.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:476b3a7c1b59cc76e8045b63cba1d3c236c911b786e29b2037fb98ed3af98c91 3 | size 9121 4 | -------------------------------------------------------------------------------- /client/src/static/ogro_red.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8c1d22d40f58d13a112c1ba1a81e289647b3c1e6e73b38c428a6e978ec3483f5 3 | size 8897 4 | -------------------------------------------------------------------------------- /client/src/static/pistol.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1a734fdf9cbb8a6e963c87e5d934c9dfe825d94a548b49a1492b71a4287ff218 3 | size 11094 4 | -------------------------------------------------------------------------------- /client/src/static/radio_off.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8984e195d36cbd8d9c48dae1e45f2b099c37c8366fe7042e2f1147d0cabeaa2e 3 | size 12166 4 | -------------------------------------------------------------------------------- /client/src/static/radio_on.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c985a99f0f4ad9c0b820e5f622ffcfe68d98022d523f5c9cca7e876c23892a32 3 | size 12662 4 | -------------------------------------------------------------------------------- /client/src/static/readme.txt: -------------------------------------------------------------------------------- 1 | action.jpg 2 | checkbox_off.jpg 3 | checkbox_on.jpg 4 | exit.jpg 5 | info.jpg 6 | menu.jpg 7 | ogro.jpg 8 | radio_off.jpg 9 | radio_on.jpg 10 | 11 | (c) 2006-2007 Markus "makkE" Bekel 12 | ALL RIGHTS RESERVED 13 | 14 | ------------------------------------ 15 | 16 | serverfull.jpg 17 | server.jpg 18 | serverlock.jpg 19 | serverpriv.jpg 20 | serverunk.jpg 21 | 22 | CC-BY-SA, Joshua "verbalshadow" Blocher 23 | 24 | -------------------------------------------------------------------------------- /client/src/static/rifle.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bef27038f4442a5b8221b40ce0ef3b0d9a205bd97218f4838d901394bbc2443a 3 | size 10270 4 | -------------------------------------------------------------------------------- /client/src/static/rocket.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:64d6fb9c72a365dcfb544ebac3e57dde29e4861c6122bb010d812380bfe6e37f 3 | size 10291 4 | -------------------------------------------------------------------------------- /client/src/static/sauer.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d55ed2cc53f950c45e17148302497422d57fc353e3abeccfc036893a1f137fe2 3 | size 6317 4 | -------------------------------------------------------------------------------- /client/src/static/saw.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8840515839fce3589385371887415bf5a6d08de45657ebe8ed8abe4ea161ba2d 3 | size 10992 4 | -------------------------------------------------------------------------------- /client/src/static/server.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f6ad36e8d797b2219d3d3d040e7d926bd1c10cd77fe9c84e17f2bc4c5e25da5a 3 | size 5506 4 | -------------------------------------------------------------------------------- /client/src/static/serverfull.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:782250456288ad2908236215a3ea5e311db6f5adfa3bea20a311384cfc2f9a10 3 | size 7326 4 | -------------------------------------------------------------------------------- /client/src/static/serverlock.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:34308d09fcd1263b278131bad6d8fb5aed8bca4157dedf9483fa95aeacb112d3 3 | size 6759 4 | -------------------------------------------------------------------------------- /client/src/static/serverpriv.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9c120be276615607cab6ce54b4b01a85bed1597eaa4cc3ea50af7d49feb3c0f0 3 | size 7238 4 | -------------------------------------------------------------------------------- /client/src/static/serverunk.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b84d9d1f870457c0984335eafc326f34876b1da5e7acfb8d86212ab368aeb712 3 | size 7891 4 | -------------------------------------------------------------------------------- /client/src/static/shotgun.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7c86937a8e307ba9fdce66f665a53d9d3210234601a543922fbf48f0c8124bc3 3 | size 11238 4 | -------------------------------------------------------------------------------- /client/src/static/snoutx10k.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9039945717c9425c08c39b7b70a23234e53e8e47b1383e49c4fe364a15d27600 3 | size 8936 4 | -------------------------------------------------------------------------------- /client/src/static/snoutx10k_blue.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:af1cd571a40b8bbd338dae55b54bc85fd0000b7c2d59f179a0134dc16fc82f11 3 | size 9171 4 | -------------------------------------------------------------------------------- /client/src/static/snoutx10k_red.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5e3d331def28a0a44acb44d51b8d58c2ff4c059aad4977ad3251ab0988d6a255 3 | size 9295 4 | -------------------------------------------------------------------------------- /client/src/static/spectator.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d7e18443d43fc1b7e3e3ec55ee1bb48e126ef00c96a59b093b0b7bd761b9e3eb 3 | size 5650 4 | -------------------------------------------------------------------------------- /client/src/static/sword.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:aa493a169da6c5b686c96fadc7b0ff59471e352a0e99a9b194743a9aab472864 3 | size 1538 4 | -------------------------------------------------------------------------------- /client/src/types.ts: -------------------------------------------------------------------------------- 1 | export enum GameStateType { 2 | PageLoading, 3 | // Waiting for files to download 4 | Downloading, 5 | // When we're starting a map transition 6 | MapChange, 7 | // The game is starting up 8 | Running, 9 | // At the main menu 10 | Ready, 11 | GameError, 12 | } 13 | 14 | export type PageLoadingState = { 15 | type: GameStateType.PageLoading 16 | } 17 | 18 | export enum DownloadingType { 19 | Map, 20 | Mod, 21 | Index, 22 | } 23 | 24 | export type DownloadState = { 25 | downloadedBytes: number 26 | totalBytes: number 27 | } 28 | 29 | export type DownloadingState = { 30 | type: GameStateType.Downloading 31 | text: string 32 | progress: number 33 | } 34 | 35 | export type MapChangeState = { 36 | type: GameStateType.MapChange 37 | map: string 38 | } 39 | 40 | export type RunningState = { 41 | type: GameStateType.Running 42 | } 43 | 44 | export type ReadyState = { 45 | type: GameStateType.Ready 46 | } 47 | 48 | export type ErrorState = { 49 | type: GameStateType.GameError 50 | } 51 | 52 | export type GameState = 53 | | PageLoadingState 54 | | DownloadingState 55 | | MapChangeState 56 | | RunningState 57 | | ReadyState 58 | | ErrorState 59 | 60 | export enum WeaponType { 61 | Saw, 62 | Shotgun, 63 | Chaingun, 64 | Rocket, 65 | Rifle, 66 | Grenade, 67 | Pistol, 68 | } 69 | 70 | export type PlayerState = { 71 | health: number, 72 | maxHealth: number, 73 | weapon: WeaponType 74 | ammo: Record 75 | } 76 | -------------------------------------------------------------------------------- /client/src/unsafe-startup.d.ts: -------------------------------------------------------------------------------- 1 | declare function start(): void; 2 | export default start; 3 | -------------------------------------------------------------------------------- /client/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { detect } from 'detect-browser' 2 | 3 | export type PromiseSet = { 4 | promise: Promise 5 | resolve: (value: T) => void 6 | reject: (reason?: Error) => void 7 | } 8 | 9 | // Break up a promise into its resolve and reject functions for ease of use. 10 | export function breakPromise(): PromiseSet { 11 | let resolve: (value: T) => void = () => {} 12 | let reject: (reason?: Error) => void = () => {} 13 | const promise = new Promise((_resolve, _reject) => { 14 | resolve = _resolve 15 | reject = _reject 16 | }) 17 | 18 | return { 19 | promise, 20 | resolve, 21 | reject, 22 | } 23 | } 24 | 25 | function isiOS(): boolean { 26 | if (/iPad|iPhone|iPod/.test(navigator.platform)) { 27 | return true 28 | } else { 29 | return ( 30 | navigator.maxTouchPoints != null && 31 | navigator.maxTouchPoints > 2 && 32 | /MacIntel/.test(navigator.platform) 33 | ) 34 | } 35 | } 36 | 37 | function isiPad(): boolean { 38 | return ( 39 | navigator.maxTouchPoints != null && 40 | navigator.maxTouchPoints > 2 && 41 | /MacIntel/.test(navigator.platform) 42 | ) 43 | } 44 | 45 | export function getBrowser(): { 46 | isFirefox: boolean 47 | isSafari: boolean 48 | isMobile: boolean 49 | } { 50 | const result = detect() 51 | 52 | return { 53 | isFirefox: result?.name === 'firefox', 54 | isSafari: result?.name === 'safari' || result?.os === 'iOS', 55 | isMobile: 56 | result?.os === 'iOS' || 57 | result?.os === 'Android OS' || 58 | isiOS() || 59 | isiPad(), 60 | } 61 | } 62 | 63 | export const BROWSER = getBrowser() 64 | -------------------------------------------------------------------------------- /cmd/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "time" 7 | 8 | "github.com/cfoust/sour/pkg/enet" 9 | 10 | "github.com/rs/zerolog" 11 | "github.com/rs/zerolog/log" 12 | ) 13 | 14 | func main() { 15 | log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}) 16 | 17 | host, err := enet.NewConnectHost("localhost", 28785) 18 | if err != nil { 19 | log.Error().Err(err) 20 | return 21 | } 22 | 23 | ctx := context.Background() 24 | events := host.Service() 25 | outer: 26 | for { 27 | select { 28 | case <-ctx.Done(): 29 | break outer 30 | case event := <-events: 31 | log.Info().Msgf("event %v", event) 32 | if event.Type == enet.EventTypeReceive { 33 | log.Info().Msgf("packet %d", len(event.Packet.Data)) 34 | 35 | } 36 | } 37 | } 38 | 39 | host.Shutdown() 40 | } 41 | -------------------------------------------------------------------------------- /cmd/cs/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/cfoust/sour/pkg/cs" 5 | "log" 6 | ) 7 | 8 | func Test(a int) { 9 | log.Printf("%d", a) 10 | } 11 | 12 | func MdlName() string { 13 | return "mdl" 14 | } 15 | 16 | func main() { 17 | vm := cs.NewVM() 18 | 19 | vm.AddCommand("test", Test) 20 | vm.AddCommand("mdlname", MdlName) 21 | vm.Run(` 22 | echo (mdlname) 23 | echo ok 24 | `) 25 | } 26 | -------------------------------------------------------------------------------- /cmd/demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "compress/gzip" 5 | "flag" 6 | "io" 7 | "log" 8 | "os" 9 | "time" 10 | 11 | I "github.com/cfoust/sour/pkg/game/io" 12 | P "github.com/cfoust/sour/pkg/game/protocol" 13 | 14 | "github.com/rs/zerolog" 15 | Z "github.com/rs/zerolog/log" 16 | ) 17 | 18 | type DemoHeader struct { 19 | Magic [16]byte 20 | Version int32 21 | Protocol int32 22 | } 23 | 24 | type SectionHeader struct { 25 | From bool 26 | Millis int32 27 | Channel int32 28 | Length int32 29 | } 30 | 31 | func main() { 32 | Z.Logger = Z.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}) 33 | 34 | flag.Parse() 35 | args := flag.Args() 36 | 37 | if len(args) != 1 { 38 | Z.Fatal().Msg("You must provide only a single argument.") 39 | } 40 | 41 | file, err := os.Open(args[0]) 42 | 43 | if err != nil { 44 | Z.Fatal().Err(err).Msg("could not open demo") 45 | } 46 | 47 | gz, err := gzip.NewReader(file) 48 | 49 | if err != nil { 50 | Z.Fatal().Err(err).Msg("could not unzip demo") 51 | } 52 | 53 | defer file.Close() 54 | defer gz.Close() 55 | 56 | buffer, err := io.ReadAll(gz) 57 | 58 | p := I.Buffer(buffer) 59 | 60 | section := SectionHeader{} 61 | for { 62 | if len(p) == 0 { 63 | return 64 | } 65 | p.Get(§ion) 66 | 67 | bytes, _ := p.GetBytes(int(section.Length)) 68 | messages, err := P.Decode(bytes, true) 69 | if err != nil { 70 | Z.Error().Err(err).Msg("failed to parse messages") 71 | continue 72 | } 73 | 74 | sender := "->" 75 | if !section.From { 76 | sender = "<-" 77 | } 78 | 79 | for _, message := range messages { 80 | log.Printf( 81 | "%s |%8d| %s %+v", 82 | sender, 83 | section.Millis, 84 | message.Type().String(), 85 | message, 86 | ) 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /cmd/ogz/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "os" 7 | "time" 8 | 9 | "github.com/cfoust/sour/pkg/maps" 10 | "github.com/cfoust/sour/pkg/maps/api" 11 | 12 | "github.com/rs/zerolog" 13 | "github.com/rs/zerolog/log" 14 | ) 15 | 16 | func Dump(filename string) error { 17 | gameMap, err := maps.FromFile(filename) 18 | if err != nil { 19 | return err 20 | } 21 | 22 | apiMap, err := gameMap.ToAPI() 23 | if err != nil { 24 | return err 25 | } 26 | 27 | data, err := json.Marshal(apiMap) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | os.Stdout.Write(data) 33 | 34 | decoded := api.New() 35 | err = json.Unmarshal(data, &decoded) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | //log.Info().Msgf("%+v", decoded) 41 | 42 | //for _, entity := range decoded.Entities { 43 | //log.Info().Msgf("%+v", entity.Info) 44 | //} 45 | 46 | return nil 47 | } 48 | 49 | func main() { 50 | log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}) 51 | 52 | dumpCmd := flag.NewFlagSet("dump", flag.ExitOnError) 53 | 54 | flag.Parse() 55 | args := flag.Args() 56 | 57 | if len(args) == 0 { 58 | log.Fatal().Msg("You must provide at least one argument.") 59 | } 60 | 61 | switch args[0] { 62 | case "dump": 63 | dumpCmd.Parse(args[1:]) 64 | args := dumpCmd.Args() 65 | if len(args) != 1 { 66 | log.Fatal().Msg("You must provide only a single argument.") 67 | } 68 | err := Dump(args[0]) 69 | if err != nil { 70 | log.Fatal().Err(err).Msg("could not dump map") 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /cmd/sour/http.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | ) 7 | 8 | // SkipIndex is an http.Handler that disables the browser cache for .source 9 | // files. 10 | func SkipIndex(h http.Handler) http.Handler { 11 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 12 | // Set cache-control to none if url contains ".source" 13 | if strings.Contains(r.URL.Path, ".source") { 14 | w.Header().Set("Cache-Control", "no-store") 15 | } 16 | 17 | h.ServeHTTP(w, r) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /game/.agignore: -------------------------------------------------------------------------------- 1 | packages 2 | -------------------------------------------------------------------------------- /game/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.gch 3 | src/native/fpsgame/*.h 4 | src/native/engine/*.h 5 | src/native/shared/*.h 6 | src/native/fpsgame/*.cpp 7 | src/native/engine/*.cpp 8 | src/native/shared/*.cpp 9 | src/native/enet/ 10 | src/web/fpsgame/*.h 11 | src/web/engine/*.h 12 | src/web/shared/*.h 13 | src/web/fpsgame/*.cpp 14 | src/web/engine/*.cpp 15 | src/web/shared/*.cpp 16 | src/web/enet/ 17 | *~ 18 | *.BAK 19 | client*.html 20 | init.cfg 21 | config.cfg 22 | restore.cfg 23 | servers.cfg 24 | *.diff 25 | *.crn 26 | 27 | dist/** 28 | sauerbraten.js 29 | sauerbraten.js.orig 30 | sauerbraten.wasm 31 | src/web/client.bc 32 | -------------------------------------------------------------------------------- /game/README.markdown: -------------------------------------------------------------------------------- 1 | 2 | Cube 2/Sauerbraten 3 | ------------------ 4 | 5 | This directory contains Sauerbraten. 6 | 7 | -------------------------------------------------------------------------------- /game/arbitrary_ws.patch: -------------------------------------------------------------------------------- 1 | --- sauerbraten.js.orig 2022-12-09 22:23:59.583211327 +0000 2 | +++ sauerbraten.js 2022-12-09 22:24:58.935157723 +0000 3 | @@ -3864,7 +3864,7 @@ 4 | } else { 5 | WebSocketConstructor = WebSocket; 6 | } 7 | - ws = new WebSocketConstructor(url, opts); 8 | + ws = Module["socket"](addr, port) 9 | ws.binaryType = "arraybuffer"; 10 | } catch (e) { 11 | throw new FS.ErrnoError(23); 12 | -------------------------------------------------------------------------------- /game/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | cd "$SCRIPT_DIR/../" 6 | 7 | set -e 8 | 9 | cd "$SCRIPT_DIR/src" 10 | 11 | # When you restart the container, this is not there 12 | if ! [ -f "$EMSDK/upstream/emscripten/cache/ports/zlib.2.11.zip" ]; then 13 | emmake make clean 14 | fi 15 | 16 | emmake make client -j8 17 | cd "$SCRIPT_DIR" 18 | 19 | OUTPUT_DIR=${GAME_OUTPUT_DIR:-dist/game} 20 | mkdir -p "$OUTPUT_DIR" 21 | # Need to get rid of some unseemly behavior 22 | patch sauerbraten.js file_create.patch 23 | patch sauerbraten.js arbitrary_ws.patch 24 | patch sauerbraten.js resolve_wasm.patch 25 | cp -r js/api.js sauerbraten.* "$OUTPUT_DIR" 26 | -------------------------------------------------------------------------------- /game/file_create.patch: -------------------------------------------------------------------------------- 1 | 3369c3369,3373 2 | < FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); 3 | --- 4 | > try { 5 | > FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); 6 | > } catch (err) { 7 | > if (!(err instanceof FS.ErrnoError)) throw err; 8 | > } 9 | -------------------------------------------------------------------------------- /game/resolve_wasm.patch: -------------------------------------------------------------------------------- 1 | --- sauerbraten.js.orig 2023-02-03 14:16:11.758471728 +0000 2 | +++ sauerbraten.js 2023-02-03 17:07:14.989280578 +0000 3 | @@ -631,6 +631,7 @@ 4 | wasmTable = Module["asm"]["Qg"]; 5 | addOnInit(Module["asm"]["Pg"]); 6 | removeRunDependency("wasm-instantiate"); 7 | + WASM_PROMISE_RESOLVE() 8 | } 9 | addRunDependency("wasm-instantiate"); 10 | function receiveInstantiationResult(result) { 11 | -------------------------------------------------------------------------------- /game/src/enet/.gitignore: -------------------------------------------------------------------------------- 1 | *.wasm 2 | /libenet.a 3 | -------------------------------------------------------------------------------- /game/src/enet/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2020 Lee Salzman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /game/src/enet/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-O3 -fomit-frame-pointer 2 | override CFLAGS:= $(CFLAGS) -Iinclude $(shell ./check_cflags.sh $(CC) $(CFLAGS)) 3 | 4 | CXX = $(EMSCRIPTEN)/emcc 5 | EMCONFIGURE = $(EMSCRIPTEN)/emconfigure 6 | EMMAKE = $(EMSCRIPTEN)/emmake 7 | 8 | OBJS= \ 9 | callbacks.o \ 10 | compress.o \ 11 | host.o \ 12 | list.o \ 13 | packet.o \ 14 | peer.o \ 15 | protocol.o \ 16 | unix.o \ 17 | win32.o 18 | 19 | libenet.a: $(OBJS) 20 | $(AR) rcs $@ $(OBJS) 21 | 22 | default: libenet.a 23 | 24 | clean: 25 | -$(RM) libenet.a $(OBJS) 26 | 27 | -------------------------------------------------------------------------------- /game/src/enet/README: -------------------------------------------------------------------------------- 1 | Please visit the ENet homepage at http://enet.bespin.org for installation 2 | and usage instructions. 3 | 4 | If you obtained this package from github, the quick description on how to build 5 | is: 6 | 7 | # Generate the build system. 8 | 9 | autoreconf -vfi 10 | 11 | # Compile and install the library. 12 | 13 | ./configure && make && make install 14 | 15 | 16 | -------------------------------------------------------------------------------- /game/src/enet/callbacks.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file callbacks.c 3 | @brief ENet callback functions 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include "enet/enet.h" 7 | 8 | static ENetCallbacks callbacks = { malloc, free, abort }; 9 | 10 | int 11 | enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits) 12 | { 13 | if (version < ENET_VERSION_CREATE (1, 3, 0)) 14 | return -1; 15 | 16 | if (inits -> malloc != NULL || inits -> free != NULL) 17 | { 18 | if (inits -> malloc == NULL || inits -> free == NULL) 19 | return -1; 20 | 21 | callbacks.malloc = inits -> malloc; 22 | callbacks.free = inits -> free; 23 | } 24 | 25 | if (inits -> no_memory != NULL) 26 | callbacks.no_memory = inits -> no_memory; 27 | 28 | return enet_initialize (); 29 | } 30 | 31 | ENetVersion 32 | enet_linked_version (void) 33 | { 34 | return ENET_VERSION; 35 | } 36 | 37 | void * 38 | enet_malloc (size_t size) 39 | { 40 | void * memory = callbacks.malloc (size); 41 | 42 | if (memory == NULL) 43 | callbacks.no_memory (); 44 | 45 | return memory; 46 | } 47 | 48 | void 49 | enet_free (void * memory) 50 | { 51 | callbacks.free (memory); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /game/src/enet/check_cflags.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ENet cflags detection for unix by Daniel 'q66' Kolesa 3 | # I hereby put this file into public domain, use as you wish 4 | 5 | CC=$* 6 | 7 | cat << EOF > check_func.c 8 | void TEST_FUN(); 9 | int main() { TEST_FUN(); return 0; } 10 | EOF 11 | cat << EOF > check_member.c 12 | #include "check_member.h" 13 | static void pass() {} 14 | int main() { struct TEST_STRUCT test; pass(test.TEST_FIELD); return 0; } 15 | EOF 16 | cat << EOF > check_type.c 17 | #include "check_type.h" 18 | int main() { TEST_TYPE test; return 0; } 19 | EOF 20 | 21 | CHECK_FUNC() { 22 | $CC check_func.c -DTEST_FUN=$1 -o check_func 2>/dev/null 23 | if [ $? -eq 0 ]; then printf " $2"; rm check_func; fi 24 | } 25 | 26 | CHECK_FUNC getaddrinfo -DHAS_GETADDRINFO 27 | CHECK_FUNC getnameinfo -DHAS_GETNAMEINFO 28 | CHECK_FUNC gethostbyaddr_r -DHAS_GETHOSTBYADDR_R 29 | CHECK_FUNC gethostbyname_r -DHAS_GETHOSTBYNAME_R 30 | CHECK_FUNC poll -DHAS_POLL 31 | CHECK_FUNC fcntl -DHAS_FCNTL 32 | CHECK_FUNC inet_pton -DHAS_INET_PTON 33 | CHECK_FUNC inet_ntop -DHAS_INET_NTOP 34 | 35 | echo "#include " > check_member.h 36 | $CC check_member.c -DTEST_STRUCT=msghdr -DTEST_FIELD=msg_flags \ 37 | -o check_member 2>/dev/null 38 | if [ $? -eq 0 ]; then printf " -DHAS_MSGHDR_FLAGS"; rm check_member; fi 39 | rm check_member.h 40 | 41 | echo "#include " > check_type.h 42 | echo "#include " >> check_type.h 43 | $CC check_type.c -DTEST_TYPE=socklen_t -o check_type 2>/dev/null 44 | if [ $? -eq 0 ]; then printf " -DHAS_SOCKLEN_T"; rm check_type; fi 45 | rm check_type.h 46 | 47 | echo '' 48 | rm check_func.c 49 | rm check_member.c 50 | rm check_type.c 51 | -------------------------------------------------------------------------------- /game/src/enet/include/enet/callbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file callbacks.h 3 | @brief ENet callbacks 4 | */ 5 | #ifndef __ENET_CALLBACKS_H__ 6 | #define __ENET_CALLBACKS_H__ 7 | 8 | #include 9 | 10 | typedef struct _ENetCallbacks 11 | { 12 | void * (ENET_CALLBACK * malloc) (size_t size); 13 | void (ENET_CALLBACK * free) (void * memory); 14 | void (ENET_CALLBACK * no_memory) (void); 15 | } ENetCallbacks; 16 | 17 | /** @defgroup callbacks ENet internal callbacks 18 | @{ 19 | @ingroup private 20 | */ 21 | extern void * enet_malloc (size_t); 22 | extern void enet_free (void *); 23 | 24 | /** @} */ 25 | 26 | #endif /* __ENET_CALLBACKS_H__ */ 27 | 28 | -------------------------------------------------------------------------------- /game/src/enet/include/enet/list.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file list.h 3 | @brief ENet list management 4 | */ 5 | #ifndef __ENET_LIST_H__ 6 | #define __ENET_LIST_H__ 7 | 8 | #include 9 | 10 | typedef struct _ENetListNode 11 | { 12 | struct _ENetListNode * next; 13 | struct _ENetListNode * previous; 14 | } ENetListNode; 15 | 16 | typedef ENetListNode * ENetListIterator; 17 | 18 | typedef struct _ENetList 19 | { 20 | ENetListNode sentinel; 21 | } ENetList; 22 | 23 | extern void enet_list_clear (ENetList *); 24 | 25 | extern ENetListIterator enet_list_insert (ENetListIterator, void *); 26 | extern void * enet_list_remove (ENetListIterator); 27 | extern ENetListIterator enet_list_move (ENetListIterator, void *, void *); 28 | 29 | extern size_t enet_list_size (ENetList *); 30 | 31 | #define enet_list_begin(list) ((list) -> sentinel.next) 32 | #define enet_list_end(list) (& (list) -> sentinel) 33 | 34 | #define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list)) 35 | 36 | #define enet_list_next(iterator) ((iterator) -> next) 37 | #define enet_list_previous(iterator) ((iterator) -> previous) 38 | 39 | #define enet_list_front(list) ((void *) (list) -> sentinel.next) 40 | #define enet_list_back(list) ((void *) (list) -> sentinel.previous) 41 | 42 | #endif /* __ENET_LIST_H__ */ 43 | 44 | -------------------------------------------------------------------------------- /game/src/enet/include/enet/time.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file time.h 3 | @brief ENet time constants and macros 4 | */ 5 | #ifndef __ENET_TIME_H__ 6 | #define __ENET_TIME_H__ 7 | 8 | #define ENET_TIME_OVERFLOW 86400000 9 | 10 | #define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) 11 | #define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) 12 | #define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) 13 | #define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) 14 | 15 | #define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) 16 | 17 | #endif /* __ENET_TIME_H__ */ 18 | 19 | -------------------------------------------------------------------------------- /game/src/enet/include/enet/types.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file types.h 3 | @brief type definitions for ENet 4 | */ 5 | #ifndef __ENET_TYPES_H__ 6 | #define __ENET_TYPES_H__ 7 | 8 | typedef unsigned char enet_uint8; /**< unsigned 8-bit type */ 9 | typedef unsigned short enet_uint16; /**< unsigned 16-bit type */ 10 | typedef unsigned int enet_uint32; /**< unsigned 32-bit type */ 11 | 12 | #endif /* __ENET_TYPES_H__ */ 13 | 14 | -------------------------------------------------------------------------------- /game/src/enet/include/enet/unix.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file unix.h 3 | @brief ENet Unix header 4 | */ 5 | #ifndef __ENET_UNIX_H__ 6 | #define __ENET_UNIX_H__ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef MSG_MAXIOVLEN 17 | #define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN 18 | #endif 19 | 20 | typedef int ENetSocket; 21 | 22 | #define ENET_SOCKET_NULL -1 23 | 24 | #define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ 25 | #define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ 26 | 27 | #define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */ 28 | #define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */ 29 | 30 | typedef struct 31 | { 32 | void * data; 33 | size_t dataLength; 34 | } ENetBuffer; 35 | 36 | #define ENET_CALLBACK 37 | 38 | #define ENET_API extern 39 | 40 | typedef fd_set ENetSocketSet; 41 | 42 | #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) 43 | #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) 44 | #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) 45 | #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) 46 | 47 | #endif /* __ENET_UNIX_H__ */ 48 | 49 | -------------------------------------------------------------------------------- /game/src/enet/include/enet/utility.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file utility.h 3 | @brief ENet utility header 4 | */ 5 | #ifndef __ENET_UTILITY_H__ 6 | #define __ENET_UTILITY_H__ 7 | 8 | #define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) 9 | #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) 10 | #define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y)) 11 | 12 | #endif /* __ENET_UTILITY_H__ */ 13 | 14 | -------------------------------------------------------------------------------- /game/src/enet/include/enet/win32.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file win32.h 3 | @brief ENet Win32 header 4 | */ 5 | #ifndef __ENET_WIN32_H__ 6 | #define __ENET_WIN32_H__ 7 | 8 | #ifdef _MSC_VER 9 | #ifdef ENET_BUILDING_LIB 10 | #pragma warning (disable: 4267) // size_t to int conversion 11 | #pragma warning (disable: 4244) // 64bit to 32bit int 12 | #pragma warning (disable: 4018) // signed/unsigned mismatch 13 | #pragma warning (disable: 4146) // unary minus operator applied to unsigned type 14 | #endif 15 | #endif 16 | 17 | #include 18 | #include 19 | 20 | typedef SOCKET ENetSocket; 21 | 22 | #define ENET_SOCKET_NULL INVALID_SOCKET 23 | 24 | #define ENET_HOST_TO_NET_16(value) (htons (value)) 25 | #define ENET_HOST_TO_NET_32(value) (htonl (value)) 26 | 27 | #define ENET_NET_TO_HOST_16(value) (ntohs (value)) 28 | #define ENET_NET_TO_HOST_32(value) (ntohl (value)) 29 | 30 | typedef struct 31 | { 32 | size_t dataLength; 33 | void * data; 34 | } ENetBuffer; 35 | 36 | #define ENET_CALLBACK __cdecl 37 | 38 | #ifdef ENET_DLL 39 | #ifdef ENET_BUILDING_LIB 40 | #define ENET_API __declspec( dllexport ) 41 | #else 42 | #define ENET_API __declspec( dllimport ) 43 | #endif /* ENET_BUILDING_LIB */ 44 | #else /* !ENET_DLL */ 45 | #define ENET_API extern 46 | #endif /* ENET_DLL */ 47 | 48 | typedef fd_set ENetSocketSet; 49 | 50 | #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) 51 | #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) 52 | #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) 53 | #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) 54 | 55 | #endif /* __ENET_WIN32_H__ */ 56 | 57 | 58 | -------------------------------------------------------------------------------- /game/src/enet/list.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file list.c 3 | @brief ENet linked list functions 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include "enet/enet.h" 7 | 8 | /** 9 | @defgroup list ENet linked list utility functions 10 | @ingroup private 11 | @{ 12 | */ 13 | void 14 | enet_list_clear (ENetList * list) 15 | { 16 | list -> sentinel.next = & list -> sentinel; 17 | list -> sentinel.previous = & list -> sentinel; 18 | } 19 | 20 | ENetListIterator 21 | enet_list_insert (ENetListIterator position, void * data) 22 | { 23 | ENetListIterator result = (ENetListIterator) data; 24 | 25 | result -> previous = position -> previous; 26 | result -> next = position; 27 | 28 | result -> previous -> next = result; 29 | position -> previous = result; 30 | 31 | return result; 32 | } 33 | 34 | void * 35 | enet_list_remove (ENetListIterator position) 36 | { 37 | position -> previous -> next = position -> next; 38 | position -> next -> previous = position -> previous; 39 | 40 | return position; 41 | } 42 | 43 | ENetListIterator 44 | enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast) 45 | { 46 | ENetListIterator first = (ENetListIterator) dataFirst, 47 | last = (ENetListIterator) dataLast; 48 | 49 | first -> previous -> next = last -> next; 50 | last -> next -> previous = first -> previous; 51 | 52 | first -> previous = position -> previous; 53 | last -> next = position; 54 | 55 | first -> previous -> next = first; 56 | position -> previous = last; 57 | 58 | return first; 59 | } 60 | 61 | size_t 62 | enet_list_size (ENetList * list) 63 | { 64 | size_t size = 0; 65 | ENetListIterator position; 66 | 67 | for (position = enet_list_begin (list); 68 | position != enet_list_end (list); 69 | position = enet_list_next (position)) 70 | ++ size; 71 | 72 | return size; 73 | } 74 | 75 | /** @} */ 76 | -------------------------------------------------------------------------------- /game/src/engine/glare.cpp: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | #include "rendertarget.h" 3 | 4 | static struct glaretexture : rendertarget 5 | { 6 | bool dorender() 7 | { 8 | extern void drawglare(); 9 | drawglare(); 10 | return true; 11 | } 12 | } glaretex; 13 | 14 | void cleanupglare() 15 | { 16 | glaretex.cleanup(true); 17 | } 18 | 19 | VARFP(glaresize, 6, 8, 10, cleanupglare()); 20 | VARP(glare, 0, 0, 1); 21 | VARP(blurglare, 0, 4, 7); 22 | VARP(blurglareaspect, 0, 1, 1); 23 | VARP(blurglaresigma, 1, 50, 200); 24 | 25 | VAR(debugglare, 0, 0, 1); 26 | 27 | void viewglaretex() 28 | { 29 | if(!glare) return; 30 | glaretex.debug(); 31 | } 32 | 33 | bool glaring = false; 34 | 35 | void drawglaretex() 36 | { 37 | if(!glare) return; 38 | 39 | int w = 1< (1<<5) && (screenw*h)/w >= (screenh*4)/3) h /= 2; 43 | blury = ((1 + 4*blurglare)*(screenw*h)/w + screenh*2)/(screenh*4); 44 | blury = clamp(blury, 1, MAXBLURRADIUS); 45 | } 46 | 47 | glaretex.render(w, h, blurglare, blurglaresigma/100.0f, blury); 48 | } 49 | 50 | FVAR(glaremod, 0.5f, 0.75f, 1); 51 | FVARP(glarescale, 0, 1, 8); 52 | 53 | void addglare() 54 | { 55 | if(!glare) return; 56 | 57 | glEnable(GL_BLEND); 58 | glBlendFunc(GL_ONE, GL_ONE); 59 | 60 | SETSHADER(screenrect); 61 | 62 | glBindTexture(GL_TEXTURE_2D, glaretex.rendertex); 63 | 64 | float g = glarescale*glaremod; 65 | gle::colorf(g, g, g); 66 | 67 | screenquad(1, 1); 68 | 69 | glDisable(GL_BLEND); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /game/src/engine/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | 3 | -------------------------------------------------------------------------------- /game/src/engine/world.h: -------------------------------------------------------------------------------- 1 | 2 | enum // hardcoded texture numbers 3 | { 4 | DEFAULT_SKY = 0, 5 | DEFAULT_GEOM 6 | }; 7 | 8 | #define MAPVERSION 33 // bump if map format changes, see worldio.cpp 9 | 10 | struct octaheader 11 | { 12 | char magic[4]; // "OCTA" 13 | int version; // any >8bit quantity is little endian 14 | int headersize; // sizeof(header) 15 | int worldsize; 16 | int numents; 17 | int numpvs; 18 | int lightmaps; 19 | int blendmap; 20 | int numvars; 21 | int numvslots; 22 | }; 23 | 24 | struct compatheader // map file format header 25 | { 26 | char magic[4]; // "OCTA" 27 | int version; // any >8bit quantity is little endian 28 | int headersize; // sizeof(header) 29 | int worldsize; 30 | int numents; 31 | int numpvs; 32 | int lightmaps; 33 | int lightprecision, lighterror, lightlod; 34 | uchar ambient; 35 | uchar watercolour[3]; 36 | uchar blendmap; 37 | uchar lerpangle, lerpsubdiv, lerpsubdivsize; 38 | uchar bumperror; 39 | uchar skylight[3]; 40 | uchar lavacolour[3]; 41 | uchar waterfallcolour[3]; 42 | uchar reserved[10]; 43 | char maptitle[128]; 44 | }; 45 | 46 | #define WATER_AMPLITUDE 0.4f 47 | #define WATER_OFFSET 1.1f 48 | 49 | enum 50 | { 51 | MATSURF_NOT_VISIBLE = 0, 52 | MATSURF_VISIBLE, 53 | MATSURF_EDIT_ONLY 54 | }; 55 | 56 | #define TEX_SCALE 8.0f 57 | 58 | struct vertex { vec pos; bvec4 norm; vec2 tc; svec2 lm; bvec4 tangent; }; 59 | 60 | -------------------------------------------------------------------------------- /game/src/fpsgame/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "game.h" 2 | 3 | -------------------------------------------------------------------------------- /game/src/include/SDL_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #ifndef SDL_config_h_ 23 | #define SDL_config_h_ 24 | 25 | #include "SDL_platform.h" 26 | 27 | /** 28 | * \file SDL_config.h 29 | */ 30 | 31 | /* Add any platform that doesn't build using the configure system. */ 32 | #if defined(__WIN32__) 33 | #include "SDL_config_windows.h" 34 | #elif defined(__WINRT__) 35 | #include "SDL_config_winrt.h" 36 | #elif defined(__MACOSX__) 37 | #include "SDL_config_macosx.h" 38 | #elif defined(__IPHONEOS__) 39 | #include "SDL_config_iphoneos.h" 40 | #elif defined(__ANDROID__) 41 | #include "SDL_config_android.h" 42 | #elif defined(__PSP__) 43 | #include "SDL_config_psp.h" 44 | #elif defined(__OS2__) 45 | #include "SDL_config_os2.h" 46 | #else 47 | /* This is a minimal configuration just to get SDL running on new platforms. */ 48 | #include "SDL_config_minimal.h" 49 | #endif /* platform config */ 50 | 51 | #ifdef USING_GENERATED_CONFIG_H 52 | #error Wrong SDL_config.h, check your include path? 53 | #endif 54 | 55 | #endif /* SDL_config_h_ */ 56 | -------------------------------------------------------------------------------- /game/src/include/SDL_copying.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | -------------------------------------------------------------------------------- /game/src/include/SDL_name.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #ifndef SDLname_h_ 23 | #define SDLname_h_ 24 | 25 | #if defined(__STDC__) || defined(__cplusplus) 26 | #define NeedFunctionPrototypes 1 27 | #endif 28 | 29 | #define SDL_NAME(X) SDL_##X 30 | 31 | #endif /* SDLname_h_ */ 32 | 33 | /* vi: set ts=4 sw=4 expandtab: */ 34 | -------------------------------------------------------------------------------- /game/src/include/SDL_opengles.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | /** 23 | * \file SDL_opengles.h 24 | * 25 | * This is a simple file to encapsulate the OpenGL ES 1.X API headers. 26 | */ 27 | #include "SDL_config.h" 28 | 29 | #ifdef __IPHONEOS__ 30 | #include 31 | #include 32 | #else 33 | #include 34 | #include 35 | #endif 36 | 37 | #ifndef APIENTRY 38 | #define APIENTRY 39 | #endif 40 | -------------------------------------------------------------------------------- /game/src/include/SDL_opengles2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | /** 23 | * \file SDL_opengles2.h 24 | * 25 | * This is a simple file to encapsulate the OpenGL ES 2.0 API headers. 26 | */ 27 | #include "SDL_config.h" 28 | 29 | #ifndef _MSC_VER 30 | 31 | #ifdef __IPHONEOS__ 32 | #include 33 | #include 34 | #else 35 | #include 36 | #include 37 | #include 38 | #endif 39 | 40 | #else /* _MSC_VER */ 41 | 42 | /* OpenGL ES2 headers for Visual Studio */ 43 | #include "SDL_opengles2_khrplatform.h" 44 | #include "SDL_opengles2_gl2platform.h" 45 | #include "SDL_opengles2_gl2.h" 46 | #include "SDL_opengles2_gl2ext.h" 47 | 48 | #endif /* _MSC_VER */ 49 | 50 | #ifndef APIENTRY 51 | #define APIENTRY GL_APIENTRY 52 | #endif 53 | -------------------------------------------------------------------------------- /game/src/include/SDL_opengles2_gl2platform.h: -------------------------------------------------------------------------------- 1 | #ifndef __gl2platform_h_ 2 | #define __gl2platform_h_ 3 | 4 | /* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */ 5 | 6 | /* 7 | * This document is licensed under the SGI Free Software B License Version 8 | * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . 9 | */ 10 | 11 | /* Platform-specific types and definitions for OpenGL ES 2.X gl2.h 12 | * 13 | * Adopters may modify khrplatform.h and this file to suit their platform. 14 | * You are encouraged to submit all modifications to the Khronos group so that 15 | * they can be included in future versions of this file. Please submit changes 16 | * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) 17 | * by filing a bug against product "OpenGL-ES" component "Registry". 18 | */ 19 | 20 | /*#include */ 21 | 22 | #ifndef GL_APICALL 23 | #define GL_APICALL KHRONOS_APICALL 24 | #endif 25 | 26 | #ifndef GL_APIENTRY 27 | #define GL_APIENTRY KHRONOS_APIENTRY 28 | #endif 29 | 30 | #endif /* __gl2platform_h_ */ 31 | -------------------------------------------------------------------------------- /game/src/include/SDL_revision.h: -------------------------------------------------------------------------------- 1 | #define SDL_REVISION "hg-13609:34cc7d3b69d3" 2 | #define SDL_REVISION_NUMBER 13609 3 | -------------------------------------------------------------------------------- /game/src/include/SDL_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | /** 23 | * \file SDL_types.h 24 | * 25 | * \deprecated 26 | */ 27 | 28 | /* DEPRECATED */ 29 | #include "SDL_stdinc.h" 30 | -------------------------------------------------------------------------------- /game/src/include/close_code.h: -------------------------------------------------------------------------------- 1 | /* 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | /** 23 | * \file close_code.h 24 | * 25 | * This file reverses the effects of begin_code.h and should be included 26 | * after you finish any function and structure declarations in your headers 27 | */ 28 | 29 | #ifndef _begin_code_h 30 | #error close_code.h included without matching begin_code.h 31 | #endif 32 | #undef _begin_code_h 33 | 34 | /* Reset structure packing at previous byte alignment */ 35 | #if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) 36 | #ifdef __BORLANDC__ 37 | #pragma nopackwarning 38 | #endif 39 | #pragma pack(pop) 40 | #endif /* Compiler needs structure packing set */ 41 | -------------------------------------------------------------------------------- /game/src/native/engine/keepalive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/game/src/native/engine/keepalive -------------------------------------------------------------------------------- /game/src/native/fpsgame/keepalive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/game/src/native/fpsgame/keepalive -------------------------------------------------------------------------------- /game/src/native/shared/keepalive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/game/src/native/shared/keepalive -------------------------------------------------------------------------------- /game/src/shared/cube.h: -------------------------------------------------------------------------------- 1 | #ifndef __CUBE_H__ 2 | #define __CUBE_H__ 3 | 4 | #define _FILE_OFFSET_BITS 64 5 | 6 | #ifdef WIN32 7 | #define _USE_MATH_DEFINES 8 | #endif 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #ifdef WIN32 21 | #define WIN32_LEAN_AND_MEAN 22 | #define _WIN32_WINNT 0x0500 23 | #include "windows.h" 24 | #ifndef _WINDOWS 25 | #define _WINDOWS 26 | #endif 27 | #ifndef __GNUC__ 28 | #include 29 | #include 30 | #include 31 | #endif 32 | #define ZLIB_DLL 33 | #endif 34 | 35 | #ifndef STANDALONE 36 | #ifdef __APPLE__ 37 | #include "SDL.h" 38 | #define GL_GLEXT_LEGACY 39 | #define __glext_h_ 40 | #include 41 | #else 42 | #include 43 | #include 44 | #endif 45 | #endif 46 | 47 | #include 48 | 49 | #include 50 | 51 | #include "tools.h" 52 | #include "geom.h" 53 | #include "ents.h" 54 | #include "command.h" 55 | 56 | #ifndef STANDALONE 57 | #include "glexts.h" 58 | #include "glemu.h" 59 | #endif 60 | 61 | #include "iengine.h" 62 | #include "igame.h" 63 | 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /game/src/shared/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "cube.h" 2 | -------------------------------------------------------------------------------- /game/src/web/.agignore: -------------------------------------------------------------------------------- 1 | engine 2 | fpsgame 3 | shared 4 | -------------------------------------------------------------------------------- /game/src/web/engine/keepalive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/game/src/web/engine/keepalive -------------------------------------------------------------------------------- /game/src/web/fpsgame/keepalive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/game/src/web/fpsgame/keepalive -------------------------------------------------------------------------------- /game/src/web/shared/keepalive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfoust/sour/42cc0e25d3310fd189f294e7ff3784e0109f1de0/game/src/web/shared/keepalive -------------------------------------------------------------------------------- /game/websocket_hook.patch: -------------------------------------------------------------------------------- 1 | --- sauerbraten.js.orig 2022-03-26 06:56:34.149134145 +0000 2 | +++ sauerbraten.js 2022-03-26 06:57:24.892768208 +0000 3 | @@ -4547,6 +4547,9 @@ 4 | if ("string" === typeof Module["websocket"]["url"]) { 5 | url = Module["websocket"]["url"]; 6 | } 7 | + if ("function" === typeof Module["websocket"]["url"]) { 8 | + url = Module["websocket"]["url"](addr, port); 9 | + } 10 | } 11 | if (url === "ws://" || url === "wss://") { 12 | var parts = addr.split("/"); 13 | -------------------------------------------------------------------------------- /gh-assets/.gitattributes: -------------------------------------------------------------------------------- 1 | *.gif filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /gh-assets/header.gif: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bbc73c6ecc44e73130c200bf77a1820b90bb6883c35fd245f45daef721a40bc8 3 | size 39292607 4 | -------------------------------------------------------------------------------- /gh-assets/header.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:149a127406cac218c8184d0196f792b1862e71ddab6d1ccc385e27307a2c44fd 3 | size 4026979 4 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cfoust/sour 2 | 3 | go 1.22.0 4 | 5 | require ( 6 | cuelang.org/go v0.10.1 // indirect 7 | github.com/alecthomas/kong v1.2.1 // indirect 8 | github.com/cespare/xxhash/v2 v2.1.2 // indirect 9 | github.com/cockroachdb/apd/v3 v3.2.1 // indirect 10 | github.com/codecat/go-enet v0.0.0-20201213053919-8c1bf6ac65fa // indirect 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 13 | github.com/fxamacker/cbor/v2 v2.4.0 // indirect 14 | github.com/go-redis/redis/v9 v9.0.0-rc.2 // indirect 15 | github.com/google/uuid v1.6.0 // indirect 16 | github.com/jinzhu/inflection v1.0.0 // indirect 17 | github.com/jinzhu/now v1.1.5 // indirect 18 | github.com/klauspost/compress v1.10.3 // indirect 19 | github.com/mattn/go-colorable v0.1.13 // indirect 20 | github.com/mattn/go-isatty v0.0.16 // indirect 21 | github.com/mattn/go-sqlite3 v1.14.16 // indirect 22 | github.com/mileusna/useragent v1.2.1 // indirect 23 | github.com/petermattis/goid v0.0.0-20241025130422-66cb2e6d7274 // indirect 24 | github.com/pmezard/go-difflib v1.0.0 // indirect 25 | github.com/repeale/fp-go v0.11.1 // indirect 26 | github.com/rs/zerolog v1.28.0 // indirect 27 | github.com/sasha-s/go-deadlock v0.3.5 // indirect 28 | github.com/stretchr/objx v0.5.0 // indirect 29 | github.com/stretchr/testify v1.8.2 // indirect 30 | github.com/x448/float16 v0.8.4 // indirect 31 | golang.org/x/mod v0.21.0 // indirect 32 | golang.org/x/net v0.30.0 // indirect 33 | golang.org/x/sys v0.26.0 // indirect 34 | golang.org/x/text v0.19.0 // indirect 35 | golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect 36 | gopkg.in/yaml.v3 v3.0.1 // indirect 37 | gorm.io/driver/sqlite v1.4.4 // indirect 38 | gorm.io/gorm v1.24.5 // indirect 39 | nhooyr.io/websocket v1.8.7 // indirect 40 | ) 41 | -------------------------------------------------------------------------------- /pkg/assets/types.go: -------------------------------------------------------------------------------- 1 | package assets 2 | 3 | type IndexAsset struct { 4 | _ struct{} `cbor:",toarray"` 5 | Id int 6 | Path string 7 | } 8 | 9 | type Asset struct { 10 | _ struct{} `cbor:",toarray"` 11 | Id string 12 | Path string 13 | } 14 | 15 | type Mod struct { 16 | Id string 17 | Name string 18 | Image string 19 | Description string 20 | } 21 | 22 | type GameMap struct { 23 | Id string 24 | Name string 25 | Ogz string 26 | Bundle string 27 | Assets []Asset 28 | Image string 29 | Description string 30 | } 31 | 32 | type SlimMap struct { 33 | Id string 34 | Name string 35 | Ogz string 36 | Bundle string 37 | HasCFG bool 38 | } 39 | 40 | type Bundle struct { 41 | Id string 42 | Desktop bool 43 | Web bool 44 | Assets []Asset 45 | } 46 | 47 | type Model struct { 48 | Id string 49 | Name string 50 | } 51 | 52 | type Index struct { 53 | Assets []string 54 | Refs []IndexAsset 55 | Textures []Asset 56 | Sounds []Asset 57 | Bundles []Bundle 58 | Maps []GameMap 59 | Models []Model 60 | Mods []Mod 61 | } 62 | 63 | type AssetSource struct { 64 | Index *Index 65 | Base string 66 | } 67 | -------------------------------------------------------------------------------- /pkg/assets/utils.go: -------------------------------------------------------------------------------- 1 | package assets 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net/http" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | func FileExists(path string) bool { 12 | if _, err := os.Stat(path); !os.IsNotExist(err) { 13 | return true 14 | } 15 | return false 16 | } 17 | 18 | func WriteBytes(data []byte, path string) error { 19 | out, err := os.Create(path) 20 | if err != nil { 21 | return err 22 | } 23 | defer out.Close() 24 | 25 | out, err = os.Create(path) 26 | if err != nil { 27 | return err 28 | } 29 | defer out.Close() 30 | 31 | _, err = out.Write(data) 32 | if err != nil { 33 | return err 34 | } 35 | 36 | return nil 37 | } 38 | 39 | func DownloadBytes(url string) ([]byte, error) { 40 | resp, err := http.Get(url) 41 | if err != nil { 42 | return nil, err 43 | } 44 | defer resp.Body.Close() 45 | 46 | // Check server response 47 | if resp.StatusCode != http.StatusOK { 48 | return nil, fmt.Errorf("bad status: %s", resp.Status) 49 | } 50 | 51 | return io.ReadAll(resp.Body) 52 | } 53 | 54 | func DownloadFile(url string, path string) error { 55 | out, err := os.Create(path) 56 | if err != nil { 57 | return err 58 | } 59 | defer out.Close() 60 | 61 | resp, err := http.Get(url) 62 | if err != nil { 63 | return err 64 | } 65 | defer resp.Body.Close() 66 | 67 | // Check server response 68 | if resp.StatusCode != http.StatusOK { 69 | return fmt.Errorf("bad status: %s", resp.Status) 70 | } 71 | 72 | _, err = io.Copy(out, resp.Body) 73 | if err != nil { 74 | return err 75 | } 76 | 77 | return nil 78 | } 79 | 80 | func CleanSourcePath(indexURL string) string { 81 | lastSlash := strings.LastIndex(indexURL, "/") 82 | if lastSlash == -1 { 83 | return "" 84 | } 85 | 86 | return indexURL[:lastSlash+1] 87 | } 88 | 89 | func GetURLBase(url string) string { 90 | lastSlash := strings.LastIndex(url, "/") 91 | if lastSlash == -1 { 92 | return "" 93 | } 94 | 95 | return url[lastSlash+1:] 96 | } 97 | -------------------------------------------------------------------------------- /pkg/chanlock/README.md: -------------------------------------------------------------------------------- 1 | # chanlock 2 | 3 | This is a fork of _some aspects of_ [go-deadlock](https://github.com/sasha-s/go-deadlock), a library for diagnosing locking issues with mutexes. It repurposes the deadlock detection mechanism for use with Go code that uses the `for { select { ... } }` pattern. 4 | -------------------------------------------------------------------------------- /pkg/config/config_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestProcess(t *testing.T) { 12 | // Default config 13 | _, err := Process([]string{}) 14 | require.NoError(t, err) 15 | 16 | dir := t.TempDir() 17 | 18 | // yaml config 19 | { 20 | yaml := filepath.Join(dir, "config.yaml") 21 | err = os.WriteFile(yaml, []byte(` 22 | server: 23 | ingress: 24 | web: 25 | port: 1234 26 | `), 0644) 27 | require.NoError(t, err) 28 | _, err = Process([]string{yaml}) 29 | require.NoError(t, err) 30 | } 31 | 32 | // json config 33 | { 34 | json := filepath.Join(dir, "config.json") 35 | err = os.WriteFile(json, []byte(`{ 36 | "server": { 37 | "ingress": { 38 | "web": { 39 | "port": 1235 40 | } 41 | } 42 | } 43 | }`), 0644) 44 | require.NoError(t, err) 45 | _, err = Process([]string{json}) 46 | require.NoError(t, err) 47 | } 48 | 49 | // multiple yaml 50 | { 51 | yaml1 := filepath.Join(dir, "config1.yaml") 52 | err = os.WriteFile(yaml1, []byte(` 53 | server: 54 | ingress: 55 | web: 56 | port: 1234 57 | `), 0644) 58 | require.NoError(t, err) 59 | 60 | yaml2 := filepath.Join(dir, "config2.yaml") 61 | err = os.WriteFile(yaml2, []byte(` 62 | server: 63 | serverDescription: "Hello, World!" 64 | `), 0644) 65 | require.NoError(t, err) 66 | _, err = Process([]string{yaml1, yaml2}) 67 | require.NoError(t, err) 68 | } 69 | 70 | // Invalid config 71 | _, err = Process([]string{}) 72 | } 73 | -------------------------------------------------------------------------------- /pkg/config/default.yaml: -------------------------------------------------------------------------------- 1 | # This is Sour's default configuration. 2 | server: 3 | presets: 4 | - name: "ffa-duel" 5 | virtual: true 6 | config: 7 | defaultMode: "ffa" 8 | defaultMap: "turbine" 9 | - name: "insta-duel" 10 | virtual: true 11 | config: 12 | defaultMode: "insta" 13 | defaultMap: "turbine" 14 | - name: "default" 15 | default: true 16 | config: 17 | defaultMode: "coop" 18 | defaultMap: "xmwhub" 19 | - name: "ffa" 20 | config: 21 | defaultMode: "ffa" 22 | defaultMap: "complex" 23 | maps: 24 | - "turbine" 25 | - "complex" 26 | - "dust2" 27 | - name: "insta" 28 | config: 29 | defaultMode: "insta" 30 | defaultMap: "complex" 31 | maps: 32 | - "turbine" 33 | - "complex" 34 | - "dust2" 35 | - name: "explore" 36 | config: 37 | matchLength: 180 38 | 39 | ingress: 40 | desktop: 41 | - port: 28785 42 | target: lobby 43 | serverInfo: 44 | enabled: false 45 | 46 | matchmaking: 47 | duel: 48 | - name: "ffa" 49 | preset: "ffa-duel" 50 | forceRespawn: "dead" 51 | default: true 52 | - name: "insta" 53 | preset: "insta-duel" 54 | forceRespawn: "dead" 55 | 56 | spaces: 57 | - preset: ffa 58 | config: 59 | alias: lobby 60 | - preset: insta 61 | config: 62 | alias: insta 63 | -------------------------------------------------------------------------------- /pkg/config/dev.yaml: -------------------------------------------------------------------------------- 1 | # This configuration can be used for local development. 2 | server: 3 | assets: 4 | - "fs:./assets/dist/.index.source" 5 | presets: 6 | - name: "ffa-duel" 7 | virtual: true 8 | config: 9 | defaultMode: "ffa" 10 | defaultMap: "turbine" 11 | - name: "insta-duel" 12 | virtual: true 13 | config: 14 | defaultMode: "insta" 15 | defaultMap: "turbine" 16 | - name: "default" 17 | default: true 18 | config: 19 | defaultMode: "coop" 20 | defaultMap: "xmwhub" 21 | - name: "ffa" 22 | config: 23 | defaultMode: "ffa" 24 | defaultMap: "complex" 25 | maps: 26 | - "turbine" 27 | - "complex" 28 | - "dust2" 29 | - name: "insta" 30 | config: 31 | defaultMode: "insta" 32 | defaultMap: "complex" 33 | maps: 34 | - "turbine" 35 | - "complex" 36 | - "dust2" 37 | - name: "explore" 38 | config: 39 | matchLength: 180 40 | 41 | ingress: 42 | desktop: 43 | - port: 28785 44 | target: ffa 45 | serverInfo: 46 | enabled: true 47 | server: true 48 | web: 49 | port: 29999 50 | 51 | matchmaking: 52 | duel: 53 | - name: "ffa" 54 | preset: "ffa-duel" 55 | forceRespawn: "dead" 56 | default: true 57 | - name: "insta" 58 | preset: "insta-duel" 59 | forceRespawn: "dead" 60 | 61 | spaces: 62 | - preset: ffa 63 | config: 64 | alias: lobby 65 | - preset: insta 66 | config: 67 | alias: insta 68 | -------------------------------------------------------------------------------- /pkg/cs/cs.swigcxx: -------------------------------------------------------------------------------- 1 | %module interop 2 | %{ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "command.h" 14 | %} 15 | %include "wrap.h" 16 | 17 | -------------------------------------------------------------------------------- /pkg/cs/wrap.h: -------------------------------------------------------------------------------- 1 | extern int execute(const char *p); 2 | void intret(int v); 3 | void floatret(float v); 4 | void stringret(char *s); 5 | void result(const char *s); 6 | -------------------------------------------------------------------------------- /pkg/enet/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2014-2019, Alexander Willing 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /pkg/enet/README.md: -------------------------------------------------------------------------------- 1 | Forked from [sauerbraten/waiter](https://github.com/sauerbraten/waiter) with some modifications. 2 | -------------------------------------------------------------------------------- /pkg/enet/disconnect_reasons.go: -------------------------------------------------------------------------------- 1 | package enet 2 | 3 | import "strconv" 4 | 5 | type ID uint32 6 | 7 | const ( 8 | None ID = iota 9 | EOP 10 | LocalMode // LOCAL 11 | Kick 12 | MessageError // MSGERR 13 | IPBanned // IPBAN 14 | PrivateMode // PRIVATE 15 | Full // MAXCLIENTS 16 | Timeout 17 | Overflow 18 | WrongPassword // PASSWORD 19 | ) 20 | 21 | func (dr ID) String() string { 22 | switch dr { 23 | case None: 24 | return "" 25 | case EOP: 26 | return "end of packet" 27 | case LocalMode: 28 | return "server is in local mode" 29 | case Kick: 30 | return "kicked/banned" 31 | case MessageError: 32 | return "message error" 33 | case IPBanned: 34 | return "ip is banned" 35 | case PrivateMode: 36 | return "server is in private mode" 37 | case Full: 38 | return "server full" 39 | case Timeout: 40 | return "connection timed out" 41 | case Overflow: 42 | return "overflow" 43 | case WrongPassword: 44 | return "invalid password" 45 | default: 46 | return strconv.Itoa(int(dr)) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pkg/enet/enet/.gitignore: -------------------------------------------------------------------------------- 1 | # Potential build directories 2 | [Aa][Rr][Mm]/ 3 | [Aa][Rr][Mm]64/ 4 | [Bb]in/ 5 | [Dd]ebug/ 6 | [Dd]ebugPublic/ 7 | [Ll]og/ 8 | [Ll]ogs/ 9 | [Oo]bj/ 10 | [Rr]elease/ 11 | [Rr]eleases/ 12 | [Ww][Ii][Nn]32/ 13 | bld/ 14 | build/ 15 | builds/ 16 | out/ 17 | x64/ 18 | x86/ 19 | 20 | # VS 21 | .vs/ 22 | .vscode/ 23 | !.vscode/extensions.json 24 | !.vscode/launch.json 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | 28 | # CMake 29 | _deps 30 | CMakeCache.txt 31 | CMakeFiles 32 | CMakeLists.txt.user 33 | CMakeScripts 34 | CMakeUserPresets.json 35 | CTestTestfile.cmake 36 | cmake_install.cmake 37 | compile_commands.json 38 | install_manifest.txt 39 | 40 | # Prerequisites 41 | *.d 42 | 43 | # Object files 44 | *.o 45 | *.ko 46 | *.obj 47 | *.elf 48 | 49 | # Linker output 50 | *.ilk 51 | *.map 52 | *.exp 53 | 54 | # Libraries 55 | *.lib 56 | *.a 57 | *.la 58 | *.lo 59 | 60 | # Shared objects 61 | *.dll 62 | *.so 63 | *.so.* 64 | *.dylib 65 | 66 | # Debug files 67 | *.dSYM/ 68 | *.su 69 | *.idb 70 | *.pdb 71 | -------------------------------------------------------------------------------- /pkg/enet/enet/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2024 Lee Salzman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /pkg/enet/enet/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-O3 -fomit-frame-pointer 2 | override CFLAGS:= $(CFLAGS) -Iinclude 3 | 4 | OBJS= \ 5 | callbacks.o \ 6 | compress.o \ 7 | host.o \ 8 | list.o \ 9 | packet.o \ 10 | peer.o \ 11 | protocol.o \ 12 | unix.o \ 13 | win32.o 14 | 15 | libenet.a: $(OBJS) 16 | $(AR) rcs $@ $(OBJS) 17 | 18 | default: libenet.a 19 | 20 | clean: 21 | -$(RM) libenet.a $(OBJS) 22 | 23 | -------------------------------------------------------------------------------- /pkg/enet/enet/Makefile.am: -------------------------------------------------------------------------------- 1 | pkgconfigdir = $(libdir)/pkgconfig 2 | nodist_pkgconfig_DATA = libenet.pc 3 | 4 | enetincludedir=$(includedir)/enet 5 | enetinclude_HEADERS = \ 6 | include/enet/callbacks.h \ 7 | include/enet/enet.h \ 8 | include/enet/list.h \ 9 | include/enet/protocol.h \ 10 | include/enet/time.h \ 11 | include/enet/types.h \ 12 | include/enet/unix.h \ 13 | include/enet/utility.h \ 14 | include/enet/win32.h 15 | 16 | lib_LTLIBRARIES = libenet.la 17 | libenet_la_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c protocol.c unix.c win32.c 18 | # see info '(libtool) Updating version info' before making a release 19 | libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:6:0 20 | AM_CPPFLAGS = -I$(top_srcdir)/include 21 | 22 | ACLOCAL_AMFLAGS = -Im4 23 | -------------------------------------------------------------------------------- /pkg/enet/enet/README: -------------------------------------------------------------------------------- 1 | Please visit the ENet homepage at http://sauerbraten.org/enet/ for installation 2 | and usage instructions. 3 | 4 | If you obtained this package from github, the quick description on how to build 5 | is: 6 | 7 | # Generate the build system. 8 | 9 | autoreconf -vfi 10 | 11 | # Compile and install the library. 12 | 13 | ./configure && make && make install 14 | 15 | 16 | -------------------------------------------------------------------------------- /pkg/enet/enet/callbacks.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file callbacks.c 3 | @brief ENet callback functions 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include "enet/enet.h" 7 | 8 | static ENetCallbacks callbacks = { malloc, free, abort }; 9 | 10 | int 11 | enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits) 12 | { 13 | if (version < ENET_VERSION_CREATE (1, 3, 0)) 14 | return -1; 15 | 16 | if (inits -> malloc != NULL || inits -> free != NULL) 17 | { 18 | if (inits -> malloc == NULL || inits -> free == NULL) 19 | return -1; 20 | 21 | callbacks.malloc = inits -> malloc; 22 | callbacks.free = inits -> free; 23 | } 24 | 25 | if (inits -> no_memory != NULL) 26 | callbacks.no_memory = inits -> no_memory; 27 | 28 | return enet_initialize (); 29 | } 30 | 31 | ENetVersion 32 | enet_linked_version (void) 33 | { 34 | return ENET_VERSION; 35 | } 36 | 37 | void * 38 | enet_malloc (size_t size) 39 | { 40 | void * memory = callbacks.malloc (size); 41 | 42 | if (memory == NULL) 43 | callbacks.no_memory (); 44 | 45 | return memory; 46 | } 47 | 48 | void 49 | enet_free (void * memory) 50 | { 51 | callbacks.free (memory); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /pkg/enet/enet/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([libenet], [1.3.18]) 2 | AC_CONFIG_SRCDIR([include/enet/enet.h]) 3 | AM_INIT_AUTOMAKE([foreign]) 4 | 5 | AC_CONFIG_MACRO_DIR([m4]) 6 | 7 | AC_PROG_CC 8 | AC_PROG_LIBTOOL 9 | 10 | AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAS_GETADDRINFO)]) 11 | AC_CHECK_FUNC(getnameinfo, [AC_DEFINE(HAS_GETNAMEINFO)]) 12 | AC_CHECK_FUNC(gethostbyaddr_r, [AC_DEFINE(HAS_GETHOSTBYADDR_R)]) 13 | AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAS_GETHOSTBYNAME_R)]) 14 | AC_CHECK_FUNC(poll, [AC_DEFINE(HAS_POLL)]) 15 | AC_CHECK_FUNC(fcntl, [AC_DEFINE(HAS_FCNTL)]) 16 | AC_CHECK_FUNC(inet_pton, [AC_DEFINE(HAS_INET_PTON)]) 17 | AC_CHECK_FUNC(inet_ntop, [AC_DEFINE(HAS_INET_NTOP)]) 18 | 19 | AC_CHECK_MEMBER(struct msghdr.msg_flags, [AC_DEFINE(HAS_MSGHDR_FLAGS)], , [#include ]) 20 | 21 | AC_CHECK_TYPE(socklen_t, [AC_DEFINE(HAS_SOCKLEN_T)], , 22 | #include 23 | #include 24 | ) 25 | 26 | AC_CONFIG_FILES([Makefile 27 | libenet.pc]) 28 | AC_OUTPUT 29 | -------------------------------------------------------------------------------- /pkg/enet/enet/include/enet/callbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file callbacks.h 3 | @brief ENet callbacks 4 | */ 5 | #ifndef __ENET_CALLBACKS_H__ 6 | #define __ENET_CALLBACKS_H__ 7 | 8 | #include 9 | 10 | typedef struct _ENetCallbacks 11 | { 12 | void * (ENET_CALLBACK * malloc) (size_t size); 13 | void (ENET_CALLBACK * free) (void * memory); 14 | void (ENET_CALLBACK * no_memory) (void); 15 | } ENetCallbacks; 16 | 17 | #ifdef __cplusplus 18 | extern "C" 19 | { 20 | #endif 21 | 22 | /** @defgroup callbacks ENet internal callbacks 23 | @{ 24 | @ingroup private 25 | */ 26 | 27 | extern void * enet_malloc (size_t); 28 | extern void enet_free (void *); 29 | 30 | /** @} */ 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif /* __ENET_CALLBACKS_H__ */ 37 | 38 | -------------------------------------------------------------------------------- /pkg/enet/enet/include/enet/list.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file list.h 3 | @brief ENet list management 4 | */ 5 | #ifndef __ENET_LIST_H__ 6 | #define __ENET_LIST_H__ 7 | 8 | #include 9 | 10 | typedef struct _ENetListNode 11 | { 12 | struct _ENetListNode * next; 13 | struct _ENetListNode * previous; 14 | } ENetListNode; 15 | 16 | typedef ENetListNode * ENetListIterator; 17 | 18 | typedef struct _ENetList 19 | { 20 | ENetListNode sentinel; 21 | } ENetList; 22 | 23 | #ifdef __cplusplus 24 | extern "C" 25 | { 26 | #endif 27 | 28 | extern void enet_list_clear (ENetList *); 29 | 30 | extern ENetListIterator enet_list_insert (ENetListIterator, void *); 31 | extern void * enet_list_remove (ENetListIterator); 32 | extern ENetListIterator enet_list_move (ENetListIterator, void *, void *); 33 | 34 | extern size_t enet_list_size (ENetList *); 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #define enet_list_begin(list) ((list) -> sentinel.next) 41 | #define enet_list_end(list) (& (list) -> sentinel) 42 | 43 | #define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list)) 44 | 45 | #define enet_list_next(iterator) ((iterator) -> next) 46 | #define enet_list_previous(iterator) ((iterator) -> previous) 47 | 48 | #define enet_list_front(list) ((void *) (list) -> sentinel.next) 49 | #define enet_list_back(list) ((void *) (list) -> sentinel.previous) 50 | 51 | #endif /* __ENET_LIST_H__ */ 52 | 53 | -------------------------------------------------------------------------------- /pkg/enet/enet/include/enet/time.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file time.h 3 | @brief ENet time constants and macros 4 | */ 5 | #ifndef __ENET_TIME_H__ 6 | #define __ENET_TIME_H__ 7 | 8 | #define ENET_TIME_OVERFLOW 86400000 9 | 10 | #define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) 11 | #define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) 12 | #define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) 13 | #define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) 14 | 15 | #define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) 16 | 17 | #endif /* __ENET_TIME_H__ */ 18 | 19 | -------------------------------------------------------------------------------- /pkg/enet/enet/include/enet/types.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file types.h 3 | @brief type definitions for ENet 4 | */ 5 | #ifndef __ENET_TYPES_H__ 6 | #define __ENET_TYPES_H__ 7 | 8 | typedef unsigned char enet_uint8; /**< unsigned 8-bit type */ 9 | typedef unsigned short enet_uint16; /**< unsigned 16-bit type */ 10 | typedef unsigned int enet_uint32; /**< unsigned 32-bit type */ 11 | 12 | #endif /* __ENET_TYPES_H__ */ 13 | 14 | -------------------------------------------------------------------------------- /pkg/enet/enet/include/enet/unix.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file unix.h 3 | @brief ENet Unix header 4 | */ 5 | #ifndef __ENET_UNIX_H__ 6 | #define __ENET_UNIX_H__ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef MSG_MAXIOVLEN 17 | #define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN 18 | #endif 19 | 20 | typedef int ENetSocket; 21 | 22 | #define ENET_SOCKET_NULL -1 23 | 24 | #define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ 25 | #define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ 26 | 27 | #define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */ 28 | #define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */ 29 | 30 | typedef struct 31 | { 32 | void * data; 33 | size_t dataLength; 34 | } ENetBuffer; 35 | 36 | #define ENET_CALLBACK 37 | 38 | #define ENET_API extern 39 | 40 | typedef fd_set ENetSocketSet; 41 | 42 | #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) 43 | #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) 44 | #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) 45 | #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) 46 | 47 | #endif /* __ENET_UNIX_H__ */ 48 | 49 | -------------------------------------------------------------------------------- /pkg/enet/enet/include/enet/utility.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file utility.h 3 | @brief ENet utility header 4 | */ 5 | #ifndef __ENET_UTILITY_H__ 6 | #define __ENET_UTILITY_H__ 7 | 8 | #define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) 9 | #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) 10 | #define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y)) 11 | 12 | #endif /* __ENET_UTILITY_H__ */ 13 | 14 | -------------------------------------------------------------------------------- /pkg/enet/enet/include/enet/win32.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file win32.h 3 | @brief ENet Win32 header 4 | */ 5 | #ifndef __ENET_WIN32_H__ 6 | #define __ENET_WIN32_H__ 7 | 8 | #ifdef _MSC_VER 9 | #ifdef ENET_BUILDING_LIB 10 | #pragma warning (disable: 4267) // size_t to int conversion 11 | #pragma warning (disable: 4244) // 64bit to 32bit int 12 | #pragma warning (disable: 4018) // signed/unsigned mismatch 13 | #pragma warning (disable: 4146) // unary minus operator applied to unsigned type 14 | #ifndef _CRT_SECURE_NO_DEPRECATE 15 | #define _CRT_SECURE_NO_DEPRECATE 16 | #endif 17 | #ifndef _CRT_SECURE_NO_WARNINGS 18 | #define _CRT_SECURE_NO_WARNINGS 19 | #endif 20 | #endif 21 | #endif 22 | 23 | #include 24 | #include 25 | 26 | typedef SOCKET ENetSocket; 27 | 28 | #define ENET_SOCKET_NULL INVALID_SOCKET 29 | 30 | #define ENET_HOST_TO_NET_16(value) (htons (value)) 31 | #define ENET_HOST_TO_NET_32(value) (htonl (value)) 32 | 33 | #define ENET_NET_TO_HOST_16(value) (ntohs (value)) 34 | #define ENET_NET_TO_HOST_32(value) (ntohl (value)) 35 | 36 | typedef struct 37 | { 38 | size_t dataLength; 39 | void * data; 40 | } ENetBuffer; 41 | 42 | #define ENET_CALLBACK __cdecl 43 | 44 | #ifdef ENET_DLL 45 | #ifdef ENET_BUILDING_LIB 46 | #define ENET_API __declspec( dllexport ) 47 | #else 48 | #define ENET_API __declspec( dllimport ) 49 | #endif /* ENET_BUILDING_LIB */ 50 | #else /* !ENET_DLL */ 51 | #define ENET_API extern 52 | #endif /* ENET_DLL */ 53 | 54 | typedef fd_set ENetSocketSet; 55 | 56 | #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) 57 | #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) 58 | #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) 59 | #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) 60 | 61 | #endif /* __ENET_WIN32_H__ */ 62 | 63 | 64 | -------------------------------------------------------------------------------- /pkg/enet/enet/libenet.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr/local 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: libenet 7 | Description: Low-latency UDP networking library supporting optional reliability 8 | Version: 1.3.18 9 | Cflags: -I${includedir} 10 | Libs: -L${libdir} -lenet 11 | -------------------------------------------------------------------------------- /pkg/enet/enet/libenet.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: @PACKAGE_NAME@ 7 | Description: Low-latency UDP networking library supporting optional reliability 8 | Version: @PACKAGE_VERSION@ 9 | Cflags: -I${includedir} 10 | Libs: -L${libdir} -lenet 11 | -------------------------------------------------------------------------------- /pkg/enet/enet/list.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file list.c 3 | @brief ENet linked list functions 4 | */ 5 | #define ENET_BUILDING_LIB 1 6 | #include "enet/enet.h" 7 | 8 | /** 9 | @defgroup list ENet linked list utility functions 10 | @ingroup private 11 | @{ 12 | */ 13 | void 14 | enet_list_clear (ENetList * list) 15 | { 16 | list -> sentinel.next = & list -> sentinel; 17 | list -> sentinel.previous = & list -> sentinel; 18 | } 19 | 20 | ENetListIterator 21 | enet_list_insert (ENetListIterator position, void * data) 22 | { 23 | ENetListIterator result = (ENetListIterator) data; 24 | 25 | result -> previous = position -> previous; 26 | result -> next = position; 27 | 28 | result -> previous -> next = result; 29 | position -> previous = result; 30 | 31 | return result; 32 | } 33 | 34 | void * 35 | enet_list_remove (ENetListIterator position) 36 | { 37 | position -> previous -> next = position -> next; 38 | position -> next -> previous = position -> previous; 39 | 40 | return position; 41 | } 42 | 43 | ENetListIterator 44 | enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast) 45 | { 46 | ENetListIterator first = (ENetListIterator) dataFirst, 47 | last = (ENetListIterator) dataLast; 48 | 49 | first -> previous -> next = last -> next; 50 | last -> next -> previous = first -> previous; 51 | 52 | first -> previous = position -> previous; 53 | last -> next = position; 54 | 55 | first -> previous -> next = first; 56 | position -> previous = last; 57 | 58 | return first; 59 | } 60 | 61 | size_t 62 | enet_list_size (ENetList * list) 63 | { 64 | size_t size = 0; 65 | ENetListIterator position; 66 | 67 | for (position = enet_list_begin (list); 68 | position != enet_list_end (list); 69 | position = enet_list_next (position)) 70 | ++ size; 71 | 72 | return size; 73 | } 74 | 75 | /** @} */ 76 | -------------------------------------------------------------------------------- /pkg/enet/event.go: -------------------------------------------------------------------------------- 1 | package enet 2 | 3 | /* 4 | #cgo LDFLAGS: -L./enet -lenet 5 | #cgo CFLAGS: -I./enet/include 6 | #include 7 | */ 8 | import "C" 9 | 10 | type EventType uint 11 | 12 | const ( 13 | EventTypeConnect = C.ENET_EVENT_TYPE_CONNECT 14 | EventTypeDisconnect = C.ENET_EVENT_TYPE_DISCONNECT 15 | EventTypeReceive = C.ENET_EVENT_TYPE_RECEIVE 16 | ) 17 | 18 | type Event struct { 19 | Type EventType 20 | Peer *Peer 21 | ChannelID uint8 22 | Data uint32 23 | Packet *Packet 24 | } 25 | 26 | func (h *Host) eventFromCEvent(cEvent *C.ENetEvent) Event { 27 | e := Event{ 28 | Type: EventType(cEvent._type), 29 | Peer: h.peerFromCPeer(cEvent.peer, h), 30 | ChannelID: uint8(cEvent.channelID), 31 | Data: uint32(cEvent.data), 32 | } 33 | 34 | if e.Type == EventTypeReceive { 35 | e.Packet = packetFromCPacket(cEvent.packet) 36 | C.enet_packet_destroy(cEvent.packet) 37 | } 38 | 39 | return e 40 | 41 | } 42 | -------------------------------------------------------------------------------- /pkg/enet/packet.go: -------------------------------------------------------------------------------- 1 | package enet 2 | 3 | /* 4 | #cgo LDFLAGS: -L./enet -lenet 5 | #cgo CFLAGS: -I./enet/include 6 | #include 7 | */ 8 | import "C" 9 | 10 | import ( 11 | "unsafe" 12 | ) 13 | 14 | const ( 15 | PacketFlagNone = 0 16 | PacketFlagReliable = (1 << 0) 17 | PacketFlagUnsequenced = (1 << 1) 18 | PacketFlagNoAllocate = (1 << 2) 19 | PacketFlagUnreliableFragment = (1 << 3) 20 | PacketFlagSent = (1 << 8) 21 | ) 22 | 23 | type Packet struct { 24 | Flags uint32 // bitwise-or of ENetPacketFlag constants 25 | Data []byte // allocated data for packet 26 | } 27 | 28 | func packetFromCPacket(cPacket *C.ENetPacket) *Packet { 29 | if cPacket == nil { 30 | return nil 31 | } 32 | 33 | return &Packet{ 34 | Flags: uint32(cPacket.flags), 35 | Data: C.GoBytes(unsafe.Pointer(cPacket.data), C.int(cPacket.dataLength)), 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pkg/gameserver/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2014-2019, Alexander Willing 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /pkg/gameserver/client.go: -------------------------------------------------------------------------------- 1 | package gameserver 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | 8 | "github.com/cfoust/sour/pkg/game/protocol" 9 | "github.com/cfoust/sour/pkg/gameserver/game" 10 | "github.com/cfoust/sour/pkg/gameserver/protocol/disconnectreason" 11 | "github.com/cfoust/sour/pkg/gameserver/protocol/role" 12 | "github.com/cfoust/sour/pkg/gameserver/relay" 13 | ) 14 | 15 | var rng = rand.New(rand.NewSource(time.Now().UnixNano())) 16 | 17 | type Authentication struct { 18 | reqID uint32 19 | name string 20 | } 21 | 22 | // Describes a client. 23 | type Client struct { 24 | game.Player 25 | 26 | Role role.ID 27 | Joined bool // true if the player is actually in the game 28 | AuthRequiredBecause disconnectreason.ID // e.g. server is in private mode 29 | SessionID uint32 30 | Ping int32 31 | Positions *relay.Publisher 32 | Packets *relay.Publisher 33 | Authentications map[string]*Authentication 34 | 35 | connected chan bool 36 | outgoing Outgoing 37 | 38 | server *Server 39 | } 40 | 41 | func NewClient(cn uint32, sessionId uint32, outgoing Outgoing) *Client { 42 | return &Client{ 43 | Player: game.NewPlayer(cn), 44 | SessionID: sessionId, 45 | Authentications: map[string]*Authentication{}, 46 | outgoing: outgoing, 47 | } 48 | } 49 | 50 | func (c *Client) GrantMaster() { 51 | c.server._setRole(c, role.Master) 52 | } 53 | 54 | func (c *Client) RefreshWelcome() { 55 | c.server.SendWelcome(c) 56 | } 57 | 58 | func (c *Client) String() string { 59 | return fmt.Sprintf("%s (%d:%d)", c.Name, c.CN, c.SessionID) 60 | } 61 | 62 | func (c *Client) Message(text string) { 63 | c.Send(protocol.ServerMessage{Text: text}) 64 | } 65 | 66 | func (c *Client) Send(messages ...protocol.Message) { 67 | c.outgoing <- ServerPacket{ 68 | Session: c.SessionID, 69 | Channel: 1, 70 | Messages: messages, 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /pkg/gameserver/config.go: -------------------------------------------------------------------------------- 1 | package gameserver 2 | 3 | type Config struct { 4 | MaxClients int 5 | MatchLength int 6 | DefaultGameSpeed int 7 | DefaultMode string 8 | DefaultMap string 9 | Maps []string 10 | } 11 | -------------------------------------------------------------------------------- /pkg/gameserver/game.go: -------------------------------------------------------------------------------- 1 | package gameserver 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cfoust/sour/pkg/gameserver/game" 7 | "github.com/cfoust/sour/pkg/gameserver/protocol/gamemode" 8 | ) 9 | 10 | func (s *Server) StartMode(id gamemode.ID) game.Mode { 11 | switch id { 12 | case gamemode.FFA: 13 | return game.NewFFA(s) 14 | case gamemode.CoopEdit: 15 | return game.NewCoopEdit(s) 16 | case gamemode.Insta: 17 | return game.NewInsta(s) 18 | case gamemode.InstaTeam: 19 | return game.NewInstaTeam(s, s.KeepTeams) 20 | case gamemode.Effic: 21 | return game.NewEffic(s) 22 | case gamemode.Teamplay: 23 | return game.NewTeamplay(s, s.KeepTeams) 24 | case gamemode.EfficTeam: 25 | return game.NewEfficTeam(s, s.KeepTeams) 26 | case gamemode.Tactics: 27 | return game.NewTactics(s) 28 | case gamemode.TacticsTeam: 29 | return game.NewTacticsTeam(s, s.KeepTeams) 30 | case gamemode.CTF: 31 | return game.NewCTF(s, s.KeepTeams) 32 | case gamemode.InstaCTF: 33 | return game.NewInstaCTF(s, s.KeepTeams) 34 | case gamemode.EfficCTF: 35 | return game.NewEfficCTF(s, s.KeepTeams) 36 | default: 37 | panic(fmt.Sprintf("unhandled gamemode ID %d", id)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pkg/gameserver/game/capture.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | type CaptureMode interface { 4 | TeamMode 5 | Bases(*Team) []int32 6 | } 7 | 8 | type captureMode struct { 9 | teamMode 10 | bases map[*Team][]int32 11 | } 12 | 13 | func (cm *captureMode) Bases(t *Team) []int32 { 14 | if bases, ok := cm.bases[t]; ok { 15 | return bases 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /pkg/gameserver/game/coop.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | P "github.com/cfoust/sour/pkg/game/protocol" 5 | "github.com/cfoust/sour/pkg/gameserver/protocol/gamemode" 6 | "github.com/cfoust/sour/pkg/gameserver/protocol/playerstate" 7 | ) 8 | 9 | type CoopEdit struct { 10 | *teamlessMode 11 | *handlesPickups 12 | 13 | noSpawnWait 14 | ffaSpawnState 15 | 16 | s Server 17 | } 18 | 19 | func (*CoopEdit) ID() gamemode.ID { return gamemode.CoopEdit } 20 | 21 | // assert interface implementations at compile time 22 | var ( 23 | _ Mode = &CoopEdit{} 24 | _ PickupMode = &CoopEdit{} 25 | ) 26 | 27 | func NewCoopEdit(s Server) *CoopEdit { 28 | return &CoopEdit{ 29 | handlesPickups: handlingPickups(s), 30 | teamlessMode: withoutTeams(s), 31 | s: s, 32 | } 33 | } 34 | 35 | func (m *CoopEdit) HandlePacket(p *Player, message P.Message) bool { 36 | switch message.Type() { 37 | case P.N_EDITMODE: 38 | msg := message.(P.EditMode) 39 | enabled := msg.Enabled 40 | 41 | if enabled && p.State == playerstate.Spectator { 42 | return true 43 | } 44 | 45 | if !enabled && p.State != playerstate.Editing { 46 | return true 47 | } 48 | 49 | if enabled { 50 | p.EditState = p.State 51 | p.State = playerstate.Editing 52 | 53 | // TODO 54 | //ci->events.setsize(0); 55 | //ci->state.rockets.reset(); 56 | //ci->state.grenades.reset(); 57 | } else { 58 | p.State = p.EditState 59 | } 60 | 61 | return true 62 | default: 63 | return m.handlesPickups.HandlePacket(p, message) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /pkg/gameserver/game/game_test.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "testing" 7 | "time" 8 | 9 | "github.com/cfoust/sour/pkg/gameserver/protocol/nmc" 10 | ) 11 | 12 | var ( 13 | _ Server = &mockServer{} 14 | //_ Player = &mockPlayer{} 15 | ) 16 | 17 | type mockServer struct{} 18 | 19 | func (s *mockServer) GameDuration() time.Duration { return 10 * time.Minute } 20 | 21 | func (s *mockServer) Broadcast(nmc.ID, ...interface{}) {} 22 | 23 | func (s *mockServer) Intermission() {} 24 | 25 | func (s *mockServer) ForEachPlayer(func(*Player)) {} 26 | 27 | func (s *mockServer) UniqueName(p *Player) string { return fmt.Sprintf("%v", p) } 28 | 29 | func (s *mockServer) NumberOfPlayers() int { return 5 } 30 | 31 | func TestCompetitiveMode(t *testing.T) { 32 | s := &mockServer{} 33 | 34 | timing := NewCompetitiveClock(s) 35 | 36 | var mode Mode = NewEfficCTF(s, true, timing) 37 | 38 | log.Printf("%T", mode) 39 | 40 | teamed, ok := mode.(TeamMode) 41 | if !ok { 42 | t.Error("effic ctf is not a team mode") 43 | return 44 | } 45 | 46 | _, ok = mode.(Clock) 47 | if !ok { 48 | t.Error("effic ctf is not a timed mode") 49 | return 50 | } 51 | 52 | p1, p2 := NewPlayer(1), NewPlayer(2) 53 | 54 | teamed.Join(&p1) 55 | 56 | if countPlayers(teamed) != 1 { 57 | t.Error("after one player joined, player count is not 1") 58 | } 59 | 60 | teamed.Join(&p2) 61 | 62 | if countPlayers(teamed) != 2 { 63 | t.Error("after two players joined, player count is not 2") 64 | } 65 | } 66 | 67 | func countPlayers(tm TeamMode) (sum int) { 68 | tm.ForEachTeam(func(t *Team) { sum += len(t.Players) }) 69 | return 70 | } 71 | -------------------------------------------------------------------------------- /pkg/gameserver/game/mode.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "time" 5 | 6 | P "github.com/cfoust/sour/pkg/game/protocol" 7 | "github.com/cfoust/sour/pkg/gameserver/protocol/gamemode" 8 | ) 9 | 10 | type Mode interface { 11 | HasTimers 12 | ID() gamemode.ID 13 | NeedsMapInfo() bool 14 | Leave(*Player) 15 | CanSpawn(*Player) bool 16 | Spawn(*PlayerState) // sets armour, ammo, and health 17 | HandleFrag(fragger, victim *Player) 18 | } 19 | 20 | type HandlesPackets interface { 21 | HandlePacket(*Player, P.Message) bool 22 | } 23 | 24 | type noSpawnWait struct{} 25 | 26 | func (*noSpawnWait) CanSpawn(*Player) bool { return true } 27 | 28 | type fiveSecondsSpawnWait struct{} 29 | 30 | func (*fiveSecondsSpawnWait) CanSpawn(p *Player) bool { 31 | return p.LastDeath.IsZero() || time.Since(p.LastDeath) > 5*time.Second 32 | } 33 | 34 | // simple frag handling 35 | type teamlessMode struct { 36 | s Server 37 | } 38 | 39 | func withoutTeams(s Server) *teamlessMode { 40 | return &teamlessMode{ 41 | s: s, 42 | } 43 | } 44 | 45 | func (m *teamlessMode) HandleFrag(actor, victim *Player) { 46 | victim.Die() 47 | if actor == victim { 48 | actor.Frags-- 49 | } else { 50 | actor.Frags++ 51 | } 52 | m.s.Broadcast(P.Died{ 53 | Client: int32(victim.CN), 54 | Killer: int32(actor.CN), 55 | KillerFrags: actor.Frags, 56 | VictimFrags: actor.Team.Frags, 57 | }) 58 | } 59 | 60 | func (m *teamlessMode) Leave(*Player) {} 61 | 62 | type HasTimers interface { 63 | Pause() 64 | Resume() 65 | Leave(*Player) 66 | CleanUp() 67 | } 68 | 69 | type noTimers struct{} 70 | 71 | func (*noTimers) Pause() {} 72 | 73 | func (*noTimers) Resume() {} 74 | 75 | func (*noTimers) Leave(*Player) {} 76 | 77 | func (*noTimers) CleanUp() {} 78 | -------------------------------------------------------------------------------- /pkg/gameserver/game/player.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "github.com/cfoust/sour/pkg/gameserver/geom" 5 | "github.com/cfoust/sour/pkg/gameserver/protocol/weapon" 6 | ) 7 | 8 | type Player struct { 9 | CN uint32 10 | Name string 11 | Team *Team 12 | Model int32 13 | Position *geom.Vector 14 | PlayerState 15 | } 16 | 17 | func NewPlayer(cn uint32) Player { 18 | return Player{ 19 | CN: cn, 20 | Team: NoTeam, 21 | PlayerState: NewPlayerState(), 22 | } 23 | } 24 | 25 | func (p *Player) ApplyDamage(attacker *Player, damage int32, weapon weapon.ID, direction *geom.Vector) { 26 | p.PlayerState.applyDamage(damage) 27 | if attacker != p && attacker.Team != p.Team { 28 | attacker.Damage += damage 29 | } 30 | 31 | // TODO quad? 32 | } 33 | 34 | func (p *Player) Reset() { 35 | // keep the CN, so low CNs can be reused 36 | p.Name = "" 37 | p.Team = NoTeam 38 | p.Model = -1 39 | p.Position = nil 40 | p.PlayerState.Reset() 41 | } 42 | -------------------------------------------------------------------------------- /pkg/gameserver/game/server.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/cfoust/sour/pkg/game/protocol" 7 | ) 8 | 9 | type Server interface { 10 | GameDuration() time.Duration 11 | Broadcast(messages ...protocol.Message) 12 | Message(message string) 13 | Intermission() 14 | ForEachPlayer(func(*Player)) 15 | UniqueName(*Player) string 16 | NumberOfPlayers() int 17 | } 18 | -------------------------------------------------------------------------------- /pkg/gameserver/game/team.go: -------------------------------------------------------------------------------- 1 | package game 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | var rng = rand.New(rand.NewSource(time.Now().UnixNano())) 9 | 10 | type Team struct { 11 | Name string 12 | Frags int32 13 | Score int32 14 | Players map[*Player]struct{} 15 | } 16 | 17 | func NewTeam(name string) *Team { 18 | return &Team{ 19 | Name: name, 20 | Players: map[*Player]struct{}{}, 21 | } 22 | } 23 | 24 | var NoTeam = &Team{Name: "none"} 25 | 26 | // sorts teams ascending by size, then score 27 | type BySizeAndScore []*Team 28 | 29 | func (teams BySizeAndScore) Len() int { 30 | return len(teams) 31 | } 32 | 33 | func (teams BySizeAndScore) Swap(i, j int) { 34 | teams[i], teams[j] = teams[j], teams[i] 35 | } 36 | 37 | func (teams BySizeAndScore) Less(i, j int) bool { 38 | if len(teams[i].Players) != len(teams[j].Players) { 39 | return len(teams[i].Players) < len(teams[j].Players) 40 | } 41 | if teams[i].Score != teams[j].Score { 42 | return teams[i].Score < teams[j].Score 43 | } 44 | if teams[i].Frags != teams[j].Frags { 45 | return teams[i].Frags < teams[j].Frags 46 | } 47 | return rng.Intn(2) == 0 48 | } 49 | 50 | func (t *Team) Add(p *Player) { 51 | t.Players[p] = struct{}{} 52 | p.Team = t 53 | } 54 | 55 | func (t *Team) Remove(p *Player) { 56 | p.Team = NoTeam 57 | delete(t.Players, p) 58 | } 59 | -------------------------------------------------------------------------------- /pkg/gameserver/geom/vector.go: -------------------------------------------------------------------------------- 1 | package geom 2 | 3 | import "math" 4 | 5 | const ( 6 | DNF = 100.0 7 | DMF = 16.0 8 | ) 9 | 10 | type Vector struct { 11 | x, y, z float64 12 | } 13 | 14 | func NewVector(x, y, z float64) *Vector { 15 | return &Vector{x, y, z} 16 | } 17 | 18 | func (v *Vector) X() float64 { return v.x } 19 | func (v *Vector) Y() float64 { return v.y } 20 | func (v *Vector) Z() float64 { return v.z } 21 | 22 | func (v *Vector) IsZero() bool { return v.x == 0 && v.y == 0 && v.z == 0 } 23 | 24 | func (v *Vector) Magnitude() float64 { 25 | return math.Sqrt(v.x*v.x + v.y*v.y + v.z*v.z) 26 | } 27 | 28 | func (v *Vector) Sub(o *Vector) *Vector { 29 | return NewVector(v.x-o.x, v.y-o.y, v.z-o.z) 30 | } 31 | 32 | func (v *Vector) Mul(k float64) *Vector { 33 | return NewVector(v.x*k, v.y*k, v.z*k) 34 | } 35 | 36 | func (v *Vector) Scale(k float64) *Vector { 37 | if mag := v.Magnitude(); mag > 1e-6 { 38 | return v.Mul(k / mag) 39 | } 40 | return NewVector(v.x, v.y, v.z) 41 | } 42 | 43 | func Distance(from, to *Vector) float64 { 44 | return from.Sub(to).Magnitude() 45 | } 46 | -------------------------------------------------------------------------------- /pkg/gameserver/pausableticker/pausable_ticker.go: -------------------------------------------------------------------------------- 1 | package pausableticker 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sasha-s/go-deadlock" 7 | ) 8 | 9 | type Ticker struct { 10 | C <-chan time.Time // The channel on which the ticks are delivered. 11 | 12 | deadlock.Mutex 13 | pause chan bool 14 | paused bool 15 | stop chan struct{} 16 | ticker *time.Ticker 17 | } 18 | 19 | func New(d time.Duration) *Ticker { 20 | c := make(chan time.Time) 21 | pause := make(chan bool) 22 | stop := make(chan struct{}) 23 | ticker := time.NewTicker(d) 24 | 25 | t := &Ticker{ 26 | C: c, 27 | pause: pause, 28 | stop: stop, 29 | ticker: ticker, 30 | } 31 | 32 | go t.run(c) 33 | 34 | return t 35 | } 36 | 37 | func (t *Ticker) run(c chan<- time.Time) { 38 | defer close(t.stop) 39 | 40 | for { 41 | select { 42 | case c <- <-t.ticker.C: 43 | case shouldPause := <-t.pause: 44 | if shouldPause { 45 | t.paused = true 46 | for shouldPause { 47 | select { 48 | case shouldPause = <-t.pause: 49 | case <-t.stop: 50 | return 51 | } 52 | } 53 | t.paused = false 54 | } 55 | case <-t.stop: 56 | return 57 | } 58 | } 59 | } 60 | 61 | func (t *Ticker) Pause() { 62 | t.Lock() 63 | defer t.Unlock() 64 | 65 | if t.pause != nil { 66 | t.pause <- true 67 | } 68 | } 69 | 70 | func (t *Ticker) Paused() bool { 71 | return t.paused 72 | } 73 | 74 | func (t *Ticker) Resume() { 75 | t.Lock() 76 | defer t.Unlock() 77 | 78 | if t.pause != nil { 79 | t.pause <- false 80 | } 81 | } 82 | 83 | func (t *Ticker) Stop() { 84 | t.Lock() 85 | defer t.Unlock() 86 | 87 | if t.stop != nil { 88 | close(t.pause) 89 | t.pause = nil 90 | t.stop <- struct{}{} 91 | <-t.stop 92 | t.stop = nil 93 | go t.ticker.Stop() 94 | } 95 | } 96 | 97 | func (t *Ticker) Stopped() bool { 98 | return t.stop == nil 99 | } 100 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/armour/armour.go: -------------------------------------------------------------------------------- 1 | package armour 2 | 3 | import "github.com/cfoust/sour/pkg/gameserver/protocol/gamemode" 4 | 5 | type ID int32 6 | 7 | const ( 8 | Blue ID = iota 9 | Green 10 | Yellow 11 | 12 | None = -1 13 | ) 14 | 15 | func Absorption(typ ID) int32 { 16 | switch typ { 17 | case Blue: 18 | return 25 19 | case Green: 20 | return 50 21 | case Yellow: 22 | return 75 23 | default: 24 | return 0 25 | } 26 | } 27 | 28 | func SpawnArmour(mode gamemode.ID) (ID, int32) { 29 | switch mode { 30 | case gamemode.Insta, 31 | gamemode.InstaTeam, 32 | gamemode.InstaCTF, 33 | gamemode.InstaProtect, 34 | gamemode.InstaHold, 35 | gamemode.InstaCollect: 36 | return None, 0 37 | case gamemode.Tactics, 38 | gamemode.TacticsTeam, 39 | gamemode.Effic, 40 | gamemode.EfficTeam, 41 | gamemode.EfficCTF, 42 | gamemode.EfficProtect, 43 | gamemode.EfficHold, 44 | gamemode.EfficCollect: 45 | return Green, 100 46 | case gamemode.CTF, 47 | gamemode.Protect, 48 | gamemode.Hold, 49 | gamemode.Collect: 50 | return Blue, 50 51 | case gamemode.Capture, 52 | gamemode.RegenCapture, 53 | gamemode.FFA, 54 | gamemode.Teamplay: 55 | return Blue, 25 56 | default: 57 | println("unhandled gamemode:", mode) 58 | panic("fix this!") 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/cubecode/README.md: -------------------------------------------------------------------------------- 1 | # CubeCode 2 | 3 | A basic Go package to parse Cube 2: Sauerbraten network messages. 4 | 5 | This package offers easy methods to read Sauerbraten network messages with Go and does integer decompression and character translation to Unicode for you. -------------------------------------------------------------------------------- /pkg/gameserver/protocol/cubecode/colors.go: -------------------------------------------------------------------------------- 1 | package cubecode 2 | 3 | // from engine/rendertext.cpp 4 | const ( 5 | green = "\f0" // player talk 6 | blue = "\f1" // "echo" command 7 | yellow = "\f2" // gameplay messages 8 | red = "\f3" // important errors 9 | gray = "\f4" 10 | magenta = "\f5" 11 | orange = "\f6" 12 | white = "\f7" 13 | 14 | save = "\fs" 15 | restore = "\fr" 16 | ) 17 | 18 | func wrap(s, color string) string { 19 | return save + color + s + restore 20 | } 21 | 22 | func Green(s string) string { return wrap(s, green) } 23 | func Blue(s string) string { return wrap(s, blue) } 24 | func Yellow(s string) string { return wrap(s, yellow) } 25 | func Red(s string) string { return wrap(s, red) } 26 | func Gray(s string) string { return wrap(s, gray) } 27 | func Magenta(s string) string { return wrap(s, magenta) } 28 | func Orange(s string) string { return wrap(s, orange) } 29 | func White(s string) string { return wrap(s, white) } 30 | 31 | func Success(s string) string { return Green(s) } 32 | func Fail(s string) string { return Orange(s) } 33 | func Error(s string) string { return Red(s) } 34 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/cubecode/sanitize.go: -------------------------------------------------------------------------------- 1 | package cubecode 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | "unicode" 7 | ) 8 | 9 | // Matches sauer color codes (sauer uses form feed followed by a digit, e.g. \f3 for red) 10 | var sauerStringsSanitizer = regexp.MustCompile("\\f.") 11 | 12 | // SanitizeString returns the string, cleared of sauer color codes like \f3 for red. 13 | func SanitizeString(s string) string { 14 | s = sauerStringsSanitizer.ReplaceAllLiteralString(s, "") 15 | return strings.TrimSpace(s) 16 | } 17 | 18 | func Filter(s string, whitespaceAllowed bool) (filtered string) { 19 | s = SanitizeString(s) 20 | 21 | for _, r := range s { 22 | if unicode.IsPrint(r) && (whitespaceAllowed || r != ' ') { 23 | filtered += string(r) 24 | } 25 | } 26 | 27 | return 28 | } 29 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/disconnectreason/disconnect_reasons.go: -------------------------------------------------------------------------------- 1 | package disconnectreason 2 | 3 | import "strconv" 4 | 5 | type ID uint32 6 | 7 | const ( 8 | None ID = iota 9 | EOP 10 | LocalMode // LOCAL 11 | Kick 12 | MessageError // MSGERR 13 | IPBanned // IPBAN 14 | PrivateMode // PRIVATE 15 | Full // MAXCLIENTS 16 | Timeout 17 | Overflow 18 | WrongPassword // PASSWORD 19 | ) 20 | 21 | func (dr ID) String() string { 22 | switch dr { 23 | case None: 24 | return "" 25 | case EOP: 26 | return "end of packet" 27 | case LocalMode: 28 | return "server is in local mode" 29 | case Kick: 30 | return "kicked/banned" 31 | case MessageError: 32 | return "message error" 33 | case IPBanned: 34 | return "ip is banned" 35 | case PrivateMode: 36 | return "server is in private mode" 37 | case Full: 38 | return "server full" 39 | case Timeout: 40 | return "connection timed out" 41 | case Overflow: 42 | return "overflow" 43 | case WrongPassword: 44 | return "invalid password" 45 | default: 46 | return strconv.Itoa(int(dr)) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/entity/entities.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type ID int32 4 | 5 | const ( 6 | NotUsed ID = iota 7 | LIGHT 8 | MAPMODEL 9 | PLAYERSTART 10 | ENVMAP 11 | PARTICLES 12 | MAPSOUND 13 | SPOTLIGHT 14 | PickupShotgun // 8 15 | PickupMinigun 16 | PickupRocketLauncher 17 | PickupRifle 18 | PickupGrenadeLauncher 19 | PickupPistol 20 | PickupHealth 21 | PickupBoost 22 | PickupGreenArmour 23 | PickupYellowArmor 24 | PickupQuadDamage 25 | Teleport 26 | Teledest 27 | Monster 28 | CARROT 29 | JUMPPAD 30 | BASE 31 | RESPAWNPOINT 32 | BOX 33 | BARREL 34 | PLATFORM 35 | ELEVATOR 36 | FLAG 37 | MAXENTTYPES 38 | ) 39 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/entity/pickups.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "github.com/cfoust/sour/pkg/gameserver/protocol/sound" 5 | ) 6 | 7 | type Pickup struct { 8 | Typ ID 9 | Sound sound.ID 10 | Amount int32 11 | MaxAmount int32 12 | } 13 | 14 | var Pickups map[ID]Pickup = map[ID]Pickup{ 15 | PickupShotgun: Pickup{PickupShotgun, sound.PickUpAmmo, 10, 30}, 16 | PickupMinigun: Pickup{PickupMinigun, sound.PickUpAmmo, 20, 60}, 17 | PickupRocketLauncher: Pickup{PickupRocketLauncher, sound.PickUpAmmo, 5, 15}, 18 | PickupRifle: Pickup{PickupRifle, sound.PickUpAmmo, 5, 15}, 19 | PickupGrenadeLauncher: Pickup{PickupGrenadeLauncher, sound.PickUpAmmo, 10, 30}, 20 | PickupPistol: Pickup{PickupPistol, sound.PickUpAmmo, 30, 120}, 21 | PickupHealth: Pickup{PickupHealth, sound.PickUpHealth, 25, 100}, 22 | PickupBoost: Pickup{PickupBoost, sound.PickUpHealth, 50, 200}, 23 | PickupGreenArmour: Pickup{PickupGreenArmour, sound.PickUpArmour, 100, 100}, 24 | PickupYellowArmor: Pickup{PickupYellowArmor, sound.PickUpArmour, 200, 200}, 25 | PickupQuadDamage: Pickup{PickupQuadDamage, sound.PickUpQuaddamage, 20000, 30000}, 26 | } 27 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/mastermode/master_mode.go: -------------------------------------------------------------------------------- 1 | package mastermode 2 | 3 | import "strconv" 4 | 5 | type ID int32 6 | 7 | const ( 8 | Auth ID = iota - 1 9 | Open 10 | Veto 11 | Locked 12 | Private 13 | ) 14 | 15 | func (mm ID) String() string { 16 | switch mm { 17 | case Auth: 18 | return "auth" 19 | case Open: 20 | return "open" 21 | case Veto: 22 | return "veto" 23 | case Locked: 24 | return "locked" 25 | case Private: 26 | return "private" 27 | default: 28 | return strconv.Itoa(int(mm)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/playerstate/player_state.go: -------------------------------------------------------------------------------- 1 | package playerstate 2 | 3 | type ID uint32 4 | 5 | const ( 6 | Alive ID = iota 7 | Dead 8 | _ // Spawning, not used on server side 9 | _ // Lagged, not used on server side 10 | Editing 11 | Spectator 12 | ) 13 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/role/role.go: -------------------------------------------------------------------------------- 1 | package role 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | ) 7 | 8 | type ID int32 9 | 10 | const ( 11 | None ID = iota 12 | Master 13 | Auth 14 | Admin 15 | ) 16 | 17 | func Parse(s string) ID { 18 | switch strings.ToLower(s) { 19 | case "none": 20 | return None 21 | case "master": 22 | return Master 23 | case "auth": 24 | return Auth 25 | case "admin": 26 | return Admin 27 | default: 28 | return -1 29 | } 30 | } 31 | 32 | func (r ID) String() string { 33 | switch r { 34 | case None: 35 | return "none" 36 | case Master: 37 | return "master" 38 | case Auth: 39 | return "auth" 40 | case Admin: 41 | return "admin" 42 | default: 43 | return strconv.Itoa(int(r)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/sound/sound.go: -------------------------------------------------------------------------------- 1 | package sound 2 | 3 | type ID int32 4 | 5 | const ( 6 | Jump ID = iota 7 | Land 8 | Rifle 9 | Saw 10 | Shotgun 11 | Minigun 12 | RocketLaunch 13 | RocketHit 14 | Weaponload 15 | PickUpAmmo 16 | PickUpHealth 17 | PickUpArmour 18 | PickUpQuaddamage 19 | ItemSpawn 20 | Teleport 21 | NoAmmo 22 | QuaddamageOver 23 | Pain1 24 | Pain2 25 | Pain3 26 | Pain4 27 | Pain5 28 | Pain6 29 | Die1 30 | Die2 31 | GrenadeLaunch 32 | GrenadeExplode 33 | Splash1 // start singleplayer-only sound 34 | Splash2 35 | Grunt1 36 | Grunt2 37 | Rumble 38 | PainO 39 | PainR 40 | DeathR 41 | PainE 42 | DeathE 43 | PainS 44 | DeathS 45 | PainB 46 | DeathB 47 | PainP 48 | PigGrunt2 49 | PainH 50 | DeathH 51 | PainD 52 | DeathD 53 | PigGrunt1 54 | IceBall 55 | SlimeBall // end singleplayer-only sounds 56 | JumpPad 57 | Pistol 58 | BaseCaptured // start voice sounds 59 | BaseLost 60 | Fight 61 | HealthBoost 62 | HealthBoostIn10Seconds 63 | Quaddamage 64 | QuaddamageIn10Seconds 65 | RespawnPointSet // end voice sounds 66 | FlagPickup 67 | FlagDrop 68 | FlagReturn 69 | FlagScore 70 | FlagReset 71 | Burn 72 | ChainSawAttack 73 | ChainSawIdle 74 | Hit 75 | FlagFail 76 | ) 77 | -------------------------------------------------------------------------------- /pkg/gameserver/protocol/version.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | const Version = 260 4 | -------------------------------------------------------------------------------- /pkg/gameserver/relay/publisher.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | import ( 4 | "github.com/cfoust/sour/pkg/game/protocol" 5 | "github.com/sasha-s/go-deadlock" 6 | ) 7 | 8 | // Publisher provides methods to send updates to all subscribers of a certain topic. 9 | type Publisher struct { 10 | cn uint32 11 | notifyRelay chan<- uint32 12 | updates chan<- []protocol.Message 13 | closed bool 14 | mutex deadlock.RWMutex 15 | } 16 | 17 | func newPublisher(cn uint32, notifyRelay chan<- uint32) (*Publisher, <-chan []protocol.Message) { 18 | updates := make(chan []protocol.Message) 19 | 20 | p := &Publisher{ 21 | cn: cn, 22 | notifyRelay: notifyRelay, 23 | updates: updates, 24 | } 25 | 26 | return p, updates 27 | } 28 | 29 | // Publish notifies p's broker that there is an update on p's topic and blocks 30 | // until the broker received the notification. Publish then blocks until the 31 | // broker received the update. Calling Publish() after Close() returns 32 | // immediately. Use p's Stop channel to know when the broker stopped listening. 33 | func (p *Publisher) Publish(messages ...protocol.Message) { 34 | p.mutex.RLock() 35 | closed := p.closed 36 | p.mutex.RUnlock() 37 | 38 | if closed { 39 | return 40 | } 41 | 42 | p.notifyRelay <- p.cn 43 | p.updates <- messages 44 | } 45 | 46 | // Close tells the broker there will be no more updates coming from p. Calling Publish() after Close() returns immediately. 47 | // Calling Close() makes the broker unsubscribe all subscribers and telling them updates on the topic have ended. 48 | func (p *Publisher) Close() { 49 | p.mutex.Lock() 50 | p.closed = true 51 | p.mutex.Unlock() 52 | 53 | close(p.updates) 54 | } 55 | -------------------------------------------------------------------------------- /pkg/gameserver/state.go: -------------------------------------------------------------------------------- 1 | package gameserver 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/cfoust/sour/pkg/gameserver/game" 7 | "github.com/cfoust/sour/pkg/gameserver/protocol/mastermode" 8 | ) 9 | 10 | type State struct { 11 | Clock game.Clock 12 | MasterMode mastermode.ID 13 | GameMode game.Mode 14 | Map string 15 | UpSince time.Time 16 | NumClients func() int // number of clients connected 17 | } 18 | -------------------------------------------------------------------------------- /pkg/gameserver/timer/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pkg/gameserver/timer/README.md: -------------------------------------------------------------------------------- 1 | # timer 2 | [![Build Status](https://travis-ci.org/ivahaev/timer.svg?branch=master)](http://travis-ci.org/ivahaev/timer) [![GoDoc](https://godoc.org/github.com/ivahaev/timer?status.svg)](https://godoc.org/github.com/ivahaev/timer) 3 | 4 | Golang timer with start and pause 5 | -------------------------------------------------------------------------------- /pkg/maps/api/entities/serde_test.go: -------------------------------------------------------------------------------- 1 | package entities 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func cmp(t *testing.T, before EntityInfo) { 10 | a, err := Encode(before) 11 | assert.NoError(t, err) 12 | 13 | after, err := Decode(before.Type(), a) 14 | assert.NoError(t, err) 15 | 16 | t.Logf("%+v", after) 17 | assert.Equal(t, before, after, "should yield same result") 18 | } 19 | 20 | func TestMapModel(t *testing.T) { 21 | cmp(t, &MapModel{ 22 | Angle: 1, 23 | Index: 2, 24 | }) 25 | } 26 | 27 | func TestLight(t *testing.T) { 28 | cmp(t, &Light{ 29 | Radius: 8, 30 | Color: Color{ 31 | R: 0, 32 | G: 255, 33 | B: 128, 34 | }, 35 | }) 36 | } 37 | 38 | func TestParticle(t *testing.T) { 39 | cmp(t, &Particles{ 40 | Particle: ParticleTypeFire, 41 | Data: &Fire{ 42 | Height: 8, 43 | Radius: 8, 44 | Color: Color16{ 45 | R: 0x90, 46 | G: 0x30, 47 | B: 0x20, 48 | }, 49 | }, 50 | }) 51 | } 52 | 53 | func TestDefault(t *testing.T) { 54 | before := Particles{ 55 | Particle: ParticleTypeFire, 56 | Data: &Fire{ 57 | Color: Color16{ 58 | R: 0x90, 59 | G: 0x30, 60 | B: 0x20, 61 | }, 62 | }, 63 | } 64 | a, err := Encode(&before) 65 | assert.NoError(t, err) 66 | 67 | after, err := Decode(before.Type(), a) 68 | particles := after.(*Particles) 69 | assert.NoError(t, err) 70 | assert.Equal(t, particles.Data, &Fire{ 71 | Radius: 1.5, 72 | Height: 0.5, 73 | Color: Color16{ 74 | R: 0x90, 75 | G: 0x30, 76 | B: 0x20, 77 | }, 78 | }, "should yield same result") 79 | } 80 | -------------------------------------------------------------------------------- /pkg/maps/api/module.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | C "github.com/cfoust/sour/pkg/game/constants" 5 | V "github.com/cfoust/sour/pkg/game/variables" 6 | "github.com/cfoust/sour/pkg/maps/api/entities" 7 | ) 8 | 9 | type Map struct { 10 | WorldSize int32 `json:"worldSize"` 11 | GameType string `json:"gameType"` 12 | Entities []entities.Entity `json:"entities"` 13 | Variables V.Variables `json:"variables"` 14 | } 15 | 16 | func New() *Map { 17 | return &Map{ 18 | Variables: make(map[string]V.Variable), 19 | } 20 | } 21 | 22 | type Typable interface { 23 | String() string 24 | FromString(string) 25 | } 26 | 27 | var _ Typable = (*C.EntityType)(nil) 28 | var _ Typable = (*entities.ParticleType)(nil) 29 | -------------------------------------------------------------------------------- /pkg/maps/default.textures: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:db334d1c6170fbba392a691deb60b8246043a8b6dfaeec6cf51b7afd9b78cd50 3 | size 136702 4 | -------------------------------------------------------------------------------- /pkg/maps/edit.go: -------------------------------------------------------------------------------- 1 | package maps 2 | 3 | func EmptyMap(scale int) *Cube { 4 | root := NewCubes(F_EMPTY, MAT_AIR) 5 | 6 | for i := 0; i < 4; i++ { 7 | root.Children[i].SolidFaces() 8 | } 9 | 10 | //if(worldsize > 0x1000) splitocta(worldroot, worldsize>>1); 11 | 12 | return root 13 | } 14 | -------------------------------------------------------------------------------- /pkg/maps/translate.go: -------------------------------------------------------------------------------- 1 | package maps 2 | 3 | import ( 4 | "github.com/cfoust/sour/pkg/maps/api" 5 | E "github.com/cfoust/sour/pkg/maps/api/entities" 6 | ) 7 | 8 | func (m *GameMap) ToAPI() (*api.Map, error) { 9 | map_ := api.New() 10 | map_.WorldSize = m.Header.WorldSize 11 | map_.GameType = m.Header.GameType 12 | 13 | entities := make([]E.Entity, 0) 14 | for _, entity := range m.Entities { 15 | attributes := E.Attributes([]int16{ 16 | entity.Attr1, 17 | entity.Attr2, 18 | entity.Attr3, 19 | entity.Attr4, 20 | entity.Attr5, 21 | }) 22 | 23 | info, err := E.Decode(entity.Type, &attributes) 24 | if err != nil { 25 | // TODO handle entities that were not decoded 26 | continue 27 | } 28 | 29 | entities = append(entities, E.Entity{ 30 | Position: E.Vector{ 31 | X: entity.Position.X, 32 | Y: entity.Position.Y, 33 | Z: entity.Position.Z, 34 | }, 35 | Info: info, 36 | }) 37 | } 38 | 39 | map_.Entities = entities 40 | map_.Variables = m.Vars 41 | 42 | return map_, nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/maps/worldio/cube.h: -------------------------------------------------------------------------------- 1 | #ifndef __CUBE_H__ 2 | #define __CUBE_H__ 3 | 4 | #define _FILE_OFFSET_BITS 64 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "tools.h" 18 | #include "geom.h" 19 | #include "ents.h" 20 | #include "command.h" 21 | #include "iengine.h" 22 | #include "igame.h" 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /pkg/maps/worldio/pvs.cpp: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | 3 | #define MAXWATERPVS 32 4 | 5 | uint numwaterplanes = 0; 6 | 7 | static struct 8 | { 9 | int height; 10 | vector matsurfs; 11 | } waterplanes[MAXWATERPVS]; 12 | 13 | struct viewcellnode 14 | { 15 | uchar leafmask; 16 | union viewcellchild 17 | { 18 | int pvs; 19 | viewcellnode *node; 20 | } children[8]; 21 | 22 | viewcellnode() : leafmask(0xFF) 23 | { 24 | loopi(8) children[i].pvs = -1; 25 | } 26 | ~viewcellnode() 27 | { 28 | loopi(8) if(!(leafmask&(1<leafmask = f->getchar(); 36 | loopi(8) 37 | { 38 | if(p->leafmask&(1<children[i].pvs = f->getlil(); 39 | else p->children[i].node = loadviewcells(f); 40 | } 41 | return p; 42 | } 43 | 44 | struct pvsdata 45 | { 46 | int offset, len; 47 | 48 | pvsdata() {} 49 | pvsdata(int offset, int len) : offset(offset), len(len) {} 50 | }; 51 | 52 | static vector pvs; 53 | static vector pvsbuf; 54 | 55 | static viewcellnode *viewcells = NULL; 56 | 57 | void loadpvs(stream *f, int numpvs) 58 | { 59 | uint totallen = f->getlil(); 60 | if(totallen & 0x80000000U) 61 | { 62 | totallen &= ~0x80000000U; 63 | numwaterplanes = f->getlil(); 64 | loopi(numwaterplanes) waterplanes[i].height = f->getlil(); 65 | } 66 | int offset = 0; 67 | loopi(numpvs) 68 | { 69 | ushort len = f->getlil(); 70 | pvs.add(pvsdata(offset, len)); 71 | offset += len; 72 | } 73 | f->read(pvsbuf.reserve(totallen).buf, totallen); 74 | pvsbuf.advance(totallen); 75 | viewcells = loadviewcells(f); 76 | } 77 | -------------------------------------------------------------------------------- /pkg/maps/worldio/state.h: -------------------------------------------------------------------------------- 1 | struct MapState { 2 | cube *root; 3 | vector *slots; 4 | vector *vslots; 5 | }; 6 | -------------------------------------------------------------------------------- /pkg/maps/worldio/world.h: -------------------------------------------------------------------------------- 1 | 2 | enum // hardcoded texture numbers 3 | { 4 | DEFAULT_SKY = 0, 5 | DEFAULT_GEOM 6 | }; 7 | 8 | #define MAPVERSION 33 // bump if map format changes, see worldio.cpp 9 | 10 | struct octaheader 11 | { 12 | char magic[4]; // "OCTA" 13 | int version; // any >8bit quantity is little endian 14 | int headersize; // sizeof(header) 15 | int worldsize; 16 | int numents; 17 | int numpvs; 18 | int lightmaps; 19 | int blendmap; 20 | int numvars; 21 | int numvslots; 22 | }; 23 | 24 | struct compatheader // map file format header 25 | { 26 | char magic[4]; // "OCTA" 27 | int version; // any >8bit quantity is little endian 28 | int headersize; // sizeof(header) 29 | int worldsize; 30 | int numents; 31 | int numpvs; 32 | int lightmaps; 33 | int lightprecision, lighterror, lightlod; 34 | uchar ambient; 35 | uchar watercolour[3]; 36 | uchar blendmap; 37 | uchar lerpangle, lerpsubdiv, lerpsubdivsize; 38 | uchar bumperror; 39 | uchar skylight[3]; 40 | uchar lavacolour[3]; 41 | uchar waterfallcolour[3]; 42 | uchar reserved[10]; 43 | char maptitle[128]; 44 | }; 45 | 46 | #define WATER_AMPLITUDE 0.4f 47 | #define WATER_OFFSET 1.1f 48 | 49 | enum 50 | { 51 | MATSURF_NOT_VISIBLE = 0, 52 | MATSURF_VISIBLE, 53 | MATSURF_EDIT_ONLY 54 | }; 55 | 56 | #define TEX_SCALE 8.0f 57 | 58 | struct vertex { vec pos; bvec4 norm; vec2 tc; svec2 lm; bvec4 tangent; }; 59 | 60 | -------------------------------------------------------------------------------- /pkg/maps/worldio/worldio.go: -------------------------------------------------------------------------------- 1 | package worldio 2 | 3 | // #cgo LDFLAGS: -lz 4 | import "C" 5 | 6 | import ( 7 | "sync" 8 | "unsafe" 9 | 10 | "github.com/cfoust/sour/pkg/game/io" 11 | ) 12 | 13 | var M sync.Mutex 14 | 15 | func CountRefs(state MapState, numSlots int) []int32 { 16 | data := make([]byte, numSlots*4) 17 | Getrefs(state, uintptr(unsafe.Pointer(&data[0])), numSlots) 18 | 19 | result := make([]int32, 0) 20 | buffer := io.Buffer(data) 21 | for i := 0; i < numSlots; i++ { 22 | value, ok := buffer.GetInt() 23 | if !ok { 24 | return result 25 | } 26 | result = append(result, value) 27 | } 28 | return result 29 | } 30 | -------------------------------------------------------------------------------- /pkg/maps/worldio/worldio.h: -------------------------------------------------------------------------------- 1 | #ifndef WORLD_H 2 | #define WORLD_H 3 | 4 | #define _FILE_OFFSET_BITS 64 5 | 6 | #include "tools.h" 7 | #include "engine.h" 8 | #include "texture.h" 9 | #include "state.h" 10 | 11 | void freeocta(cube *c); 12 | cube *loadchildren_buf(void *p, size_t len, int size, int _mapversion); 13 | size_t savec_buf(void *p, unsigned int len, cube *c, int size); 14 | 15 | MapState *empty_world(int size); 16 | 17 | MapState *partial_load_world( 18 | void *p, 19 | size_t len, 20 | int numvslots, 21 | int _worldsize, 22 | int _mapversion, 23 | int numlightmaps, 24 | int numpvs, 25 | int blendmap 26 | ); 27 | 28 | size_t partial_save_world( 29 | void *p, 30 | size_t len, 31 | MapState *state, 32 | int _worldsize 33 | ); 34 | 35 | bool load_texture_index(void *data, size_t len, MapState *state); 36 | 37 | editinfo *store_copy(MapState *state, void *data, size_t len); 38 | bool apply_paste(MapState *state, editinfo *info, void *data, size_t len); 39 | void free_state(MapState *state); 40 | void free_edit(editinfo *info); 41 | 42 | int getnumvslots(MapState *state); 43 | VSlot *getvslotindex(MapState *state, int i); 44 | 45 | void getrefs(MapState *state, void *result, int numSlots); 46 | 47 | cube *getcubeindex(cube *c, int i); 48 | void cube_setedge(cube *c, int i, uchar value); 49 | void cube_settexture(cube *c, int i, ushort value); 50 | bool apply_messages(MapState *state, int _worldsize, void *data, size_t len); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /pkg/maps/worldio/worldio.swigcxx: -------------------------------------------------------------------------------- 1 | %module worldio 2 | %{ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "worldio.h" 15 | %} 16 | %include "worldio.h" 17 | %include "state.h" 18 | %include "wrap.h" 19 | 20 | %include "carrays.i" 21 | %array_functions(cube, CubeArray); 22 | %array_functions(ushort, Uint16Array); 23 | %array_functions(uchar, UcharArray); 24 | %array_functions(surfaceinfo, SurfaceInfoArray); 25 | 26 | -------------------------------------------------------------------------------- /pkg/min/index.go: -------------------------------------------------------------------------------- 1 | package min 2 | 3 | type IndexAsset struct { 4 | Id int 5 | Path string 6 | } 7 | 8 | type Index struct { 9 | Assets []string 10 | Refs []IndexAsset 11 | } 12 | -------------------------------------------------------------------------------- /pkg/server/ingress/module.go: -------------------------------------------------------------------------------- 1 | package ingress 2 | 3 | import ( 4 | "github.com/cfoust/sour/pkg/game/io" 5 | "github.com/cfoust/sour/pkg/utils" 6 | ) 7 | 8 | // A unique identifier for this client for the lifetime of their session. 9 | type ClientID uint32 10 | 11 | type ClientType uint8 12 | 13 | const ( 14 | ClientTypeWS = iota 15 | ClientTypeENet 16 | ) 17 | 18 | const ( 19 | CLIENT_MESSAGE_LIMIT int = 16 20 | ) 21 | 22 | // The status of the client's connection to the cluster. 23 | type NetworkStatus uint8 24 | 25 | const ( 26 | NetworkStatusConnected = iota 27 | NetworkStatusDisconnected 28 | ) 29 | 30 | type CommandResult struct { 31 | Err error 32 | } 33 | 34 | type ClusterCommand struct { 35 | Command string 36 | Response chan CommandResult 37 | } 38 | 39 | type Connection interface { 40 | Session() *utils.Session 41 | 42 | // Lasts for the duration of the client's connection to its ingress. 43 | NetworkStatus() NetworkStatus 44 | Host() string 45 | Type() ClientType 46 | DeviceType() string 47 | // Tell the client that we've connected 48 | Connect(name string, isHidden bool, shouldCopy bool) 49 | // Messages going to the client 50 | Send(packet io.RawPacket) <-chan error 51 | // Messages going to the server 52 | ReceivePackets() <-chan io.RawPacket 53 | // Clients can issue commands out-of-band 54 | // Commands sent in ordinary game packets are interpreted anyway 55 | ReceiveCommands() <-chan ClusterCommand 56 | // When the client disconnects on its own 57 | ReceiveDisconnect() <-chan bool 58 | // Forcibly disconnect this client 59 | Disconnect(reason int, message string) 60 | Destroy() 61 | } 62 | 63 | var _ Connection = (*WSClient)(nil) 64 | var _ Connection = (*ENetClient)(nil) 65 | -------------------------------------------------------------------------------- /pkg/server/module.go: -------------------------------------------------------------------------------- 1 | package server 2 | -------------------------------------------------------------------------------- /pkg/server/service/api.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | "regexp" 7 | 8 | "github.com/go-redis/redis/v9" 9 | ) 10 | 11 | var ( 12 | DEMO_PATH_REGEX = regexp.MustCompile(`^/api/demo/([\w-]+)$`) 13 | ) 14 | 15 | func (c *Cluster) ServeHTTP(w http.ResponseWriter, r *http.Request) { 16 | matches := DEMO_PATH_REGEX.FindStringSubmatch(r.URL.Path) 17 | if len(matches) == 2 { 18 | id := matches[1] 19 | 20 | demo, err := c.GetDemo(context.Background(), id) 21 | if err == redis.Nil { 22 | w.WriteHeader(404) 23 | return 24 | } 25 | 26 | header := w.Header() 27 | header.Add("Content-Type", "application/octet-stream") 28 | w.Write(demo) 29 | return 30 | } 31 | 32 | w.WriteHeader(400) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/server/service/auth.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | func (server *Cluster) GreetClient(ctx context.Context, user *User) { 8 | server.NotifyClientChange(ctx, user, true) 9 | 10 | server.Users.Mutex.RLock() 11 | message := "users online: " 12 | users := server.Users.Users 13 | for i, other := range users { 14 | if other == user { 15 | message += "you" 16 | } else { 17 | message += other.Reference() 18 | } 19 | if i != len(users)-1 { 20 | message += ", " 21 | } 22 | } 23 | server.Users.Mutex.RUnlock() 24 | user.Message(message) 25 | } 26 | -------------------------------------------------------------------------------- /pkg/server/service/elo.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/cfoust/sour/pkg/config" 7 | ) 8 | 9 | type ELO struct { 10 | Rating uint 11 | Wins uint 12 | Draws uint 13 | Losses uint 14 | } 15 | 16 | func NewELO() *ELO { 17 | return &ELO{ 18 | Rating: 1200, 19 | } 20 | } 21 | 22 | type ELOState struct { 23 | Ratings map[string]*ELO 24 | Mutex sync.Mutex 25 | } 26 | 27 | func NewELOState(duels []config.DuelType) *ELOState { 28 | state := ELOState{ 29 | Ratings: make(map[string]*ELO), 30 | } 31 | 32 | for _, type_ := range duels { 33 | state.Ratings[type_.Name] = NewELO() 34 | } 35 | 36 | return &state 37 | } 38 | -------------------------------------------------------------------------------- /pkg/server/service/purgatory.ogz: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:781ac75228b618b7e848a44bc2e804a9e545607f31eb1bdc525515ad5c5f65ff 3 | size 22013 4 | -------------------------------------------------------------------------------- /pkg/server/static/.gitignore: -------------------------------------------------------------------------------- 1 | /site 2 | -------------------------------------------------------------------------------- /pkg/utils/colors.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "strconv" 7 | ) 8 | 9 | type Color struct { 10 | R byte 11 | G byte 12 | B byte 13 | } 14 | 15 | func (c Color) ToUint() (color uint32) { 16 | color = color | (uint32(c.R) << 16) 17 | color = color | (uint32(c.G) << 8) 18 | color = color | uint32(c.B) 19 | return color 20 | } 21 | 22 | func (c Color) ToHex() string { 23 | return fmt.Sprintf("#%06x", c.ToUint()) 24 | } 25 | 26 | func (c Color) MarshalJSON() ([]byte, error) { 27 | return json.Marshal(c.ToHex()) 28 | } 29 | 30 | func ColorFromUint(value uint32) Color { 31 | var c Color 32 | c.R = byte((value >> 16) & 0xFF) 33 | c.G = byte((value >> 8) & 0xFF) 34 | c.B = byte(value & 0xFF) 35 | return c 36 | } 37 | 38 | func (c *Color) UnmarshalJSON(data []byte) error { 39 | var hex string 40 | err := json.Unmarshal(data, &hex) 41 | if err == nil { 42 | value, err := strconv.ParseUint(hex[1:], 16, 32) 43 | if err != nil { 44 | return err 45 | } 46 | 47 | *c = ColorFromUint(uint32(value)) 48 | return nil 49 | } 50 | if _, ok := err.(*json.UnmarshalTypeError); !ok { 51 | return err 52 | } 53 | 54 | elements := [3]byte{} 55 | err = json.Unmarshal(data, &elements) 56 | if err == nil { 57 | c.R = elements[0] 58 | c.G = elements[1] 59 | c.B = elements[2] 60 | return nil 61 | } 62 | if _, ok := err.(*json.UnmarshalTypeError); !ok { 63 | return err 64 | } 65 | 66 | full := struct { 67 | R byte 68 | G byte 69 | B byte 70 | }{} 71 | err = json.Unmarshal(data, &full) 72 | if err == nil { 73 | c.R = full.R 74 | c.G = full.G 75 | c.B = full.B 76 | return nil 77 | } 78 | if _, ok := err.(*json.UnmarshalTypeError); !ok { 79 | return err 80 | } 81 | 82 | return fmt.Errorf("could not deserialize color") 83 | } 84 | -------------------------------------------------------------------------------- /pkg/utils/hash.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/sha256" 5 | "fmt" 6 | ) 7 | 8 | func Hash(data []byte) string { 9 | return fmt.Sprintf("%x", sha256.Sum256(data)) 10 | } 11 | 12 | func HashString(value string) string { 13 | return fmt.Sprintf("%x", sha256.Sum256([]byte(value))) 14 | } 15 | -------------------------------------------------------------------------------- /pkg/utils/pubsub.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/sasha-s/go-deadlock" 5 | ) 6 | 7 | type Topic[T any] struct { 8 | subscribers map[chan T]struct{} 9 | mutex deadlock.Mutex 10 | } 11 | 12 | func NewTopic[T any]() *Topic[T] { 13 | return &Topic[T]{ 14 | subscribers: make(map[chan T]struct{}), 15 | } 16 | } 17 | 18 | func (t *Topic[T]) Publish(value T) { 19 | t.mutex.Lock() 20 | for subscriber := range t.subscribers { 21 | subscriber <- value 22 | } 23 | t.mutex.Unlock() 24 | } 25 | 26 | type Subscriber[T any] struct { 27 | channel chan T 28 | topic *Topic[T] 29 | } 30 | 31 | func (t *Topic[T]) Subscribe() *Subscriber[T] { 32 | channel := make(chan T) 33 | t.mutex.Lock() 34 | t.subscribers[channel] = struct{}{} 35 | t.mutex.Unlock() 36 | 37 | return &Subscriber[T]{channel, t} 38 | } 39 | 40 | func (t *Subscriber[T]) Recv() <-chan T { 41 | return t.channel 42 | } 43 | 44 | func (t *Subscriber[T]) Done() { 45 | topic := t.topic 46 | topic.mutex.Lock() 47 | delete(topic.subscribers, t.channel) 48 | topic.mutex.Unlock() 49 | } 50 | -------------------------------------------------------------------------------- /pkg/utils/session.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "time" 6 | ) 7 | 8 | type Session struct { 9 | context context.Context 10 | cancel context.CancelFunc 11 | startTime time.Time 12 | } 13 | 14 | func NewSession(ctx context.Context) Session { 15 | ctx, cancel := context.WithCancel(ctx) 16 | return Session{ 17 | context: ctx, 18 | cancel: cancel, 19 | startTime: time.Now(), 20 | } 21 | } 22 | 23 | func (s *Session) Started() time.Time { 24 | return s.startTime 25 | } 26 | 27 | func (s *Session) Ctx() context.Context { 28 | return s.context 29 | } 30 | 31 | func (s *Session) IsDone() bool { 32 | return s.context.Err() != nil 33 | } 34 | 35 | func (s *Session) Cancel() { 36 | s.cancel() 37 | } 38 | -------------------------------------------------------------------------------- /pkg/version/module.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | // These should be set via go build -ldflags -X 'xxxx'. 4 | var ( 5 | Version = "development" 6 | GoVersion = "1.21" 7 | GitCommit = "unknown" 8 | BuildTime = "1979-01-09T16:09:53+00:00" 9 | ) 10 | -------------------------------------------------------------------------------- /proxy/.gitignore: -------------------------------------------------------------------------------- 1 | /websockify 2 | *.o 3 | /wsproxy 4 | -------------------------------------------------------------------------------- /proxy/Makefile: -------------------------------------------------------------------------------- 1 | TARGETS=wsproxy 2 | CFLAGS += -fPIC 3 | 4 | all: $(TARGETS) 5 | 6 | wsproxy: websockify.o websocket.o base64.o md5.o sha1.o 7 | $(CC) $(LDFLAGS) $^ -o $@ 8 | 9 | websocket.o: websocket.c websocket.h 10 | websockify.o: websockify.c websocket.h 11 | md5.o: md5.c md5.h 12 | sha1.o: sha1.c sha1.h 13 | base64.o: base64.c 14 | 15 | clean: 16 | rm -f wsproxy *.o 17 | 18 | -------------------------------------------------------------------------------- /proxy/README.md: -------------------------------------------------------------------------------- 1 | # wsproxy 2 | 3 | websocket tcp/udp proxy (based on websockify-c) 4 | 5 | ```Usage: wsproxy [options] [source_addr:]source_port 6 | 7 | --verbose|-v verbose messages and per frame traffic 8 | --daemon|-d become a daemon (background process) 9 | --whitelist-hosts|-W LIST new-line separated target host whitelist file 10 | --whitelist-ports|-P LIST new-line separated target port whitelist file 11 | --pid|-p desired path of pid file. Default: '/var/run/websockify.pid' 12 | 13 | ``` 14 | 15 | Patch for emscripten: 16 | 17 | https://github.com/FWGS/emscripten/commit/efcb8ecd0807c5590637812a29b4d1c7cd582719 -------------------------------------------------------------------------------- /proxy/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | make 4 | -------------------------------------------------------------------------------- /proxy/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. 3 | * MD5 Message-Digest Algorithm (RFC 1321). 4 | * 5 | * Homepage: 6 | * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 7 | * 8 | * Author: 9 | * Alexander Peslyak, better known as Solar Designer 10 | * 11 | * This software was written by Alexander Peslyak in 2001. No copyright is 12 | * claimed, and the software is hereby placed in the public domain. 13 | * In case this attempt to disclaim copyright and place the software in the 14 | * public domain is deemed null and void, then the software is 15 | * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the 16 | * general public under the following terms: 17 | * 18 | * Redistribution and use in source and binary forms, with or without 19 | * modification, are permitted. 20 | * 21 | * There's ABSOLUTELY NO WARRANTY, express or implied. 22 | * 23 | * See md5.c for more information. 24 | */ 25 | 26 | #ifdef HAVE_OPENSSL 27 | #include 28 | #elif !defined(_MD5_H) 29 | #define _MD5_H 30 | 31 | /* Any 32-bit or wider unsigned integer data type will do */ 32 | typedef unsigned int MD5_u32plus; 33 | 34 | typedef struct { 35 | MD5_u32plus lo, hi; 36 | MD5_u32plus a, b, c, d; 37 | unsigned char buffer[64]; 38 | MD5_u32plus block[16]; 39 | } MD5_CTX; 40 | 41 | extern void MD5_Init(MD5_CTX *ctx); 42 | extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); 43 | extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /proxy/sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA1_H 2 | #define SHA1_H 3 | 4 | /* 5 | SHA-1 in C 6 | By Steve Reid 7 | 100% Public Domain 8 | */ 9 | 10 | #include "stdint.h" 11 | 12 | typedef struct 13 | { 14 | uint32_t state[5]; 15 | uint32_t count[2]; 16 | unsigned char buffer[64]; 17 | } SHA1_CTX; 18 | 19 | void SHA1Transform( 20 | uint32_t state[5], 21 | const unsigned char buffer[64] 22 | ); 23 | 24 | void SHA1Init( 25 | SHA1_CTX * context 26 | ); 27 | 28 | void SHA1Update( 29 | SHA1_CTX * context, 30 | const unsigned char *data, 31 | uint32_t len 32 | ); 33 | 34 | void SHA1Final( 35 | unsigned char digest[20], 36 | SHA1_CTX * context 37 | ); 38 | 39 | void SHA1( 40 | char *hash_out, 41 | const char *str, 42 | int len); 43 | 44 | #endif /* SHA1_H */ 45 | --------------------------------------------------------------------------------