Compare commits

...

225 Commits

Author SHA1 Message Date
James R b6188a3b16 Get rid of mutexes on command buffer 2020-08-24 06:02:14 -07:00
James R 8367a8553c "Asynchronous" file queue calls findmultiplefiles on another thread, then reads the file on the main thread
This replaces the exec command's threading from before.
(See d0e7ba309a59580988225816d104e343b64d67d0.) The order of exec commands
alone is guranteed. And it removes the need to put mutexes on the command
buffer. I plan to use this system for addfile too...
2020-08-24 06:00:01 -07:00
James R 7fcbe073c3 Make mutex and cond functions no-op with NULL pointers 2020-08-24 04:34:18 -07:00
James R 83560485d1 Let findmultiplefiles use a mutex when accessing each file query 2020-08-24 04:33:44 -07:00
James R bb07f12b42 W_InitMultipleFiles with one findmultiplefiles call
This speeds up file searching for base resources and pwads by using one
directory traversal. Previously findfile could be called for each wad. And
although subsequent traversals after the first are faster, it's still a waste.
2020-08-22 01:53:22 -07:00
James R 60a4b403dd Multiple files filesearch and findmultiplefiles 2020-08-22 01:50:54 -07:00
James R 731c6bf56d Merge remote-tracking branch 'origin/next' into findfile-with-threads 2020-08-20 22:45:58 -07:00
Sal 0ca9f8f07d Merge branch 'conenction-screen-improvements' into 'next'
Connection screen improvements

See merge request KartKrew/Kart-Public!187
2020-08-21 00:11:37 -04:00
Ashnal 9e1d7146ad Fixed retry timeout to no ttrigger when starting a local server 2020-08-20 23:38:04 -04:00
Ashnal 247239c2bc Add return false to the connect timeout 2020-08-20 23:09:12 -04:00
James R 5b0cb1afcb Merge remote-tracking branch 'origin/master' into next 2020-08-20 19:55:03 -07:00
Sal 79c299bf31 Merge branch 'port-port-port' into 'master'
2.2's random client port

See merge request KartKrew/Kart-Public!201
2020-08-20 12:19:52 -04:00
Sal 67b37e54b6 Merge branch 'snapback' into 'master'
Instantaneous lookback camera (v2 backport)

See merge request KartKrew/Kart-Public!203
2020-08-20 12:19:41 -04:00
Sal 4c363db516 Merge branch 'gme-fixes-cleanup' into 'master'
GME cleanup and fixes

See merge request KartKrew/Kart-Public!202
2020-08-20 02:07:19 -04:00
lachwright d0d6128053 Instantaneous lookback camera (v2 backport) 2020-08-20 13:41:03 +08:00
Ashnal aa2b25e667 Well actually, lets fix all comparisons of askset to use the same comparison
If we initialize to I_GetTime() - NEWTICRATE*3 it never underflows and everything is good
2020-08-20 00:54:18 -04:00
Steel Titanium e3f07b33bb GME cleanup and fixes
Just some stuff backported from SRB2 2.2, well mostly

get_zlib_error function to reduce code duplication

Return false if it fails to load the VGZ lump

Reduce redundant calls to gme_set_equalizer

Fix sometimes loading a VGZ crashing the game
2020-08-19 22:39:12 -04:00
James R 94512c49e4 -clientport (it's back!) and -serverport, which is an alias to -port
If you ever need to, you can change the client port number.

(cherry picked from commit 843d9b9f0a345330d97c579e94f208eb2b65c156)
2020-08-19 18:16:54 -07:00
James R b77541b51d Use a pointer for port_name
Using strcpy is stupid because we don't know how long the argument would be.
There's no need for a buffer anyway.

(cherry picked from commit 4e321012894b2aa87e312597f19be26b30545a8b)
2020-08-19 18:16:53 -07:00
James R b1f5e66a23 Use a random port when connecting
(cherry picked from commit f584b61c93a97e1a9852f306acba673ced21e03a)
2020-08-19 18:16:53 -07:00
James R 65968f00d3 Fix tiny mistake with the last commit 2020-08-19 17:55:01 -07:00
James R 1cd7c3b747 Rearrange time comparsion on asksent to make it underflow friendly
This fixes '-connect'. NEWTICRATE*5 is subtracted from asksent after
CL_LOADFILES. If this happens too early, an underflow will occur.
2020-08-19 17:49:47 -07:00
Sal a335d6b583 Merge branch 'fix-nocurl' into 'master'
Fix NOCURL compiling

See merge request KartKrew/Kart-Public!197
2020-08-19 20:36:14 -04:00
Sal c6f85cde59 Merge branch 'httpsource-without-curl' into 'master'
Let servers send httpsource without curl

See merge request KartKrew/Kart-Public!196
2020-08-19 20:36:06 -04:00
Sal ed41d5df9e Merge branch 'kart-io' into 'next'
Lua Input/Output library

See merge request KartKrew/Kart-Public!200
2020-08-19 20:35:56 -04:00
Ashnal cadb4719cf Added m_menu_mutex to M_Drawer in connection screen 2020-08-19 19:52:24 -04:00
Ashnal 648a950ac8 Merge remote-tracking branch 'public/next' into conenction-screen-improvements 2020-08-19 19:08:33 -04:00
Ashnal 7c5740d98f COnfirm box now respects rebindable accelerate and brake on keyboards 2020-08-19 18:01:56 -04:00
Sal 8ee7443705 Merge branch 'kimmy-osx-fixes' into 'master'
[OSX] Fix "SIGILL: illegal instruction" on macOS Catalina

See merge request KartKrew/Kart-Public!194
2020-08-18 03:52:47 -04:00
Latapostrophe 392b24b769 Merge remote-tracking branch 'stjr/io' into kart-io 2020-08-17 20:22:02 +02:00
Ashnal eb81bea943 Move code down so declarations are above to appease C90 2020-08-17 04:03:02 -04:00
Ashnal 03150e5fe6 Move declaration to appease C90
also remove some extra tab characters
2020-08-17 03:56:13 -04:00
Ashnal afc6bdbc7e Fixes for file accounting
mainwads+1 to not use the first mainwad
2020-08-17 03:51:19 -04:00
Ashnal 9a9d81bbe0 New message boxes for downloads and full server waiting
Downloads must be confirmed before proceeding
Allows downloading mods for full servers
Client will wait for a slot to open on a full server to join
This has a 5 minute timeout
2020-08-17 03:47:23 -04:00
Sally Coolatta 41a401f703 Merge branch 'master' into next 2020-08-17 02:05:31 -04:00
James R 2f32891919 Do not multithread loading the first config
Resolution in particular relies on this to be done in order...
2020-08-16 22:44:42 -07:00
James R 7a05a8acf7 Do not do master server things when NOCURL 2020-08-16 21:42:58 -07:00
James R 5dc3ca3934 Remove HAVE_CURL guards on sending httpsource 2020-08-16 20:39:46 -07:00
James R 680d802d10 Fix major bruh 2020-08-16 20:07:14 -07:00
Sally Coolatta df0cc6a727 No previous prototype for K_DropKitchenSink 2020-08-16 21:18:33 -04:00
James R da6c159012 Fix bruh 2020-08-15 21:18:29 -07:00
James R d0e7ba309a Multithread the exec command
The command itself can be entirely multithreaded, but the reason I did so was
just for findfile, which can block for a long time on a slow disk.
2020-08-15 20:55:44 -07:00
James R c334230bb0 CONS_Printf: don't blit the screen during startup if this isn't the main thread 2020-08-15 20:55:11 -07:00
James R db417a8761 Don't work on mutexes or conditions if threads are stopped 2020-08-15 20:52:16 -07:00
James R 346f5c95f5 Mutexes for z_zone stuff 2020-08-15 20:51:31 -07:00
Kimberly Wilber 1bfcec9242 [OSX] Fix "SIGILL: illegal instruction" on macOS Catalina
on OSX, strncpy may copy to overlapping (protected) memory. this
sometimes happens when loading WAD files.

This patch eliminates these problems for me
2020-08-15 12:16:05 -04:00
Ashnal f800159bb8 Improve total downloads bar
Now has total file size AND number of files
2020-08-15 01:03:45 -04:00
James R a772096757 dumbass doesn't test changes before pushing directly to next
(cherry picked from commit be14b8a564a89a5afb84ac19f1586f3db7f68367)
2020-08-14 08:27:25 -07:00
Sal 06f36224ee Merge branch 'http-mserv' into 'master'
Make the HTTP Master Server official

See merge request KartKrew/Kart-Public!193
2020-08-10 16:49:47 -04:00
James R 1a1c215a91 Add http-mserv to fuck 2020-08-09 23:32:43 -07:00
Sal 9590a769ba Merge branch 'maxnetnodes-2-electric-boogaloo' into 'master'
Bump MAXNETNODES to 127

See merge request KartKrew/Kart-Public!192
2020-08-09 22:28:50 -04:00
James R 9d9f8fd8a3 Bump MAXNETNODES to 127 2020-08-09 18:26:34 -07:00
Ashnal cc78ef2c78 Now that the server doesn't erroneously send the last mainwad
As the first part of fileneeded, we must load file 0
2020-08-09 00:48:53 -04:00
Ashnal 4c5eb0d6bc Redo logic for lots of files vs not
Now new CL state for checking files so it can spread over tics
whether we ask for the extended list or not
2020-08-09 00:47:55 -04:00
Sal 97c4e7dfff Merge branch 'indirectitemcooldown' into 'next'
Fix Shrink, SPB and Hyudoro cooldowns never resetting?

See merge request KartKrew/Kart-Public!191
2020-08-06 12:19:27 -04:00
Sally Coolatta c63022350d Merge branch 'master' into next 2020-08-06 12:15:55 -04:00
AJ Martinez 3dada09aa5 Fix Hyudoro cooldown never resetting 2020-08-06 10:51:53 -05:00
AJ Martinez 2add55eb04 Fix indirect item cooldown never resetting 2020-08-06 10:34:16 -05:00
Sal b320256a47 Merge branch 'master' into 'master'
Clarify addon-related messages

See merge request KartKrew/Kart-Public!190
2020-08-05 06:48:44 -04:00
AJ Martinez 8284caf1bc Clarify addon-related messages 2020-08-05 00:40:56 -05:00
Sal 8791fd8835 Merge branch 'mine-punt-sync-fix' into 'next'
Fix desyncs caused by K_PuntMine

See merge request KartKrew/Kart-Public!189
2020-07-25 03:55:28 -04:00
Sal 341ce8f4a3 Merge branch 'rocket-sneaker-hnext-fix' into 'next'
Rocket sneaker and sink hnext fix

See merge request KartKrew/Kart-Public!188
2020-07-25 03:55:22 -04:00
Ashnal 6d0b1e93c6 Appease C91 2020-07-23 21:05:00 -04:00
Ashnal 733aefa64a Also lets do this for kitchen sinks
They also ignored in K_DropHnextList
2020-07-23 20:12:35 -04:00
Ashnal 6562c9b755 Moved K_DropRocketSneaker call into K_StripItems
This should catch when DropHnextList misses it
Should probably fix sinks too ...
2020-07-15 09:17:35 -04:00
Ashnal 3bccf01d4f Properly handle rocket sneakers when shrinking 2020-07-14 19:50:37 -04:00
Ashnal 943a898352 Some safeguards for K_DropRocketSneaker usage 2020-07-14 19:45:15 -04:00
Ashnal 0637ed89aa Fixing RocketSneakers
New function specifically for dropping rocketsneakers K_DropRocketSneaker
Used by Eggbox touchspecial to properly dispose of shoes and clean up hnext
Now also used by the shoe thinker to drop themselves
Fixes angle of spent shoe launch
2020-07-14 18:45:45 -04:00
Ashnal ddc0bc16ab Add clean up to K_PuntMine
This cleans up hnext when a mine shield is P_RemoveMobj'ed while being punted
Otherwise, hnext could point to a removed mobj and cause undefined behavior
This also fixes the bug where if you have multiple mines in your slot, drag one
and have it punted, all your unused mines would disappear.
This should/may fix the crashes/desyncs I've observed in gameplay when a held mine is punted.
2020-07-14 00:21:46 -04:00
Ashnal 159316b155 Remove now unused ret var 2020-07-04 22:25:02 -04:00
Ashnal 2c0671d8fd Let's just ALWAYS go into ask file list mode
Easier to maintain and understand a single code path
Rather than switching behavior based on amount of addons
2020-07-04 01:12:38 -04:00
Ashnal 7da3d70f6c Remove Checking Files spam 2020-07-02 21:48:45 -04:00
Ashnal b8fdd6b89c Fix file number accounting
Should ensure appropriate accounting and prevent loading of
server files if it would put us over MAX_WADFILES
2020-07-02 20:57:33 -04:00
Ashnal 774b917c0e Correct total files to load off by one 2020-07-02 17:47:10 -04:00
Ashnal 6fe8a6c96a Changed "this server has a lot of addons!" to
"Checking server addon list ..." to be more informative
2020-07-01 23:52:43 -04:00
Ashnal 03d479fdb6 Connection screen no longer freezes up while
searching for addons on disk
Game will run one tic after every file status is updated
2020-07-01 23:48:14 -04:00
Ashnal 8eb9a6946f Fix X/0 files display bug for legacy downloader
Also made "Waiting to Download" consistent with other states
2020-07-01 21:40:21 -04:00
Sal c3c466575c Merge branch 'fix-pk3-leak' into 'master'
Fix memory leak in W_ReadLumpHeaderPwad

See merge request KartKrew/Kart-Public!182
2020-07-01 18:36:48 -04:00
Sal 9f4b4d84a6 Merge branch 'http-useragent-fix' into 'master'
Fix user agent for HTTP downloads being set as SRB2Kart/v1.1.2

See merge request KartKrew/Kart-Public!185
2020-07-01 18:36:33 -04:00
Sal d2098c23fc Merge branch 'ogl-color-fix3' into 'master'
Ogl colormap fix third attempt

See merge request KartKrew/Kart-Public!184
2020-07-01 18:36:19 -04:00
Sal b6272fa299 Merge branch 'chatbug-fix' into 'master'
clientside ack fix

See merge request KartKrew/Kart-Public!186
2020-07-01 18:35:57 -04:00
Ashnal ad94b29558 Experiemntal clientside ack fix
Stops the client from using reliable packets before joining a server
Clients can time out during addon loading
sending reliable packets before then can cause out of order acks
This causes joinbug, chatbug, and chatspam, as well as
general server instability due to unnecesary packetspam
2020-06-27 23:43:15 -04:00
Ashnal f2593219a6 Adjust text position 2020-06-27 23:40:13 -04:00
Ashnal d96c938dbf Add progress bar for file loading 2020-06-27 23:26:38 -04:00
Ashnal 9d9105929b Adjustment to new progress text 2020-06-27 21:17:21 -04:00
Ashnal fc9f40a177 New "Overall Download Progress" bar
Shows progress of all file downloads pre-join
2020-06-27 21:17:04 -04:00
Ashnal 12d40a07cc Load one file per tic
Prevents game from locking up when loading large file lists
2020-06-27 20:58:33 -04:00
Steel Titanium 3af4aaff9c Fix user agent for HTTP downloads being set as SRB2Kart/v1.1.2 2020-06-23 18:39:02 -04:00
James R bae37aea2c ADD to the buffer size 2020-06-14 19:13:22 -07:00
Hannu Hanhi 44159de7f3 Colormap alpha handling was still wrong, hopefully it's correct now 2020-06-14 15:03:40 +03:00
Sal eea8c3776c Merge branch 'ogl-color-fix-fix' into 'master'
Fix bug in the OpenGL colormap bugfix

See merge request KartKrew/Kart-Public!183
2020-06-13 22:45:47 -04:00
Hannu Hanhi c382794109 Fix uninitialized alpha when reading colormaps 2020-06-13 23:34:13 +03:00
Hannu Hanhi 38c3d78d8a Cleaner version of the W_ReadLumpHeaderPwad memory leak fix 2020-06-13 21:37:33 +03:00
Hannu Hanhi 2f65955496 Add missing inflateEnd to fix memory leak in W_ReadLumpHeaderPwad 2020-06-13 17:07:05 +03:00
Sryder b96d315f25 Merge branch 'master' of git@git.magicalgirl.moe:KartKrew/Kart-Public.git into next 2020-06-13 14:15:58 +01:00
James R e7d949aeb2 masterserver_token is back 2020-06-12 23:47:08 -07:00
James R 9b3456a860 Merge remote-tracking branch 'origin/master' into http-mserv 2020-06-12 23:36:39 -07:00
Sal f7e74e8884 Merge branch 'ogl-encore-color-fix' into 'master'
Fix bug in OpenGL encore colormaps

See merge request KartKrew/Kart-Public!180
2020-06-12 22:39:18 -04:00
Hannu Hanhi d9e2336277 Guil's encore color bugfix with some additional cleanup 2020-06-01 21:14:17 +03:00
Sal 691a567f5d Merge branch 'fix-ogl-log-crash' into 'master'
Fix opengl crashing on startup due to lack of checks

See merge request KartKrew/Kart-Public!179
2020-05-28 09:47:16 -04:00
Steel Titanium 3f3cb2c976 Fix opengl crashing on startup due to lack of checks
Also fixes the log file not being written to the home directory.
2020-05-23 16:21:26 -04:00
Sryder b03f950c5a Merge branch 'master' into next 2020-05-20 16:50:56 +01:00
Sryder e229aabf22 Merge branch 'fix-clang-compile' into 'master'
Fix clang compiling

See merge request KartKrew/Kart-Public!176
2020-05-20 11:49:47 -04:00
Sryder 6b8ea22bdb Merge branch 'opengl-maybe-uninitialised' into 'master'
Some uninitialised variables that GCC 4.4 complains about

See merge request KartKrew/Kart-Public!177
2020-05-20 11:49:34 -04:00
Sryder 831ed3dedc Merge branch 'itemodds-fallthrough-fix' into 'next'
Mistaken fallthrough in item roulette.

See merge request KartKrew/Kart-Public!178
2020-05-20 11:49:22 -04:00
Sal 73b65b4725 Merge branch 'no-spb-forcing-in-2p' into 'next'
Don't force SPB in 1v1

See merge request KartKrew/Kart-Public!175
2020-05-20 10:11:19 -04:00
Sal 5f70d3e170 Merge branch 'visplane-fix' into 'master'
Fix visplane getting allocated twice

See merge request KartKrew/Kart-Public!172
2020-05-20 10:11:06 -04:00
Sryder 9e6980c8ae Fix a fallthrough issue that could cause thundershield to be rolled less often than intended. 2020-05-20 11:53:14 +01:00
Sryder 66930a0277 Initialise these to 0 just to stop GCC 4.4 from complaining.
This should be okay since 0 generally means "nothing" for these, and they should always be set before being used later on.
2020-05-20 11:47:22 +01:00
Sryder 290abe4fce D_ModifierKeyResponder is unused now so remove it. 2020-05-20 11:37:38 +01:00
Sally Coolatta a7c88d40db Merge branch 'master' into next 2020-05-19 20:40:12 -04:00
TehRealSalt 21e6190932 Don't force SPB in 1v1
(cherry picked from commit 22af2040a021cff243773a0f23371f20e69dfca5)
2020-05-19 20:12:53 -04:00
Sryder c70cf4806b Merge branch 'extra-travis-deploy' into 'master'
Fix Travis Deployment

See merge request KartKrew/Kart-Public!174
2020-05-19 20:10:42 -04:00
Sal e42ae1ed79 Merge branch 'freeplay-be-nice' into 'master'
Also apply HUD translucency to FREE PLAY

See merge request KartKrew/Kart-Public!161
2020-05-19 17:29:05 -04:00
Sal 1d5774fe2f Merge branch 'ghostly-luavars' into 'next'
Fix Luavars being saved into Record Attack ghosts/replays and potentially crashing

See merge request KartKrew/Kart-Public!168
2020-05-19 17:28:48 -04:00
Sal 71d2d357c1 Merge branch 'displayplayer-gonna-getcha' into 'next'
displayplayers.iterate crashes in replays, is that based?

See merge request KartKrew/Kart-Public!171
2020-05-19 17:28:14 -04:00
Sal bb7481a13e Merge branch 'mr-ogl-boostpad-fix' into 'master'
Fix wrong orientation in some boost pads in ogl

See merge request KartKrew/Kart-Public!173
2020-05-19 17:27:24 -04:00
Sryder bca1dd42a3 Use xenial to build all the versions newer than trusty
I'm not 100% sure why we can't use newer series to build the newer installers. But this seems to be what vanilla does
2020-05-19 20:45:49 +01:00
Sal cb9e6473a0 Merge branch 'use-extern-you-idiot' into 'master'
Fix GCC 10 linking errors

See merge request KartKrew/Kart-Public!170
2020-05-16 09:01:46 -04:00
Hannu Hanhi c3e1e1df26 Fix wrong orientation some boost pads in ogl 2020-05-16 13:47:21 +03:00
filpAM 5acafa5a87 Fix visplane getting allocated twice 2020-05-16 00:20:52 +00:00
Sal f60d05764d Merge branch 'clearbans-please' into 'master'
Write empty file on clearbans

See merge request KartKrew/Kart-Public!156
2020-05-15 19:29:11 -04:00
Sal f0f4b7bc1e Merge branch 'nomixer-fix' into 'master'
Fix "NOMIXER" flag compiling

See merge request KartKrew/Kart-Public!159
2020-05-15 19:28:54 -04:00
Sal 43874c3a4d Merge branch 'now-we-spin-in-spinout-only' into 'master'
No more first person hyper spin

See merge request KartKrew/Kart-Public!160
2020-05-15 19:28:38 -04:00
Sal e4766bbaf1 Merge branch 'ferror-errno-yareyare' into 'master'
Fix false file error reporting

See merge request KartKrew/Kart-Public!162
2020-05-15 19:27:08 -04:00
Sal 11331b7bc5 Merge branch 'hud-is-fucked' into 'next'
HUD inconsistency in Record Attack

See merge request KartKrew/Kart-Public!164
2020-05-15 19:26:26 -04:00
Sal ffdb12ccb0 Merge branch 'fastline-identification' into 'next'
Add targets to MT_FASTLINEs that are spawned

See merge request KartKrew/Kart-Public!169
2020-05-15 19:24:35 -04:00
Sal c9c8e5f15f Merge branch 'player-dot-ping' into 'next'
player.ping for the ping in milliseconds of the player

See merge request KartKrew/Kart-Public!167
2020-05-15 19:24:21 -04:00
Sal f2a9981299 Merge branch 'alias-recursion-fix' into 'master'
Fix alias recursion never counting down

See merge request KartKrew/Kart-Public!166
2020-05-15 19:24:02 -04:00
Sryder e0aa6ef252 Use bionic to build focal version because it has GCC 4.8? 2020-05-16 00:02:33 +01:00
James R 7e0b605f34 Properly bound lua displayplayers and displayplayers.iterate to splitscreen
This is fixes crashes in replays because splitscreen displayplayers are
initialized to INT32_MAX there.
2020-05-15 14:21:25 -07:00
James R fcbe4e668f Set timeout on HMS connections 2020-05-15 13:20:40 -07:00
James R bd3ea52cba ok
(cherry picked from commit 0b9c20cc7086000548e02b39c1abf94ffb56feae)
2020-05-15 11:21:40 -07:00
James R 6bd6b3f38e Add missing extern to colortranslations 2020-05-15 10:00:05 -07:00
Monster Iestyn 697c7f859e added missing extern keyword for ms_RoomId in mserv.h (the definition is already in the .c file in this case)
(cherry picked from commit 064f4bcf349e9600552a0b99bd0fbfb3cbcf0958)
2020-05-15 09:58:49 -07:00
Monster Iestyn f89400c728 turn all non-extern variables in s_sound.h into externs (and put their real definitions in the .c file)
(cherry picked from commit dab212dc56936dd92a935d0c81003ff1d35ee2ee)
2020-05-15 09:58:28 -07:00
Monster Iestyn 05c8865528 make savegamename in doomdef.h an extern, put the actual definition in d_main.c
(cherry picked from commit 89cd756cd83e4a03a34d1f16da18142d8167d889)
2020-05-15 09:52:16 -07:00
James R e8a2397dea Rename hms123311.c to http-mserv.c
HMS lives on in our hearts!
2020-05-14 17:26:10 -07:00
James R a6ce21b450 Use Unlock_state here too 2020-05-14 17:23:06 -07:00
James R 85fef2655c Resize response body buffer as needed 2020-05-14 17:19:25 -07:00
Sryder dbcbbf1ae4 Remove now unsupported distros from deployer
Add new supported distros to deployer
2020-05-14 13:16:49 +01:00
Snu 6b5eebe54a Use P_SetTarget instead of fast->target 2020-05-14 04:17:24 +01:00
Snu 3997c05988 god damnit 2020-05-14 03:23:28 +01:00
Snu f24340f46a add targets to MT_FASTLINEs spawned to tell what they're spawned from 2020-05-14 03:13:00 +01:00
Latapostrophe d949a47a70 Don't save Luavars in record attack, especially not for ghosts 2020-05-14 01:41:06 +02:00
James R 615823f024 player.ping for the ping in milliseconds of the player 2020-05-13 16:17:40 -07:00
Latapostrophe d0b4f8765d Merge branch 'master' of git.magicalgirl.moe:KartKrew/Kart-Public 2020-05-14 01:04:30 +02:00
Monster Iestyn db5cb986ee Detect infinite alias self-recursion mixed with other commands, such as in the case of `alias a "echo test; a"; a`.
(Unfortunately, this does not work if "wait" is used instead of "echo", but oh well)

(cherry picked from commit 797ca99f42)
2020-05-13 16:03:26 -07:00
James R 430fb27ec8 Bind HMS connection with -bindaddr 2020-05-13 15:29:17 -07:00
James R 9dc72f46a2 Identify this branch with VERSIONSTRING
This is temporary.
2020-05-12 19:27:54 -07:00
James R 2f63f97692 Reset the masterserver address if the old one was set by the config 2020-05-12 19:22:30 -07:00
James R 72852ab341 Clarify where debug prints go when using masterserver_debug 2020-05-12 19:22:15 -07:00
James R be3da445c3 Use IPv4 for master server connections
Your server's address is gathered from the request, so it needs to be IPv4!
2020-05-12 18:52:55 -07:00
James R bdcae79cd2 Use new two digit version number for HMS 2020-05-12 17:51:27 -07:00
James R 233e6627de Merge remote-tracking branch 'origin/master' into http-mserv 2020-05-12 17:50:32 -07:00
James R e2733600cd Oops a debug condition snuck in there 2020-04-28 14:35:03 -07:00
James R a1aa2a5e12 Fix switching the master server 2020-04-28 14:21:57 -07:00
James R e950efa5fc Put some mutex on CONS_Printf etc. hahaha 2020-04-28 13:08:43 -07:00
James R e20dccafd4 Fucking multithreading in the server registration
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2020-04-28 12:33:50 -07:00
James R 8f3820db66 Wait for threads before SDL_Quit (lol) 2020-04-27 18:03:10 -07:00
James R bdddeb9ecf Create cond if it doesn't exist when signaling 2020-04-27 18:01:27 -07:00
James R 88bcac0168 Use malloc for hms 2020-04-26 21:56:59 -07:00
Steel Titanium ba989dce10 Support for http downloads
(cherry picked from commit 6fcc06bf72)

(cherry picked just the libcurl stuff)
2020-04-26 20:01:15 -07:00
James R c96506dd3b Make mod update, room list and server list multithreaded
This took fucking ages and it still fails sometimes in edge cases, but I
don't give a FUCK right now.
2020-04-26 19:46:35 -07:00
James R c472a9f50d Multithreading in my SRB2??? 2020-04-17 20:05:29 -07:00
James R 7b714a225b WHY THE FUCK DID I DO THIS 2020-04-15 22:04:55 -07:00
James R 60bc61ef70 Oops 2020-04-14 19:41:32 -07:00
James R 30b5ec14fd Handle NULL hms buffer 2020-04-14 16:55:14 -07:00
James R 7488991ecd Compiler errors: won't stop, can't stop 2020-04-13 23:31:26 -07:00
James R a0de059235 masterserver_update_rate cvar determines wait between updates in minutes
The new default is 15 minutes as well. And if you think that's too long, I have
confirmed that the Master Server delists inactive servers after a whopping 40
minutes, at least.
2020-04-13 23:10:06 -07:00
James R ee6de3800e Don't try to update right after registering 2020-04-13 22:54:58 -07:00
James R 2c5566b013 Add a hack so the 'All' room isn't display for hosting 2020-04-13 22:31:11 -07:00
James R 1201e89132 Kill the old mserv, long live HMS! 2020-04-13 22:23:01 -07:00
James R 7255d360e1 Clean up header text 2020-04-13 21:20:29 -07:00
James R 032adadd86 HTTP update alert 2020-04-12 20:37:46 -07:00
James R 48b2112af7 Fix some goofs 2020-04-12 18:33:53 -07:00
James R 03caf27d92 Bruh 2020-04-12 18:27:01 -07:00
James R 269746fe01 Clean up a bunch of stuff and follow the Master Server API more closely 2020-04-12 18:25:59 -07:00
James R 3f4224ed37 Windows certs do work, thanks Steel! 2020-04-12 17:51:30 -07:00
James R 969fe0b28e Handle more errors 2020-04-12 17:51:05 -07:00
James R ef71bef6f3 Kill masterserver_token 2020-04-12 17:15:39 -07:00
James R f0cc851b29 This will be the Master Server in 2020 2020-03-20 20:37:26 -07:00
James R 3f9f07af84 Use https because my web server redirects 2020-03-01 12:31:49 -08:00
James R 56fac10b14 strtok can return NULL 2020-03-01 12:15:48 -08:00
James R 9d42a5ad5e This time I fucked up 2020-03-01 11:59:54 -08:00
James R aca2e97c84 Windows gaysed: the sequel 2020-03-01 11:54:21 -08:00
James R ceb332e580 Windows is weird 2020-03-01 11:46:02 -08:00
James R 32a34cc1b2 masterserver_debug to set CURLOPT_VERBOSE 2020-03-01 11:39:27 -08:00
James R 1959a9b107 Don't show "All" room when hosting 2020-03-01 11:19:59 -08:00
James R 8756ef15a2 I don't even know my own website 2020-03-01 11:17:56 -08:00
James R 47a5f9ef94 lol 2020-03-01 10:59:25 -08:00
James R e2507f390f The big bad HTTP master server
Cvars:

http_masterserver is the url to the master server's API.
masterserver_token may be an authentication token.
2020-03-01 02:36:56 -08:00
Latapostrophe 0c3b5d603b Merge branch 'master' of git.magicalgirl.moe:KartKrew/Kart-Public 2019-11-11 22:15:30 +01:00
James R 44e59e2688 Don't hide HUD with hu_showscores in single player/Record Attack
This also makes Lua game HUD consistent with the Kart HUD.
2019-10-19 14:11:24 -07:00
James R 1d6020883c Forgot includes 2019-10-07 18:10:33 -07:00
James R abaefa05b1 ferror does not return errno, are you stupid?
Use M_FileError to return the proper error description, or "end-of-file".
2019-10-07 17:55:31 -07:00
James R 5e9082fb77 Also apply HUD translucency to FREE PLAY 2019-09-19 20:29:51 -07:00
James R 3801f93181 Let first person camera work in demos 2019-09-15 00:32:01 -07:00
filpAM fe4cbd7ba1 Fix "NOMIXER" flag compiling 2019-09-13 13:20:44 -04:00
James R 3838700f2c Save bans when cleared too
(Why doesn't it work for I_Quit?)
2019-08-22 15:18:14 -07:00
Latapostrophe 496f6bcd79 Merge branch 'master' of git.magicalgirl.moe:KartKrew/Kart-Public 2019-07-02 18:24:14 +02:00
Latapostrophe 3b3a63cd90 Merge branch 'master' of git.magicalgirl.moe:KartKrew/Kart-Public 2019-04-21 15:57:03 +02:00
Latapostrophe c772b05f8c Merge branch 'master' of git.magicalgirl.moe:KartKrew/Kart 2019-04-20 10:44:17 +02:00
Alam Ed Arias 3f4e0286eb Merge branch 'master' into io 2016-03-07 16:23:08 -05:00
Alam Ed Arias bdad2ccc12 Merge branch 'next' into io 2016-02-26 01:57:28 -05:00
wolfy852 db7da456d2 Remove block on % in filename strings
According to Alam, supporting this shouldn't cause any issues.
2016-01-29 01:38:41 -06:00
Monster Iestyn 2eedecb93a Get rid of unneeded tab spaces
Least I can do to make up for breaking io.open in the first place :E
2016-01-26 12:07:28 +00:00
Nipples the Enchilada 9c299e5ad4 Fix and clean up io_open after MI broke it horribly
strcpy(NULL, filename); congrats
2016-01-25 22:13:24 -06:00
Monster Iestyn 14dcd2404b Fixed compiler warnings to the best of my ability
Hopefully this all still works properly, try not to kill me if it doesn't =V
2016-01-25 22:12:54 -06:00
Monster Iestyn 63a3e03bb0 Fixed math for calculating current texture in texture animations 2016-01-25 22:12:53 -06:00
Monster Iestyn f65c5c016a Fix shadowing in mapheaderinfo_get 2016-01-25 22:12:52 -06:00
Alam Ed Arias c7e540a870 whitespace cleanup 2016-01-25 22:12:51 -06:00
Inuyasha c30188f9fd interscreen is a lump name and thus needs lstring
... not just lstring though, but the behavior with i that is used elsewhere.
2016-01-25 22:12:50 -06:00
Inuyasha f559b50995 fix bad lstring usage in map header lua
This is not how you use pushlstring! This is actually sending uninitialized memory to Lua, which is making scripts have inconsistent results (duh?)

c/o JTE: "Tell Red they're a doofus."
2016-01-25 22:12:50 -06:00
Monster Iestyn f2f8906a19 Use modulo, not bitwise AND. My fault once again, whoops.
The point here is ColorOpposite(MAXSKINCOLORS) would have given an actual result of its own since MAXSKINCOLORS & MAXSKINCOLORS is still MAXSKINCOLORS. This shouldn't happen though, as both Color_Opposite[MAXSKINCOLORS*2] and Color_Opposite[MAXSKINCOLOR*2+1] aren't defined.
2016-01-25 22:12:49 -06:00
Inuyasha 0f2a092741 objectplace stability fix
Objectplace reallocates the mapthings list to add one more mapthing. By itself there's no problem with this.
But, mobj->spawnpoint is a pointer to the mapthing's location in the mapthings list.
So by reallocating the mapthings list, all references to mobj->spawnpoints point to freed memory.

... Oops.

Now when objectplace reallocates the mapthings list it actually corrects the locations of all mobj's spawnpoints to point to the new list.

Hooray, you can use NiGHTS objectplace again if you really want to.
2016-01-25 22:12:48 -06:00
Nipples the Enchilada 2639bf4c0b Add liolib.c to CMakeLists 2016-01-23 23:29:27 -06:00
wolfy852 591b803566 Limit file write size to 1MB
If the total file size is above 1MB after writing, discard all changes.
2016-01-22 21:45:48 -06:00
wolfy852 e274946528 Call I_mkdir on subdirectories [NEEDS CLEANUP]
I got lazy and used a weird inefficient method, but I don't know how to clean this mess up :c At least it works.
2016-01-22 00:46:32 -06:00
wolfy852 5579fb5240 Limit file creation/manipulation to luafiles subfolder
Also block % in filename strings
2016-01-20 22:35:53 -06:00
wolfy852 de03db99e7 Block possible methods of accessing folders outside of SRB2 2016-01-20 21:31:00 -06:00
wolfy852 569f7d15d1 Efficiency improvement in whitelist check
Thanks Inu!
2016-01-20 16:59:55 -06:00
wolfy852 a68e92690f Implement file type whitelist, completely remove popen and pclose
This is probably super inefficient. Someone please teach me how2C.
2016-01-20 02:26:15 -06:00
wolfy852 c9fe83b95d Block the use of ../ and ..\\
...and remove io.popen(), cause that shit is DANGEROUS.
2016-01-17 01:37:19 -06:00
wolfy852 eb7c36d72c Reimplement I/O library
Note: I/O library is fully functioning in this state, but lacks security restrictions. We'll get to those later ;)
2016-01-16 19:31:36 -06:00
62 changed files with 4019 additions and 1432 deletions

View File

@ -439,6 +439,30 @@ matrix:
# List Ubuntu LTS, newest to oldest
# Then list non-LTS, newest to oldest
################################
- os: linux
addons:
apt:
packages:
- libsdl2-mixer-dev
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
- libcurl4-openssl-dev
- p7zip-full
- gcc-4.8
compiler: gcc-4.8
dist: xenial
if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
AND env(DPL_TERMINATE_MAIN) != "1"
env:
- _DPL_JOB_ENABLED=1
- _DPL_JOB_NAME=focal
- _DPL_DPUT_TARGET=1
- _DPL_PACKAGE_SOURCE=1
- PACKAGE_DISTRO=focal
- PACKAGE_SUBVERSION=~20.04focal
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
apt:
@ -463,6 +487,30 @@ matrix:
- PACKAGE_DISTRO=bionic
- PACKAGE_SUBVERSION=~18.04bionic
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
apt:
packages:
- libsdl2-mixer-dev
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
- libcurl4-openssl-dev
- p7zip-full
- gcc-4.8
compiler: gcc-4.8
dist: xenial
if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
AND env(DPL_TERMINATE_MAIN) != "1"
env:
- _DPL_JOB_ENABLED=1
- _DPL_JOB_NAME=xenial
- _DPL_DPUT_TARGET=1
- _DPL_PACKAGE_SOURCE=1
- PACKAGE_DISTRO=xenial
- PACKAGE_SUBVERSION=~16.04xenial
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
apt:
@ -505,59 +553,11 @@ matrix:
AND env(DPL_TERMINATE_MAIN) != "1"
env:
- _DPL_JOB_ENABLED=1
- _DPL_JOB_NAME=disco
- _DPL_JOB_NAME=eoan
- _DPL_DPUT_TARGET=1
- _DPL_PACKAGE_SOURCE=1
- PACKAGE_DISTRO=disco
- PACKAGE_SUBVERSION=~19.04disco
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
apt:
packages:
- libsdl2-mixer-dev
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
- libcurl4-openssl-dev
- p7zip-full
- gcc-4.8
compiler: gcc-4.8
dist: xenial
if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
AND env(DPL_TERMINATE_MAIN) != "1"
env:
- _DPL_JOB_ENABLED=1
- _DPL_JOB_NAME=cosmic
- _DPL_DPUT_TARGET=1
- _DPL_PACKAGE_SOURCE=1
- PACKAGE_DISTRO=cosmic
- PACKAGE_SUBVERSION=~18.10cosmic
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
apt:
packages:
- libsdl2-mixer-dev
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
- libcurl4-openssl-dev
- p7zip-full
- gcc-4.8
compiler: gcc-4.8
dist: xenial
if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
AND env(DPL_TERMINATE_MAIN) != "1"
env:
- _DPL_JOB_ENABLED=1
- _DPL_JOB_NAME=xenial
- _DPL_DPUT_TARGET=1
- _DPL_PACKAGE_SOURCE=1
- PACKAGE_DISTRO=xenial
- PACKAGE_SUBVERSION=~16.04xenial
- PACKAGE_DISTRO=eoan
- PACKAGE_SUBVERSION=~19.10eoan
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
allow_failures:
- compiler: clang-3.5

View File

@ -35,6 +35,7 @@ set(SRB2_CORE_SOURCES
m_random.c
md5.c
mserv.c
http-mserv.c
s_sound.c
screen.c
sounds.c
@ -277,6 +278,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
blua/lfunc.c
blua/lgc.c
blua/linit.c
blua/liolib.c
blua/llex.c
blua/lmem.c
blua/lobject.c

View File

@ -484,6 +484,7 @@ DBGNAME?=$(EXENAME).debug
OBJS:=$(i_main_o) \
$(OBJDIR)/comptime.o \
$(OBJDIR)/string.o \
$(OBJDIR)/d_async.o \
$(OBJDIR)/d_main.o \
$(OBJDIR)/d_clisrv.o \
$(OBJDIR)/d_net.o \
@ -548,6 +549,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/w_wad.o \
$(OBJDIR)/filesrch.o \
$(OBJDIR)/mserv.o \
$(OBJDIR)/http-mserv.o\
$(OBJDIR)/i_tcp.o \
$(OBJDIR)/lzf.o \
$(OBJDIR)/vid_copy.o \

View File

@ -18,6 +18,7 @@ OBJS:=$(OBJS) \
$(OBJDIR)/ldo.o \
$(OBJDIR)/lfunc.o \
$(OBJDIR)/linit.o \
$(OBJDIR)/liolib.o \
$(OBJDIR)/llex.o \
$(OBJDIR)/lmem.o \
$(OBJDIR)/lobject.o \

View File

@ -17,6 +17,7 @@
static const luaL_Reg lualibs[] = {
{"", luaopen_base},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_STRLIBNAME, luaopen_string},
{NULL, NULL}
};

589
src/blua/liolib.c Normal file
View File

@ -0,0 +1,589 @@
/*
** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define liolib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "../i_system.h"
#include "../doomdef.h"
#include "../m_misc.h"
#define IO_INPUT 1
#define IO_OUTPUT 2
#define FILELIMIT 1024*1024 // Size limit for reading/writing files
static const char *const fnames[] = {"input", "output"};
static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
".txt",
".sav2",
".cfg",
".png",
".bmp"
};
static int pushresult (lua_State *L, int i, const char *filename) {
int en = errno; /* calls to Lua API may change this value */
if (i) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, en);
return 3;
}
}
static void fileerror (lua_State *L, int arg, const char *filename) {
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
luaL_argerror(L, arg, lua_tostring(L, -1));
}
#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
static int io_type (lua_State *L) {
void *ud;
luaL_checkany(L, 1);
ud = lua_touserdata(L, 1);
lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
lua_pushnil(L); /* not a file */
else if (*((FILE **)ud) == NULL)
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
return 1;
}
static FILE *tofile (lua_State *L) {
FILE **f = tofilep(L);
if (*f == NULL)
luaL_error(L, "attempt to use a closed file");
return *f;
}
/*
** When creating file handles, always creates a `closed' file handle
** before opening the actual file; so, if there is a memory error, the
** file is not left opened.
*/
static FILE **newfile (lua_State *L) {
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
*pf = NULL; /* file handle is currently `closed' */
luaL_getmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2);
return pf;
}
/*
** function to (not) close the standard files stdin, stdout, and stderr
*/
static int io_noclose (lua_State *L) {
lua_pushnil(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
}
/*
** function to close regular files
*/
static int io_fclose (lua_State *L) {
FILE **p = tofilep(L);
int ok = (fclose(*p) == 0);
*p = NULL;
return pushresult(L, ok, NULL);
}
static int aux_close (lua_State *L) {
lua_getfenv(L, 1);
lua_getfield(L, -1, "__close");
return (lua_tocfunction(L, -1))(L);
}
static int io_close (lua_State *L) {
if (lua_isnone(L, 1))
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
tofile(L); /* make sure argument is a file */
return aux_close(L);
}
static int io_gc (lua_State *L) {
FILE *f = *tofilep(L);
/* ignore closed files */
if (f != NULL)
aux_close(L);
return 0;
}
static int io_tostring (lua_State *L) {
FILE *f = *tofilep(L);
if (f == NULL)
lua_pushliteral(L, "file (closed)");
else
lua_pushfstring(L, "file (%p)", f);
return 1;
}
static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again
{
if(strncmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
static int io_open (lua_State *L) {
FILE **pf;
const char *filename = luaL_checkstring(L, 1);
int pass = 0;
size_t i;
int length = strlen(filename);
char *splitter, *forward, *backward;
char *destFilename;
const char *mode = luaL_optstring(L, 2, "r");
for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++)
{
if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i]))
{
pass = 1;
break;
}
}
if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\")
|| StartsWith(filename, "/") || !pass)
{
luaL_error(L,"access denied to %s", filename);
return pushresult(L,0,filename);
}
destFilename = va("luafiles"PATHSEP"%s", filename);
// Make directories as needed
splitter = destFilename;
forward = strchr(splitter, '/');
backward = strchr(splitter, '\\');
while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward)))
{
*splitter = 0;
I_mkdir(destFilename, 0755);
*splitter = '/';
splitter++;
forward = strchr(splitter, '/');
backward = strchr(splitter, '\\');
}
pf = newfile(L);
*pf = fopen(destFilename, mode);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
}
static int io_tmpfile (lua_State *L) {
FILE **pf = newfile(L);
*pf = tmpfile();
return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
}
static FILE *getiofile (lua_State *L, int findex) {
FILE *f;
lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
f = *(FILE **)lua_touserdata(L, -1);
if (f == NULL)
luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
return f;
}
static int g_iofile (lua_State *L, int f, const char *mode) {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
if (filename) {
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
if (*pf == NULL)
fileerror(L, 1, filename);
}
else {
tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
lua_rawseti(L, LUA_ENVIRONINDEX, f);
}
/* return current value */
lua_rawgeti(L, LUA_ENVIRONINDEX, f);
return 1;
}
static int io_input (lua_State *L) {
return g_iofile(L, IO_INPUT, "r");
}
static int io_output (lua_State *L) {
return g_iofile(L, IO_OUTPUT, "w");
}
static int io_readline (lua_State *L);
static void aux_lines (lua_State *L, int idx, int toclose) {
lua_pushvalue(L, idx);
lua_pushboolean(L, toclose); /* close/not close file when finished */
lua_pushcclosure(L, io_readline, 2);
}
static int f_lines (lua_State *L) {
tofile(L); /* check that it's a valid file handle */
aux_lines(L, 1, 0);
return 1;
}
static int io_lines (lua_State *L) {
if (lua_isnoneornil(L, 1)) { /* no arguments? */
/* will iterate over default input */
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
return f_lines(L);
}
else {
const char *filename = luaL_checkstring(L, 1);
FILE **pf = newfile(L);
*pf = fopen(filename, "r");
if (*pf == NULL)
fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1);
return 1;
}
}
/*
** {======================================================
** READ
** =======================================================
*/
static int read_number (lua_State *L, FILE *f) {
lua_Number d;
if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
lua_pushnumber(L, d);
return 1;
}
else return 0; /* read fails */
}
static int test_eof (lua_State *L, FILE *f) {
int c = getc(f);
ungetc(c, f);
lua_pushlstring(L, NULL, 0);
return (c != EOF);
}
static int read_line (lua_State *L, FILE *f) {
luaL_Buffer b;
luaL_buffinit(L, &b);
for (;;) {
size_t l;
char *p = luaL_prepbuffer(&b);
if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
luaL_pushresult(&b); /* close buffer */
return (lua_objlen(L, -1) > 0); /* check whether read something */
}
l = strlen(p);
if (l == 0 || p[l-1] != '\n')
luaL_addsize(&b, l);
else {
luaL_addsize(&b, l - 1); /* do not include `eol' */
luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */
}
}
}
static int read_chars (lua_State *L, FILE *f, size_t n) {
size_t rlen; /* how much to read */
size_t nr; /* number of chars actually read */
luaL_Buffer b;
luaL_buffinit(L, &b);
rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
do {
char *p = luaL_prepbuffer(&b);
if (rlen > n) rlen = n; /* cannot read more than asked */
nr = fread(p, sizeof(char), rlen, f);
luaL_addsize(&b, nr);
n -= nr; /* still have to read `n' chars */
} while (n > 0 && nr == rlen); /* until end of count or eof */
luaL_pushresult(&b); /* close buffer */
return (n == 0 || lua_objlen(L, -1) > 0);
}
static int g_read (lua_State *L, FILE *f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f);
n = first+1; /* to return 1 result */
}
else { /* ensure stack space for all results and for auxlib's buffer */
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
success = 1;
for (n = first; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
size_t l = (size_t)lua_tointeger(L, n);
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
}
else {
const char *p = lua_tostring(L, n);
luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
switch (p[1]) {
case 'n': /* number */
success = read_number(L, f);
break;
case 'l': /* line */
success = read_line(L, f);
break;
case 'a': /* file */
read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
success = 1; /* always success */
break;
default:
return luaL_argerror(L, n, "invalid format");
}
}
}
}
if (ferror(f))
return pushresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
}
return n - first;
}
static int io_read (lua_State *L) {
return g_read(L, getiofile(L, IO_INPUT), 1);
}
static int f_read (lua_State *L) {
return g_read(L, tofile(L), 2);
}
static int io_readline (lua_State *L) {
FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
int sucess;
if (f == NULL) /* file is already closed? */
luaL_error(L, "file is already closed");
sucess = read_line(L, f);
if (ferror(f))
return luaL_error(L, "%s", strerror(errno));
if (sucess) return 1;
else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
lua_settop(L, 0);
lua_pushvalue(L, lua_upvalueindex(1));
aux_close(L); /* close it */
}
return 0;
}
}
/* }====================================================== */
static int g_write (lua_State *L, FILE *f, int arg) {
int nargs = lua_gettop(L) - 1;
int status = 1;
size_t count;
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
status = status &&
fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
}
else {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
count += l;
if (ftell(f) + l > FILELIMIT)
{
luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
break;
}
status = status && (fwrite(s, sizeof(char), l, f) == l);
}
}
return pushresult(L, status, NULL);
}
static int io_write (lua_State *L) {
return g_write(L, getiofile(L, IO_OUTPUT), 1);
}
static int f_write (lua_State *L) {
return g_write(L, tofile(L), 2);
}
static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames);
long offset = luaL_optlong(L, 3, 0);
op = fseek(f, offset, mode[op]);
if (op)
return pushresult(L, 0, NULL); /* error */
else {
lua_pushinteger(L, ftell(f));
return 1;
}
}
static int f_setvbuf (lua_State *L) {
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
static const char *const modenames[] = {"no", "full", "line", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, NULL, modenames);
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
int res = setvbuf(f, NULL, mode[op], sz);
return pushresult(L, res == 0, NULL);
}
static int io_flush (lua_State *L) {
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int f_flush (lua_State *L) {
return pushresult(L, fflush(tofile(L)) == 0, NULL);
}
static const luaL_Reg iolib[] = {
{"close", io_close},
{"flush", io_flush},
{"input", io_input},
{"lines", io_lines},
{"open", io_open},
{"output", io_output},
{"read", io_read},
{"tmpfile", io_tmpfile},
{"type", io_type},
{"write", io_write},
{NULL, NULL}
};
static const luaL_Reg flib[] = {
{"close", io_close},
{"flush", f_flush},
{"lines", f_lines},
{"read", f_read},
{"seek", f_seek},
{"setvbuf", f_setvbuf},
{"write", f_write},
{"__gc", io_gc},
{"__tostring", io_tostring},
{NULL, NULL}
};
static void createmeta (lua_State *L) {
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_register(L, NULL, flib); /* file methods */
}
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
*newfile(L) = f;
if (k > 0) {
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_ENVIRONINDEX, k);
}
lua_pushvalue(L, -2); /* copy environment */
lua_setfenv(L, -2); /* set it */
lua_setfield(L, -3, fname);
}
static void newfenv (lua_State *L, lua_CFunction cls) {
lua_createtable(L, 0, 1);
lua_pushcfunction(L, cls);
lua_setfield(L, -2, "__close");
}
LUALIB_API int luaopen_io (lua_State *L) {
createmeta(L);
/* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
newfenv(L, io_fclose);
lua_replace(L, LUA_ENVIRONINDEX);
/* open library */
luaL_register(L, LUA_IOLIBNAME, iolib);
/* create (and set) default files */
newfenv(L, io_noclose); /* close function for default files */
createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, 0, "stderr");
lua_pop(L, 1); /* pop environment for default files */
return 1;
}

View File

@ -21,6 +21,9 @@ LUALIB_API int (luaopen_base) (lua_State *L);
#define LUA_TABLIBNAME "table"
LUALIB_API int (luaopen_table) (lua_State *L);
#define LUA_IOLIBNAME "io"
LUALIB_API int (luaopen_io) (lua_State *L);
#define LUA_STRLIBNAME "string"
LUALIB_API int (luaopen_string) (lua_State *L);

View File

@ -18,6 +18,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "d_main.h"
#include "command.h"
#include "console.h"
#include "z_zone.h"
@ -34,6 +35,8 @@
#include "p_setup.h"
#include "lua_script.h"
#include "d_netfil.h" // findfile
#include "d_async.h"
#include "filesrch.h"
//========
// protos.
@ -120,11 +123,9 @@ void COM_BufAddText(const char *ptext)
l = strlen(ptext);
if (com_text.cursize + l >= com_text.maxsize)
{
CONS_Alert(CONS_WARNING, M_GetText("Command buffer full!\n"));
return;
}
VS_Write(&com_text, ptext, l);
else
VS_Write(&com_text, ptext, l);
}
/** Adds command text and executes it immediately.
@ -543,10 +544,7 @@ static void COM_ExecuteString(char *ptext)
if (!stricmp(com_argv[0], a->name))
{
if (recursion > MAX_ALIAS_RECURSION)
{
CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n"));
recursion = 0;
}
else
{
char buf[1024];
@ -578,8 +576,10 @@ static void COM_ExecuteString(char *ptext)
}
WRITESTRING(write, read);
// Monster Iestyn: keep track of how many levels of recursion we're in
recursion++;
COM_BufInsertText(buf);
recursion--;
}
return;
}
@ -673,12 +673,60 @@ static void COM_CEchoDuration_f(void)
HU_SetCEchoDuration(atoi(COM_Argv(1)));
}
struct COM_Exec_Ctx
{
boolean noerror;
boolean silent;
UINT8 * buf;
};
static void Free_COM_Exec_Ctx (struct COM_Exec_Ctx *ctx)
{
Z_Free(ctx->buf);
Z_Free(ctx);
}
void COM_ExecuteFile (void *p, void *u)
{
filequery_t * q = p;
struct COM_Exec_Ctx * ctx = u;
ctx->buf = NULL;
if (q->status == FS_FOUND)
{
FIL_ReadFile(q->filename, &ctx->buf);
}
if (ctx->buf)
{
if (! ctx->silent)
CONS_Printf(M_GetText("executing %s\n"), q->filename);
// insert text file into the command buffer
COM_BufAddText((char *)ctx->buf);
COM_BufAddText("\n");
}
else
{
if (! ctx->noerror)
CONS_Printf(M_GetText("couldn't execute file %s\n"), q->filename);
}
Free_COM_Exec_Ctx(ctx);
}
/** Executes a script file.
*/
static void COM_Exec_f(void)
{
UINT8 *buf = NULL;
char filename[256];
char filenamebuf[MAX_WADPATH];
struct COM_Exec_Ctx *ctx;
const char * filename;
filequery_t q;
if (COM_Argc() < 2 || COM_Argc() > 3)
{
@ -686,35 +734,36 @@ static void COM_Exec_f(void)
return;
}
// load file
// Try with Argv passed verbatim first, for back compat
FIL_ReadFile(COM_Argv(1), &buf);
filename = COM_Argv(1);
if (!buf)
ctx = ZZ_Alloc(sizeof *ctx);
ctx->noerror = COM_CheckParm("-noerror");
ctx->silent = COM_CheckParm("-silent");
if (COM_CheckParm("-sync"))
{
// Now try by searching the file path
// filename is modified with the full found path
strcpy(filename, COM_Argv(1));
if (findfile(filename, NULL, true) != FS_NOTFOUND)
FIL_ReadFile(filename, &buf);
q.filename = filenamebuf;
if (!buf)
strcpy(q.filename, filename);
if (FIL_FileOK(va(pandf,srb2home,filename)))
{
if (!COM_CheckParm("-noerror"))
CONS_Printf(M_GetText("couldn't execute file %s\n"), COM_Argv(1));
return;
q.status = FS_FOUND;
}
else
{
q.status = findfile(q.filename, NULL, true);
}
COM_ExecuteFile(&q, ctx);
}
else
{
q.filename = strcpy(ZZ_Alloc(MAX_WADPATH), filename);
Append_async_addfile(ASYNC_EXEC, q.filename, ctx);
}
if (!COM_CheckParm("-silent"))
CONS_Printf(M_GetText("executing %s\n"), COM_Argv(1));
// insert text file into the command buffer
COM_BufAddText((char *)buf);
COM_BufAddText("\n");
// free buffer
Z_Free(buf);
}
/** Delays execution of the rest of the commands until the next frame.

View File

@ -45,6 +45,9 @@ void COM_ImmedExecute(const char *ptext);
// Execute commands in buffer, flush them
void COM_BufExecute(void);
// Execute a whole file (internal use only :v)
void COM_ExecuteFile(void *query, void *ctx);
// As above; and progress the wait timer.
void COM_BufTicker(void);

View File

@ -31,6 +31,7 @@
#include "i_video.h"
#include "z_zone.h"
#include "i_system.h"
#include "i_threads.h"
#include "d_main.h"
#include "m_menu.h"
#include "filesrch.h"
@ -45,6 +46,16 @@
#define MAXHUDLINES 20
#ifdef HAVE_THREADS
I_mutex con_mutex;
# define Lock_state() I_lock_mutex(&con_mutex)
# define Unlock_state() I_unlock_mutex(con_mutex)
#else/*HAVE_THREADS*/
# define Lock_state()
# define Unlock_state()
#endif/*HAVE_THREADS*/
static boolean con_started = false; // console has been initialised
boolean con_startup = false; // true at game startup, screen need refreshing
static boolean con_forcepic = true; // at startup toggle console translucency when first off
@ -170,6 +181,8 @@ static void CONS_hudlines_Change(void)
{
INT32 i;
Lock_state();
// Clear the currently displayed lines
for (i = 0; i < con_hudlines; i++)
con_hudtime[i] = 0;
@ -181,6 +194,8 @@ static void CONS_hudlines_Change(void)
con_hudlines = cons_hudlines.value;
Unlock_state();
CONS_Printf(M_GetText("Number of console HUD lines is now %d\n"), con_hudlines);
}
@ -188,12 +203,16 @@ static void CONS_hudlines_Change(void)
//
static void CONS_Clear_f(void)
{
Lock_state();
memset(con_buffer, 0, CON_BUFFERSIZE);
con_cx = 0;
con_cy = con_totallines-1;
con_line = &con_buffer[con_cy*con_width];
con_scrollup = 0;
Unlock_state();
}
// Choose english keymap
@ -369,20 +388,29 @@ void CON_Init(void)
for (i = 0; i < NUMINPUTS; i++)
bindtable[i] = NULL;
Lock_state();
// clear all lines
memset(con_buffer, 0, CON_BUFFERSIZE);
// make sure it is ready for the loading screen
con_width = 0;
Unlock_state();
CON_RecalcSize();
CON_SetupColormaps();
Lock_state();
//note: CON_Ticker should always execute at least once before D_Display()
con_clipviewtop = -1; // -1 does not clip
con_hudlines = atoi(cons_hudlines.defaultvalue);
Unlock_state();
// setup console input filtering
CON_InputInit();
@ -391,15 +419,23 @@ void CON_Init(void)
COM_AddCommand("cls", CONS_Clear_f);
//COM_AddCommand("english", CONS_English_f);
// set console full screen for game startup MAKE SURE VID_Init() done !!!
Lock_state();
con_destlines = vid.height;
con_curlines = vid.height;
Unlock_state();
if (!dedicated)
{
Lock_state();
con_started = true;
con_startup = true; // need explicit screen refresh until we are in Doom loop
consoletoggle = false;
Unlock_state();
CV_RegisterVar(&cons_msgtimeout);
CV_RegisterVar(&cons_hudlines);
CV_RegisterVar(&cons_speed);
@ -411,19 +447,27 @@ void CON_Init(void)
}
else
{
Lock_state();
con_started = true;
con_startup = false; // need explicit screen refresh until we are in Doom loop
consoletoggle = true;
Unlock_state();
}
}
// Console input initialization
//
static void CON_InputInit(void)
{
Lock_state();
// prepare the first prompt line
memset(inputlines, 0, sizeof (inputlines));
inputline = 0;
input_cur = input_sel = input_len = 0;
Unlock_state();
}
//======================================================================
@ -439,6 +483,8 @@ static void CON_RecalcSize(void)
char *tmp_buffer;
char *string;
Lock_state();
switch (cv_constextsize.value)
{
case V_NOSCALEPATCH:
@ -476,11 +522,18 @@ static void CON_RecalcSize(void)
// check for change of video width
if (conw == con_width)
{
Unlock_state();
return; // didn't change
}
Unlock_state();
tmp_buffer = Z_Malloc(CON_BUFFERSIZE, PU_STATIC, NULL);
string = Z_Malloc(CON_BUFFERSIZE, PU_STATIC, NULL); // BP: it is a line but who know
Lock_state();
oldcon_width = con_width;
oldnumlines = con_totallines;
oldcon_cy = con_cy;
@ -501,6 +554,8 @@ static void CON_RecalcSize(void)
con_line = &con_buffer[con_cy*con_width];
con_scrollup = 0;
Unlock_state();
// re-arrange console text buffer to keep text
if (oldcon_width) // not the first time
{
@ -525,7 +580,11 @@ static void CON_RecalcSize(void)
static void CON_ChangeHeight(void)
{
INT32 minheight = 20 * con_scalefactor; // 20 = 8+8+4
INT32 minheight;
Lock_state();
minheight = 20 * con_scalefactor; // 20 = 8+8+4
// toggle console in
con_destlines = (cons_height.value*vid.height)/100;
@ -535,13 +594,19 @@ static void CON_ChangeHeight(void)
con_destlines = vid.height;
con_destlines &= ~0x3; // multiple of text row height
Unlock_state();
}
// Handles Console moves in/out of screen (per frame)
//
static void CON_MoveConsole(void)
{
const fixed_t conspeed = FixedDiv(cons_speed.value*vid.fdupy, FRACUNIT);
fixed_t conspeed;
Lock_state();
conspeed = FixedDiv(cons_speed.value*vid.fdupy, FRACUNIT);
// instant
if (!cons_speed.value)
@ -563,6 +628,8 @@ static void CON_MoveConsole(void)
if (con_curlines < con_destlines)
con_curlines = con_destlines;
}
Unlock_state();
}
INT32 CON_ShiftChar(INT32 ch)
@ -587,27 +654,44 @@ void CON_ClearHUD(void)
{
INT32 i;
Lock_state();
for (i = 0; i < con_hudlines; i++)
con_hudtime[i] = 0;
Unlock_state();
}
// Force console to move out immediately
// note: con_ticker will set consoleready false
void CON_ToggleOff(void)
{
Lock_state();
if (!con_destlines)
{
Unlock_state();
return;
}
con_destlines = 0;
con_curlines = 0;
CON_ClearHUD();
con_forcepic = 0;
con_clipviewtop = -1; // remove console clipping of view
Unlock_state();
}
boolean CON_Ready(void)
{
return consoleready;
boolean ready;
Lock_state();
{
ready = consoleready;
}
Unlock_state();
return ready;
}
// Console ticker: handles console move in/out, cursor blinking
@ -615,7 +699,11 @@ boolean CON_Ready(void)
void CON_Ticker(void)
{
INT32 i;
INT32 minheight = 20 * con_scalefactor; // 20 = 8+8+4
INT32 minheight;
Lock_state();
minheight = 20 * con_scalefactor; // 20 = 8+8+4
// cursor blinking
con_tick++;
@ -673,6 +761,8 @@ void CON_Ticker(void)
if (con_hudtime[i] < 0)
con_hudtime[i] = 0;
}
Unlock_state();
}
//
@ -684,32 +774,51 @@ void CON_Ticker(void)
static void CON_InputClear(void)
{
Lock_state();
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
input_cur = input_sel = input_len = 0;
Unlock_state();
}
static void CON_InputSetString(const char *c)
{
Lock_state();
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
strcpy(inputlines[inputline], c);
input_cur = input_sel = input_len = strlen(c);
Unlock_state();
}
static void CON_InputAddString(const char *c)
{
size_t csize = strlen(c);
Lock_state();
if (input_len + csize > CON_MAXPROMPTCHARS-1)
{
Unlock_state();
return;
}
if (input_cur != input_len)
memmove(&inputlines[inputline][input_cur+csize], &inputlines[inputline][input_cur], input_len-input_cur);
memcpy(&inputlines[inputline][input_cur], c, csize);
input_len += csize;
input_sel = (input_cur += csize);
Unlock_state();
}
static void CON_InputDelSelection(void)
{
size_t start, end, len;
Lock_state();
if (input_cur > input_sel)
{
start = input_sel;
@ -728,27 +837,39 @@ static void CON_InputDelSelection(void)
input_len -= len;
input_sel = input_cur = start;
Unlock_state();
}
static void CON_InputAddChar(char c)
{
if (input_len >= CON_MAXPROMPTCHARS-1)
return;
Lock_state();
if (input_cur != input_len)
memmove(&inputlines[inputline][input_cur+1], &inputlines[inputline][input_cur], input_len-input_cur);
inputlines[inputline][input_cur++] = c;
inputlines[inputline][++input_len] = 0;
input_sel = input_cur;
Unlock_state();
}
static void CON_InputDelChar(void)
{
if (!input_cur)
return;
Lock_state();
if (input_cur != input_len)
memmove(&inputlines[inputline][input_cur-1], &inputlines[inputline][input_cur], input_len-input_cur);
inputlines[inputline][--input_len] = 0;
input_sel = --input_cur;
Unlock_state();
}
//
@ -1174,6 +1295,8 @@ static void CON_Print(char *msg)
S_StartSound(NULL, sfx_radio);
}
Lock_state();
if (!(*msg & 0x80))
{
con_line[con_cx++] = '\x80';
@ -1234,7 +1357,10 @@ static void CON_Print(char *msg)
}
if (*msg == '\0')
{
Unlock_state();
return;
}
// printable character
for (l = 0; l < (con_width-11) && msg[l] > ' '; l++)
@ -1252,6 +1378,8 @@ static void CON_Print(char *msg)
for (; l > 0; l--)
con_line[con_cx++] = *(msg++);
}
Unlock_state();
}
void CON_LogMessage(const char *msg)
@ -1283,6 +1411,7 @@ void CONS_Printf(const char *fmt, ...)
{
va_list argptr;
static char *txt = NULL;
boolean startup;
if (txt == NULL)
txt = malloc(8192);
@ -1315,11 +1444,23 @@ void CONS_Printf(const char *fmt, ...)
CON_LogMessage(txt);
#endif
Lock_state();
// make sure new text is visible
con_scrollup = 0;
startup = con_startup;
Unlock_state();
#ifdef HAVE_THREADS
if (! I_on_main_thread())
{
return;
}
#endif
// if not in display loop, force screen update
if (con_startup)
if (startup)
{
#if (defined (_WINDOWS)) || (defined (__OS2__) && !defined (HAVE_SDL))
patch_t *con_backpic = W_CachePatchName("KARTKREW", PU_CACHE);
@ -1633,8 +1774,13 @@ static void CON_DrawConsole(void)
//
void CON_Drawer(void)
{
Lock_state();
if (!con_started || !graphics_started)
{
Unlock_state();
return;
}
if (con_recalc)
CON_RecalcSize();
@ -1644,4 +1790,6 @@ void CON_Drawer(void)
else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS
|| gamestate == GS_VOTING || gamestate == GS_EVALUATION || gamestate == GS_WAITINGPLAYERS)
CON_DrawHudlines();
Unlock_state();
}

View File

@ -12,6 +12,7 @@
#include "d_event.h"
#include "command.h"
#include "i_threads.h"
#ifdef _WII
void CON_InitWii(void);
@ -21,6 +22,10 @@ void CON_Init(void);
boolean CON_Responder(event_t *ev);
#ifdef HAVE_THREADS
extern I_mutex con_mutex;
#endif
// set true when screen size has changed, to adapt console
extern boolean con_recalc;

259
src/d_async.c Normal file
View File

@ -0,0 +1,259 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file d_async.c
/// \brief Add wad/exec config asynchronously to the main thread, but in order
#include "doomdef.h"
#include "d_main.h"
#include "d_async.h"
#include "filesrch.h"
#include "i_threads.h"
#include "m_misc.h"
#include "p_setup.h"
#include "z_zone.h"
struct filename_queue;
struct async_addfile;
typedef struct filename_queue filename_queue_t;
typedef struct async_addfile async_addfile_t;
struct filename_queue
{
int type;
char * name;
void * u;/* exec command has some parameters that need know */
filename_queue_t * next;
};
struct async_addfile
{
int done;
int query_size;
int query_position;
filequery_t * query;
int * type;
void ** u;
async_addfile_t * next;
};
static filename_queue_t * queue_head;
static filename_queue_t * queue_tail;
static int queue_size;
static I_mutex async_mutex;
static async_addfile_t * async_head;
static async_addfile_t * async_tail;
static void
Async_addfile_thread (async_addfile_t *file)
{
findmultiplefiles(file->query_size, file->query, false, true, &async_mutex);
I_lock_mutex(&async_mutex);
{
file->done = 1;
}
I_unlock_mutex(async_mutex);
}
static void
Do_addfile (int type, filequery_t *q, void *ctx)
{
switch (type)
{
case ASYNC_EXEC:
COM_ExecuteFile(q, ctx);
break;
}
}
void
Finish_async_addfile (void)
{
async_addfile_t * file = async_head;
async_addfile_t * next;
filequery_t * q;
filestatus_t status;
int type;
int done;
while (file != NULL)
{
while (file->query_position < file->query_size)
{
q = &file->query [file->query_position];
type = file->type [file->query_position];
I_lock_mutex(&async_mutex);
{
status = q->status;
}
I_unlock_mutex(async_mutex);
if (status == FS_NOTCHECKED)
{
break;
}
else
{
Do_addfile(type, q, file->u[file->query_position]);
}
Z_Free(q->filename);
file->query_position++;
}
if (file->query_position < file->query_size)
{
break;
}
I_lock_mutex(&async_mutex);
{
done = file->done;
}
I_unlock_mutex(async_mutex);
if (done)
{
next = file->next;
Z_Free(file->u);
Z_Free(file->type);
Z_Free(file->query);
Z_Free(file);
file = next;
}
else
{
break;
}
}
async_head = file;
if (file == NULL)
{
async_tail = NULL;
}
}
void
Append_async_addfile (int type, const char * filename, void * userdata)
{
char filenamebuf[MAX_WADPATH];
filename_queue_t * q;
filequery_t file;
if (FIL_FileOK(va(pandf,srb2home,filename)))
{
file.status = FS_FOUND;
file.filename = filenamebuf;
strcpy(file.filename, filename);
Do_addfile(type, &file, userdata);
}
else
{
q = ZZ_Alloc(sizeof *q);
if (queue_tail != NULL)
{
queue_tail->next = q;
}
else
{
queue_head = q;
}
queue_tail = q;
queue_size++;
q->type = type;
q->name = strcpy(ZZ_Alloc(MAX_WADPATH), filename);
q->u = userdata;
q->next = NULL;
}
}
void
Detach_async_addfile (void)
{
filename_queue_t * q = queue_head;
filename_queue_t * next;
async_addfile_t * file;
filequery_t * query;
int * type;
void ** udata;
if (q != NULL)
{
file = ZZ_Alloc(sizeof *file);
if (async_tail != NULL)
{
async_tail->next = file;
}
else
{
async_head = file;
}
async_tail = file;
file->done = 0;
file->next = NULL;
file->query_size = queue_size;
file->query_position = 0;
file->query = ZZ_Alloc(queue_size * sizeof (*file->query));
file->type = ZZ_Alloc(queue_size * sizeof (*file->type));
file->u = ZZ_Alloc(queue_size * sizeof (*file->u));
query = file->query;
type = file->type;
udata = file->u;
do
{
*type++ = q->type;
*udata++ = q->u;
query->status = FS_NOTCHECKED;
query->wantedmd5sum = NULL;
query->filename = q->name;
query++;
next = q->next;
Z_Free(q);
}
while (( q = next ) != NULL) ;
I_spawn_thread("async-addfile",
(I_thread_fn)Async_addfile_thread, file);
queue_head = NULL;
queue_tail = NULL;
queue_size = 0;
}
}

44
src/d_async.h Normal file
View File

@ -0,0 +1,44 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file d_async.h
/// \brief Add wad/exec config asynchronously to the main thread, but in order
#ifndef D_ASYNC_H
#define D_ASYNC_H
enum
{
ASYNC_ADDFILE,
ASYNC_EXEC,
};
/*
Queue a file to be added. Detach_async_addfile will spawn a thread that
searches for any files if necessary.
*/
void Append_async_addfile (int type, const char * filename, void * ctx);
/*
Although the file searching is done on another thread, the actual adding of the
wad or executing the config must be done on the main thread. This function is
called every tic to check if a file was found so it can perform that last step.
It does this in order.
*/
void Finish_async_addfile (void);
/*
Spawns a thread that searches for files that were queued.
Called at the end of each tic.
*/
void Detach_async_addfile (void);
#endif/*D_ASYNC_H*/

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
#include "d_netcmd.h"
#include "tables.h"
#include "d_player.h"
#include "mserv.h"
/*
The 'packet version' is used to distinguish packet formats.
@ -531,6 +532,7 @@ typedef enum
} kickreason_t;
extern boolean server;
extern boolean serverrunning;
#define client (!server)
extern boolean dedicated; // For dedicated server
extern UINT16 software_MAXPACKETLENGTH;
@ -577,6 +579,7 @@ void CL_RemoveSplitscreenPlayer(UINT8 p);
void CL_Reset(void);
void CL_ClearPlayer(INT32 playernum);
void CL_RemovePlayer(INT32 playernum, INT32 reason);
void CL_QueryServerList(msg_server_t *list);
void CL_UpdateServerList(boolean internetsearch, INT32 room);
// Is there a game running
boolean Playing(void);

View File

@ -50,6 +50,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "hu_stuff.h"
#include "i_sound.h"
#include "i_system.h"
#include "i_threads.h"
#include "i_video.h"
#include "m_argv.h"
#include "m_menu.h"
@ -143,6 +144,8 @@ boolean advancedemo;
INT32 debugload = 0;
#endif
char savegamename[256];
#ifdef _arch_dreamcast
char srb2home[256] = "/cd";
char srb2path[256] = "/cd";
@ -185,35 +188,6 @@ UINT8 shiftdown = 0; // 0x1 left, 0x2 right
UINT8 ctrldown = 0; // 0x1 left, 0x2 right
UINT8 altdown = 0; // 0x1 left, 0x2 right
boolean capslock = 0; // gee i wonder what this does.
//
// D_ModifierKeyResponder
// Sets global shift/ctrl/alt variables, never actually eats events
//
static inline void D_ModifierKeyResponder(event_t *ev)
{
if (ev->type == ev_keydown || ev->type == ev_console) switch (ev->data1)
{
case KEY_LSHIFT: shiftdown |= 0x1; return;
case KEY_RSHIFT: shiftdown |= 0x2; return;
case KEY_LCTRL: ctrldown |= 0x1; return;
case KEY_RCTRL: ctrldown |= 0x2; return;
case KEY_LALT: altdown |= 0x1; return;
case KEY_RALT: altdown |= 0x2; return;
case KEY_CAPSLOCK: capslock = !capslock; return;
default: return;
}
else if (ev->type == ev_keyup) switch (ev->data1)
{
case KEY_LSHIFT: shiftdown &= ~0x1; return;
case KEY_RSHIFT: shiftdown &= ~0x2; return;
case KEY_LCTRL: ctrldown &= ~0x1; return;
case KEY_RCTRL: ctrldown &= ~0x2; return;
case KEY_LALT: altdown &= ~0x1; return;
case KEY_RALT: altdown &= ~0x2; return;
default: return;
}
}
//
// D_ProcessEvents
@ -223,6 +197,8 @@ void D_ProcessEvents(void)
{
event_t *ev;
boolean eaten;
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
{
ev = &events[eventtail];
@ -244,7 +220,17 @@ void D_ProcessEvents(void)
}
// Menu input
if (M_Responder(ev))
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
{
eaten = M_Responder(ev);
}
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
if (eaten)
continue; // menu ate the event
// Demo input:
@ -253,7 +239,17 @@ void D_ProcessEvents(void)
continue; // demo ate the event
// console input
if (CON_Responder(ev))
#ifdef HAVE_THREADS
I_lock_mutex(&con_mutex);
#endif
{
eaten = CON_Responder(ev);
}
#ifdef HAVE_THREADS
I_unlock_mutex(con_mutex);
#endif
if (eaten)
continue; // ate the event
G_Responder(ev);
@ -280,7 +276,7 @@ static void D_Display(void)
{
if (nodrawers)
return; // for comparative timing/profiling
// check for change of screen size (video mode)
if (setmodeneeded && !wipe)
SCR_SetMode(); // change video mode
@ -549,7 +545,13 @@ static void D_Display(void)
if (gamestate != GS_TIMEATTACK)
CON_Drawer();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of everything
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
// focus lost moved to M_Drawer
//

View File

@ -19,7 +19,9 @@
#define __D_NET__
// Max computers in a game
#define MAXNETNODES 64
// 127 is probably as high as this can go, because
// SINT8 is used for nodes sometimes >:(
#define MAXNETNODES 127
#define BROADCASTADDR MAXNETNODES
#define NETSPLITSCREEN // Kart's splitscreen netgame feature
@ -41,6 +43,8 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
extern boolean serverrunning;
INT32 Net_GetFreeAcks(boolean urgent);
void Net_AckTicker(void);

View File

@ -4088,7 +4088,7 @@ static void Command_RunSOC(void)
static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
{
char filename[256];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
@ -4260,7 +4260,7 @@ static void Command_Delfile(void)
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16];
boolean kick = false;
boolean toomany = false;
@ -4355,7 +4355,7 @@ static void Got_Delfilecmd(UINT8 **cp, INT32 playernum)
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
filestatus_t ncs = FS_NOTFOUND;
filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16];
READSTRINGN(*cp, filename, 240);

View File

@ -108,6 +108,10 @@ char downloaddir[512] = "DOWNLOAD";
#ifdef CLIENT_LOADINGSCREEN
// for cl loading screen
INT32 lastfilenum = -1;
INT32 downloadcompletednum = 0;
UINT32 downloadcompletedsize = 0;
INT32 totalfilesrequestednum = 0;
UINT32 totalfilesrequestedsize = 0;
#endif
#ifdef HAVE_CURL
@ -141,7 +145,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus;
for (i = mainwads; i < numwadfiles; i++)
for (i = mainwads+1; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad
{
// If it has only music/sound lumps, don't put it in the list
if (!wadfiles[i]->important)
@ -207,7 +211,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
p = (UINT8 *)fileneededstr;
for (i = firstfile; i < fileneedednum; i++)
{
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet
filestatus = READUINT8(p); // The first byte is the file status
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
@ -370,15 +374,17 @@ boolean Got_RequestFilePak(INT32 node)
* \return 0 if some files are missing
* 1 if all files exist
* 2 if some already loaded files are not requested or are in a different order
* 3 too many files, over WADLIMIT
* 4 still checking, continuing next tic
*
*/
INT32 CL_CheckFiles(void)
{
INT32 i, j;
char wadfilename[MAX_WADPATH];
INT32 ret = 1;
size_t packetsize = 0;
size_t filestoget = 0;
size_t filestoload = 0;
boolean downloadrequired = false;
// if (M_CheckParm("-nofiles"))
// return 1;
@ -395,7 +401,7 @@ INT32 CL_CheckFiles(void)
if (modifiedgame)
{
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;)
for (i = 0, j = mainwads+1; i < fileneedednum || j < numwadfiles;)
{
if (j < numwadfiles && !wadfiles[j]->important)
{
@ -424,10 +430,19 @@ INT32 CL_CheckFiles(void)
for (i = 0; i < fileneedednum; i++)
{
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_FALLBACK)
downloadrequired = true;
if (fileneeded[i].status == FS_FOUND || fileneeded[i].status == FS_NOTFOUND)
filestoload++;
if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics
continue;
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
// Check in already loaded files
for (j = mainwads; wadfiles[j]; j++)
for (j = mainwads+1; wadfiles[j]; j++)
{
nameonly(strcpy(wadfilename, wadfiles[j]->filename));
if (!stricmp(wadfilename, fileneeded[i].filename) &&
@ -435,36 +450,35 @@ INT32 CL_CheckFiles(void)
{
CONS_Debug(DBG_NETPLAY, "already loaded\n");
fileneeded[i].status = FS_OPEN;
break;
return 4;
}
}
if (fileneeded[i].status != FS_NOTFOUND)
continue;
packetsize += nameonlylength(fileneeded[i].filename) + 22;
if (mainwads+filestoget >= MAX_WADFILES)
return 3;
filestoget++;
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
if (fileneeded[i].status != FS_FOUND)
ret = 0;
return 4;
}
return ret;
//now making it here means we've checked the entire list and no FS_NOTCHECKED files remain
if (numwadfiles+filestoload > MAX_WADFILES)
return 3;
else if (downloadrequired)
return 0; //some stuff is FS_NOTFOUND, needs download
else
return 1; //everything is FS_OPEN or FS_FOUND, proceed to loading
}
// Load it now
void CL_LoadServerFiles(void)
boolean CL_LoadServerFiles(void)
{
INT32 i;
// if (M_CheckParm("-nofiles"))
// return;
for (i = 1; i < fileneedednum; i++)
for (i = 0; i < fileneedednum; i++)
{
if (fileneeded[i].status == FS_OPEN)
continue; // Already loaded
@ -473,6 +487,7 @@ void CL_LoadServerFiles(void)
P_AddWadFile(fileneeded[i].filename);
G_SetGameModified(true, false);
fileneeded[i].status = FS_OPEN;
return false;
}
else if (fileneeded[i].status == FS_MD5SUMBAD)
I_Error("Wrong version of file %s", fileneeded[i].filename);
@ -498,6 +513,7 @@ void CL_LoadServerFiles(void)
fileneeded[i].status, s);
}
}
return true;
}
// Number of files to send
@ -768,7 +784,7 @@ void SV_FileSendTicker(void)
if (ram)
M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, strerror(ferror(transfer[i].currentfile)));
I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile));
p->position = LONG(transfer[i].position);
// Put flag so receiver knows the total size
if (transfer[i].position + size == f->size)
@ -847,7 +863,7 @@ void Got_Filetxpak(void)
// We can receive packet in the wrong order, anyway all os support gaped file
fseek(file->file, pos, SEEK_SET);
if (fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1)
I_Error("Can't write to %s: %s\n",filename, strerror(ferror(file->file)));
I_Error("Can't write to %s: %s\n",filename, M_FileError(file->file));
file->currentsize += size;
// Finished?
@ -858,6 +874,8 @@ void Got_Filetxpak(void)
file->status = FS_FOUND;
CONS_Printf(M_GetText("Downloading %s...(done)\n"),
filename);
downloadcompletednum++;
downloadcompletedsize += file->totalsize;
}
}
else
@ -1005,13 +1023,13 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
// Rewritten by Monster Iestyn to be less stupid
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
filestatus_t findmultiplefiles(int n, filequery_t *files, boolean checkmd5, boolean completepath, void *mutex_ptr)
{
filestatus_t homecheck; // store result of last file search
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third)
// first, check SRB2's "home" directory
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
homecheck = filesearch(n, files, srb2home, checkmd5, completepath, 10, mutex_ptr);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
@ -1020,7 +1038,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
// if not found at all, just move on without doing anything
// next, check SRB2's "path" directory
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
homecheck = filesearch(n, files, srb2path, checkmd5, completepath, 10, mutex_ptr);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
@ -1030,9 +1048,9 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
// finally check "." directory
#ifdef _arch_dreamcast
homecheck = filesearch(filename, "/cd", wantedmd5sum, completepath, 10);
homecheck = filesearch(n, files, "/cd", checkmd5, completepath, 10, mutex_ptr);
#else
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10);
homecheck = filesearch(n, files, ".", checkmd5, completepath, 10, mutex_ptr);
#endif
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
@ -1041,6 +1059,12 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
}
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
{
filequery_t q = { FS_NOTFOUND, wantedmd5sum, filename };
return findmultiplefiles(1, &q, ( wantedmd5sum != NULL ), completepath, NULL);
}
#ifdef HAVE_CURL
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
@ -1088,7 +1112,7 @@ void CURLPrepareFile(const char* url, int dfilenum)
// Only allow HTTP and HTTPS
curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents.
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents.
// Follow a redirect request, if sent by the server.
curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L);
@ -1169,6 +1193,8 @@ void CURLGetFile(void)
{
nameonly(curl_realname);
CONS_Printf(M_GetText("Finished downloading %s\n"), curl_realname);
downloadcompletednum++;
downloadcompletedsize += curl_curfile->totalsize;
curl_curfile->status = FS_FOUND;
fclose(curl_curfile->file);
}

View File

@ -25,6 +25,7 @@ typedef enum
typedef enum
{
FS_NOTCHECKED,
FS_NOTFOUND,
FS_FOUND,
FS_REQUESTED,
@ -52,6 +53,10 @@ extern char downloaddir[512];
#ifdef CLIENT_LOADINGSCREEN
extern INT32 lastfilenum;
extern INT32 downloadcompletednum;
extern UINT32 downloadcompletedsize;
extern INT32 totalfilesrequestednum;
extern UINT32 totalfilesrequestedsize;
#endif
#ifdef HAVE_CURL
@ -65,7 +70,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
void CL_PrepareDownloadSaveGame(const char *tmpsave);
INT32 CL_CheckFiles(void);
void CL_LoadServerFiles(void);
boolean CL_LoadServerFiles(void);
void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod,
UINT8 fileid);

View File

@ -155,8 +155,8 @@ extern char logfilename[1024];
#else
#define VERSION 1 // Game version
#define SUBVERSION 2 // more precise version number
#define VERSIONSTRING "v1.2"
#define VERSIONSTRINGW L"v1.2"
#define VERSIONSTRING "v1.2 (HTTP MS)"
#define VERSIONSTRINGW L"v1.2 (HTTP MS)"
// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates!
// And change CMakeLists.txt, for CMake users!
// AND appveyor.yml, for the build bots!
@ -506,7 +506,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) FUNCDEBUG;
// Things that used to be in dstrings.h
#define SAVEGAMENAME "srb2sav"
char savegamename[256];
extern char savegamename[256];
// m_misc.h
#ifdef GETTEXT
@ -681,4 +681,10 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Hardware renderer: OpenGL
#define GL_SHADERS
#ifdef HAVE_CURL
#define MASTERSERVER
#else
#undef UPDATE_ALERT
#endif
#endif // __DOOMDEF__

View File

@ -24,6 +24,7 @@
#include "w_wad.h"
#include "z_zone.h"
#include "i_system.h"
#include "i_threads.h"
#include "m_menu.h"
#include "dehacked.h"
#include "g_input.h"
@ -317,7 +318,13 @@ void F_IntroDrawer(void)
{
I_OsPolling();
I_UpdateNoBlit();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
}
}

View File

@ -22,6 +22,7 @@
#include "z_zone.h"
#include "i_system.h"
#include "i_threads.h"
#include "m_menu.h"
#include "console.h"
#include "d_main.h"
@ -379,7 +380,15 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
I_UpdateNoBlit();
if (drawMenu)
{
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
}
I_FinishUpdate(); // page flip or blit buffer

View File

@ -33,6 +33,7 @@
#include "m_misc.h"
#include "z_zone.h"
#include "m_menu.h" // Addons_option_Onchange
#include "i_threads.h"
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX)
@ -445,17 +446,44 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
#else
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
filestatus_t filesearch(int nfiles, filequery_t *files, const char *startpath, boolean checkmd5, boolean completepath, int maxsearchdepth, void *mutex_ptr)
{
filestatus_t retval = FS_NOTFOUND;
const UINT8 *wantedmd5sum = NULL;
DIR **dirhandle;
struct dirent *dent;
struct stat fsstat;
int found = 0;
char *searchname = strdup(filename);
int depthleft = maxsearchdepth;
char searchpath[1024];
size_t *searchpathindex;
int matched;
int files_left = 0;
int i;
#ifdef HAVE_THREADS
#define Lock() I_lock_mutex ((I_mutex *)mutex_ptr)
#define Unlock() I_unlock_mutex (((mutex_ptr) ? *(I_mutex *)mutex_ptr : NULL))
#else
#define Lock() ((void)0)
#define Unlock() ((void)0)
#endif
Lock();
for (i = 0; i < nfiles; ++i)
{
if (files[i].status != FS_FOUND)
{
files_left++;
}
}
Unlock();
if (! files_left)
{
return FS_FOUND;
}
dirhandle = (DIR**) malloc(maxsearchdepth * sizeof (DIR*));
searchpathindex = (size_t *) malloc(maxsearchdepth * sizeof (size_t));
@ -467,7 +495,6 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
if (dirhandle[depthleft] == NULL)
{
free(searchname);
free(dirhandle);
free(searchpathindex);
return FS_NOTFOUND;
@ -481,7 +508,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
else
searchpathindex[depthleft]--;
while ((!found) && (depthleft < maxsearchdepth))
while ((files_left) && (depthleft < maxsearchdepth))
{
searchpath[searchpathindex[depthleft]]=0;
dent = readdir(dirhandle[depthleft]);
@ -520,34 +547,75 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
searchpath[searchpathindex[depthleft]-1]='/';
searchpath[searchpathindex[depthleft]]=0;
}
else if (!strcasecmp(searchname, dent->d_name))
else
{
switch (checkfilemd5(searchpath, wantedmd5sum))
for (i = 0; i < nfiles; ++i)
{
case FS_FOUND:
if (completepath)
strcpy(filename,searchpath);
else
strcpy(filename,dent->d_name);
retval = FS_FOUND;
found = 1;
break;
case FS_MD5SUMBAD:
retval = FS_MD5SUMBAD;
break;
default: // prevent some compiler warnings
break;
Lock();
if (checkmd5)
{
wantedmd5sum = files[i].wantedmd5sum;
}
matched = (
files[i].status != FS_FOUND &&
!strcasecmp(files[i].filename, dent->d_name)
);
Unlock();
if (matched)
{
switch (checkfilemd5(searchpath, wantedmd5sum))
{
case FS_FOUND:
Lock();
if (completepath)
strcpy(files[i].filename,searchpath);
else
strcpy(files[i].filename,dent->d_name);
files[i].status = FS_FOUND;
Unlock();
files_left--;
break;
case FS_MD5SUMBAD:
Lock();
retval = files[i].status = FS_MD5SUMBAD;
Unlock();
break;
default: // prevent some compiler warnings
break;
}
}
}
}
}
for (; depthleft < maxsearchdepth; closedir(dirhandle[depthleft++]));
free(searchname);
free(searchpathindex);
free(dirhandle);
return retval;
Lock();
{
for (i = 0; i < nfiles; ++i)
{
if (files[i].status != FS_FOUND && files[i].status != FS_MD5SUMBAD)
{
files[i].status = FS_NOTFOUND;
}
}
}
Unlock();
return ( (files_left) ? retval : FS_FOUND );
#undef Lock
#undef Unlock
}
char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two)

View File

@ -8,25 +8,38 @@
#include "d_netfil.h"
#include "m_menu.h" // MAXSTRINGLENGTH
typedef struct
{
filestatus_t status;
const UINT8 * wantedmd5sum;
char * filename;
}
filequery_t;
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
/** \brief The filesearch function
This function search files, manly WADs and return back the status of the file
\param filename the file to look for
\param nfiles number of files
\param queries the files to look for
\param startpath where to start look from
\param wantedmd5sum want to check with MD5
\param completepath want to return the complete path of the file?
\param maxsearchdepth the max depth to search for the file
\return filestatus_t
\return FS_FOUND if all files were found, FS_NOTFOUND or FS_MD5SUMBAD
if some files were not found
*/
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth);
filestatus_t filesearch(int nfiles, filequery_t *queries, const char *startpath,
boolean checkmd5, boolean completepath, int maxsearchdepth, void *mutex_ptr);
/* this is a better place for it tbh (im still too lazy to move the other) */
filestatus_t findmultiplefiles(int nfiles, filequery_t *files,
boolean checkmd5, boolean completepath, void *mutex_ptr);
#define menudepth 20

View File

@ -6368,7 +6368,9 @@ void G_BeginRecording(void)
demoflags |= DF_ENCORE;
#ifdef HAVE_BLUA
demoflags |= DF_LUAVARS;
if (!modeattacking) // Ghosts don't read luavars, and you shouldn't ever need to save Lua in replays, you doof!
// SERIOUSLY THOUGH WHY WOULD YOU LOAD HOSTMOD AND RECORD A GHOST WITH IT !????
demoflags |= DF_LUAVARS;
#endif
// Setup header.
@ -6474,8 +6476,9 @@ void G_BeginRecording(void)
WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing
#ifdef HAVE_BLUA
// player lua vars, always saved even if empty
LUA_ArchiveDemo();
// player lua vars, always saved even if empty... Unless it's record attack.
if (!modeattacking)
LUA_ArchiveDemo();
#endif
memset(&oldcmd,0,sizeof(oldcmd));
@ -7543,6 +7546,7 @@ void G_DoPlayDemo(char *defdemoname)
if (!gL) // No Lua state! ...I guess we'll just start one...
LUA_ClearState();
// No modeattacking check, DF_LUAVARS won't be present here.
LUA_UnArchiveDemo();
}
#endif

View File

@ -407,7 +407,7 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei
if (angle) // Only needs to be done if there's an altered angle
{
angle = (InvAngle(angle)+ANGLE_180)>>ANGLETOFINESHIFT;
angle = InvAngle(angle)>>ANGLETOFINESHIFT;
// This needs to be done so that it scrolls in a different direction after rotation like software
/*tempxsow = FLOAT_TO_FIXED(scrollx);
@ -439,7 +439,7 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei
tempxsow = FLOAT_TO_FIXED(v3d->s);
tempytow = FLOAT_TO_FIXED(v3d->t);
v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
v3d->t = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle))));
v3d->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
}
//v3d->s = (float)(v3d->s - flatxref + scrollx);

View File

@ -143,7 +143,7 @@ static const GLfloat byte2float[256] = {
// -----------------+
#ifdef DEBUG_TO_FILE
FILE *gllogstream;
FILE *gllogstream = NULL;
#endif
FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
@ -152,14 +152,14 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
char str[4096] = "";
va_list arglist;
if (!gllogstream)
gllogstream = fopen("ogllog.txt", "w");
if (gllogstream)
{
va_start(arglist, format);
vsnprintf(str, 4096, format, arglist);
va_end(arglist);
va_start(arglist, format);
vsnprintf(str, 4096, format, arglist);
va_end(arglist);
fwrite(str, strlen(str), 1, gllogstream);
fwrite(str, strlen(str), 1, gllogstream);
}
#else
(void)format;
#endif
@ -823,7 +823,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
#ifdef GL_SHADERS
GLuint gl_vertShader, gl_fragShader;
GLint i, result;
if (!pglUseProgram) return false;
gl_customvertexshaders[0] = NULL;
@ -2002,11 +2002,11 @@ EXPORT void HWRAPI(RenderBatches) (int *sNumPolys, int *sNumVerts, int *sNumCall
boolean stopFlag = false;
boolean changeState = false;
boolean changeShader = false;
GLuint nextShader;
GLuint nextShader = 0U;
boolean changeTexture = false;
GLuint nextTexture;
GLuint nextTexture = 0U;
boolean changePolyFlags = false;
FBITFIELD nextPolyFlags;
FBITFIELD nextPolyFlags = 0U;
boolean changeSurfaceInfo = false;
FSurfaceInfo nextSurfaceInfo;
@ -2307,7 +2307,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUI
pglColor4ubv((GLubyte*)&pSurf->PolyColor.s);
}
// Tint color
tint.red = byte2float[pSurf->TintColor.s.red];
tint.green = byte2float[pSurf->TintColor.s.green];

683
src/http-mserv.c Normal file
View File

@ -0,0 +1,683 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
// \brief HTTP based master server
/*
Documentation available here.
<http://mb.srb2.org/MS/tools/api/v1/>
*/
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
#include "doomdef.h"
#include "d_clisrv.h"
#include "command.h"
#include "m_argv.h"
#include "m_menu.h"
#include "mserv.h"
#include "i_tcp.h"/* for current_port */
#include "i_threads.h"
/* reasonable default I guess?? */
#define DEFAULT_BUFFER_SIZE (4096)
/* I just stop myself from making macros anymore. */
#define Blame( ... ) \
CONS_Printf("\x85" __VA_ARGS__)
static void MasterServer_Debug_OnChange (void);
consvar_t cv_masterserver_timeout = {
"masterserver_timeout", "5", CV_SAVE, CV_Unsigned,
NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
consvar_t cv_masterserver_debug = {
"masterserver_debug", "Off", CV_SAVE|CV_CALL, CV_OnOff,
MasterServer_Debug_OnChange, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
consvar_t cv_masterserver_token = {
"masterserver_token", "", CV_SAVE, NULL,
NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
#ifdef MASTERSERVER
static int hms_started;
static char *hms_api;
#ifdef HAVE_THREADS
static I_mutex hms_api_mutex;
#endif
static char *hms_server_token;
struct HMS_buffer
{
CURL *curl;
char *buffer;
int needle;
int end;
};
static void
Contact_error (void)
{
CONS_Alert(CONS_ERROR,
"There was a problem contacting the master server...\n"
);
}
static size_t
HMS_on_read (char *s, size_t _1, size_t n, void *userdata)
{
struct HMS_buffer *buffer;
size_t blocks;
(void)_1;
buffer = userdata;
if (n >= (size_t)( buffer->end - buffer->needle ))
{
/* resize to next multiple of buffer size */
blocks = ( n / DEFAULT_BUFFER_SIZE + 1 );
buffer->end += ( blocks * DEFAULT_BUFFER_SIZE );
buffer->buffer = realloc(buffer->buffer, buffer->end);
}
memcpy(&buffer->buffer[buffer->needle], s, n);
buffer->needle += n;
return n;
}
static struct HMS_buffer *
HMS_connect (const char *format, ...)
{
va_list ap;
CURL *curl;
char *url;
char *quack_token;
size_t seek;
size_t token_length;
struct HMS_buffer *buffer;
if (! hms_started)
{
if (curl_global_init(CURL_GLOBAL_ALL) != 0)
{
Contact_error();
Blame("From curl_global_init.\n");
return NULL;
}
else
{
atexit(curl_global_cleanup);
hms_started = 1;
}
}
curl = curl_easy_init();
if (! curl)
{
Contact_error();
Blame("From curl_easy_init.\n");
return NULL;
}
if (cv_masterserver_token.string[0])
{
quack_token = curl_easy_escape(curl, cv_masterserver_token.string, 0);
token_length = ( sizeof "?token="-1 )+ strlen(quack_token);
}
else
{
quack_token = NULL;
token_length = 0;
}
#ifdef HAVE_THREADS
I_lock_mutex(&hms_api_mutex);
#endif
seek = strlen(hms_api) + 1;/* + '/' */
va_start (ap, format);
url = malloc(seek + vsnprintf(0, 0, format, ap) + token_length + 1);
va_end (ap);
sprintf(url, "%s/", hms_api);
#ifdef HAVE_THREADS
I_unlock_mutex(hms_api_mutex);
#endif
va_start (ap, format);
seek += vsprintf(&url[seek], format, ap);
va_end (ap);
if (quack_token)
sprintf(&url[seek], "?token=%s", quack_token);
CONS_Printf("HMS: connecting '%s'...\n", url);
buffer = malloc(sizeof *buffer);
buffer->curl = curl;
buffer->end = DEFAULT_BUFFER_SIZE;
buffer->buffer = malloc(buffer->end);
buffer->needle = 0;
if (cv_masterserver_debug.value)
{
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_STDERR, logstream);
}
if (M_CheckParm("-bindaddr") && M_IsNextParm())
{
curl_easy_setopt(curl, CURLOPT_INTERFACE, M_GetNextParm());
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);
curl_free(quack_token);
free(url);
return buffer;
}
static int
HMS_do (struct HMS_buffer *buffer)
{
CURLcode cc;
long status;
char *p;
cc = curl_easy_perform(buffer->curl);
if (cc != CURLE_OK)
{
Contact_error();
Blame(
"From curl_easy_perform: %s\n",
curl_easy_strerror(cc)
);
return 0;
}
buffer->buffer[buffer->needle] = '\0';
curl_easy_getinfo(buffer->curl, CURLINFO_RESPONSE_CODE, &status);
if (status != 200)
{
p = strchr(buffer->buffer, '\n');
if (p)
*p = '\0';
Contact_error();
Blame(
"Master server error %ld: %s%s\n",
status,
buffer->buffer,
( (p) ? "" : " (malformed)" )
);
return 0;
}
else
return 1;
}
static void
HMS_end (struct HMS_buffer *buffer)
{
curl_easy_cleanup(buffer->curl);
free(buffer->buffer);
free(buffer);
}
int
HMS_fetch_rooms (int joining, int query_id)
{
struct HMS_buffer *hms;
int ok;
int doing_shit;
char *id;
char *title;
char *room_motd;
int id_no;
char *p;
char *end;
int i;
(void)query_id;
hms = HMS_connect("rooms");
if (! hms)
return 0;
if (HMS_do(hms))
{
doing_shit = 1;
p = hms->buffer;
for (i = 0; i < NUM_LIST_ROOMS && ( end = strstr(p, "\n\n\n") );)
{
*end = '\0';
id = strtok(p, "\n");
title = strtok(0, "\n");
room_motd = strtok(0, "");
if (id && title && room_motd)
{
id_no = atoi(id);
/*
Don't show the 'All' room if hosting. And it's a hack like this
because I'm way too lazy to add another feature to the MS.
*/
if (joining || id_no != 0)
{
#ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex);
{
if (query_id != ms_QueryId)
doing_shit = 0;
}
I_unlock_mutex(ms_QueryId_mutex);
if (! doing_shit)
break;
#endif
room_list[i].header.buffer[0] = 1;
room_list[i].id = id_no;
strlcpy(room_list[i].name, title, sizeof room_list[i].name);
strlcpy(room_list[i].motd, room_motd, sizeof room_list[i].motd);
i++;
}
p = ( end + 3 );/* skip the three linefeeds */
}
else
break;
}
if (doing_shit)
room_list[i].header.buffer[0] = 0;
ok = 1;
if (doing_shit)
{
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
{
for (i = 0; room_list[i].header.buffer[0]; i++)
{
if(*room_list[i].name != '\0')
{
MP_RoomMenu[i+1].text = room_list[i].name;
roomIds[i] = room_list[i].id;
MP_RoomMenu[i+1].status = IT_STRING|IT_CALL;
}
}
}
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
}
}
else
ok = 0;
HMS_end(hms);
return ok;
}
int
HMS_register (void)
{
struct HMS_buffer *hms;
int ok;
char post[256];
char *title;
hms = HMS_connect("rooms/%d/register", ms_RoomId);
if (! hms)
return 0;
title = curl_easy_escape(hms->curl, cv_servername.string, 0);
snprintf(post, sizeof post,
"port=%d&"
"title=%s&"
"version=%d.%d",
current_port,
title,
VERSION,
SUBVERSION
);
curl_free(title);
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post);
ok = HMS_do(hms);
if (ok)
{
hms_server_token = strdup(strtok(hms->buffer, "\n"));
}
HMS_end(hms);
return ok;
}
int
HMS_unlist (void)
{
struct HMS_buffer *hms;
int ok;
hms = HMS_connect("servers/%s/unlist", hms_server_token);
if (! hms)
return 0;
curl_easy_setopt(hms->curl, CURLOPT_CUSTOMREQUEST, "POST");
ok = HMS_do(hms);
HMS_end(hms);
free(hms_server_token);
return ok;
}
int
HMS_update (void)
{
struct HMS_buffer *hms;
int ok;
char post[256];
char *title;
hms = HMS_connect("servers/%s/update", hms_server_token);
if (! hms)
return 0;
title = curl_easy_escape(hms->curl, cv_servername.string, 0);
snprintf(post, sizeof post,
"title=%s",
title
);
curl_free(title);
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post);
ok = HMS_do(hms);
HMS_end(hms);
return ok;
}
void
HMS_list_servers (void)
{
struct HMS_buffer *hms;
char *p;
hms = HMS_connect("servers");
if (! hms)
return;
if (HMS_do(hms))
{
p = &hms->buffer[strlen(hms->buffer)];
while (*--p == '\n')
;
CONS_Printf("%s\n", hms->buffer);
}
HMS_end(hms);
}
msg_server_t *
HMS_fetch_servers (msg_server_t *list, int room_number, int query_id)
{
struct HMS_buffer *hms;
int doing_shit;
char local_version[9];
char *room;
char *address;
char *port;
char *title;
char *version;
char *end;
char *section_end;
char *p;
int i;
(void)query_id;
if (room_number > 0)
{
hms = HMS_connect("rooms/%d/servers", room_number);
}
else
hms = HMS_connect("servers");
if (! hms)
return NULL;
if (HMS_do(hms))
{
doing_shit = 1;
snprintf(local_version, sizeof local_version,
"%d.%d",
VERSION,
SUBVERSION
);
p = hms->buffer;
i = 0;
do
{
section_end = strstr(p, "\n\n");
room = strtok(p, "\n");
p = strtok(0, "");
if (! p)
break;
while (i < MAXSERVERLIST && ( end = strchr(p, '\n') ))
{
*end = '\0';
address = strtok(p, " ");
port = strtok(0, " ");
title = strtok(0, " ");
version = strtok(0, "");
if (address && port && title && version)
{
#ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex);
{
if (query_id != ms_QueryId)
doing_shit = 0;
}
I_unlock_mutex(ms_QueryId_mutex);
if (! doing_shit)
break;
#endif
if (strcmp(version, local_version) == 0)
{
strlcpy(list[i].ip, address, sizeof list[i].ip);
strlcpy(list[i].port, port, sizeof list[i].port);
strlcpy(list[i].name, title, sizeof list[i].name);
strlcpy(list[i].version, version, sizeof list[i].version);
list[i].room = atoi(room);
list[i].header.buffer[0] = 1;
i++;
}
if (end == section_end)/* end of list for this room */
break;
else
p = ( end + 1 );/* skip server delimiter */
}
else
{
section_end = 0;/* malformed so quit the parsing */
break;
}
}
if (! doing_shit)
break;
p = ( section_end + 2 );
}
while (section_end) ;
if (doing_shit)
list[i].header.buffer[0] = 0;
}
else
list = NULL;
HMS_end(hms);
return list;
}
int
HMS_compare_mod_version (char *buffer, size_t buffer_size)
{
struct HMS_buffer *hms;
int ok;
char *version;
char *version_name;
hms = HMS_connect("versions/%d", MODID);
if (! hms)
return 0;
ok = 0;
if (HMS_do(hms))
{
version = strtok(hms->buffer, " ");
version_name = strtok(0, "\n");
if (version && version_name)
{
if (atoi(version) != MODVERSION)
{
strlcpy(buffer, version_name, buffer_size);
ok = 1;
}
else
ok = -1;
}
}
HMS_end(hms);
return ok;
}
void
HMS_set_api (char *api)
{
#ifdef HAVE_THREADS
I_lock_mutex(&hms_api_mutex);
#endif
{
free(hms_api);
hms_api = api;
}
#ifdef HAVE_THREADS
I_unlock_mutex(hms_api_mutex);
#endif
}
#endif/*MASTERSERVER*/
static void
MasterServer_Debug_OnChange (void)
{
#ifdef MASTERSERVER
/* TODO: change to 'latest-log.txt' for log files revision. */
if (cv_masterserver_debug.value)
CONS_Printf("Master server debug messages will appear in log.txt\n");
#endif
}

View File

@ -246,7 +246,8 @@ static size_t numbans = 0;
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
static boolean init_tcp_driver = false;
static char port_name[8] = DEFAULTPORT;
static const char *serverport_name = DEFAULTPORT;
static const char *clientport_name;/* any port */
#ifndef NONET
@ -924,6 +925,7 @@ static boolean UDP_Socket(void)
#ifdef HAVE_IPV6
const INT32 b_ipv6 = M_CheckParm("-ipv6");
#endif
const char *serv;
for (s = 0; s < mysocketses; s++)
@ -939,11 +941,16 @@ static boolean UDP_Socket(void)
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if (serverrunning)
serv = serverport_name;
else
serv = clientport_name;
if (M_CheckParm("-bindaddr"))
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -964,7 +971,7 @@ static boolean UDP_Socket(void)
}
else
{
gaie = I_getaddrinfo("0.0.0.0", port_name, &hints, &ai);
gaie = I_getaddrinfo("0.0.0.0", serv, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -979,8 +986,8 @@ static boolean UDP_Socket(void)
#ifdef HAVE_MINIUPNPC
if (UPNP_support)
{
I_UPnP_rem(port_name, "UDP");
I_UPnP_add(NULL, port_name, "UDP");
I_UPnP_rem(serverport_name, "UDP");
I_UPnP_add(NULL, serverport_name, "UDP");
}
#endif
}
@ -997,7 +1004,7 @@ static boolean UDP_Socket(void)
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -1018,7 +1025,7 @@ static boolean UDP_Socket(void)
}
else
{
gaie = I_getaddrinfo("::", port_name, &hints, &ai);
gaie = I_getaddrinfo("::", serv, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -1475,15 +1482,19 @@ boolean I_InitTcpNetwork(void)
if (!I_InitTcpDriver())
return false;
if (M_CheckParm("-port"))
if (M_CheckParm("-port") || M_CheckParm("-serverport"))
// Combined -udpport and -clientport into -port
// As it was really redundant having two seperate parms that does the same thing
/* Sorry Steel, I'm adding these back. But -udpport is a stupid name. */
{
if (M_IsNextParm())
strcpy(port_name, M_GetNextParm());
else
strcpy(port_name, "0");
/*
If it's NULL, that's okay! Because then
we'll get a random port from getaddrinfo.
*/
serverport_name = M_GetNextParm();
}
if (M_CheckParm("-clientport"))
clientport_name = M_GetNextParm();
// parse network game options,
if (M_CheckParm("-server") || dedicated)

41
src/i_threads.h Normal file
View File

@ -0,0 +1,41 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file i_threads.h
/// \brief Multithreading abstraction
#ifdef HAVE_THREADS
#ifndef I_THREADS_H
#define I_THREADS_H
typedef void (*I_thread_fn)(void *userdata);
typedef void * I_mutex;
typedef void * I_cond;
void I_start_threads (void);
void I_stop_threads (void);
void I_spawn_thread (const char *name, I_thread_fn, void *userdata);
/* check in your thread whether to return early */
int I_thread_is_stopped (void);
int I_on_main_thread (void);
void I_lock_mutex (I_mutex *);
void I_unlock_mutex (I_mutex);
void I_hold_cond (I_cond *, I_mutex);
void I_wake_one_cond (I_cond *);
void I_wake_all_cond (I_cond *);
#endif/*I_THREADS_H*/
#endif/*HAVE_THREADS*/

View File

@ -898,6 +898,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp
newodds = 0;
else
POWERITEMODDS(newodds);
break;
case KITEM_HYUDORO:
if ((hyubgone > 0) || COOLDOWNONSTART)
newodds = 0;
@ -1061,6 +1062,10 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
bestbumper = players[i].kartstuff[k_bumper];
}
// No forced SPB in 1v1s, it has to be randomly rolled
if (pingame <= 2)
dontforcespb = true;
// This makes the roulette produce the random noises.
if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player) && !demo.freecam)
{
@ -3312,7 +3317,8 @@ void K_PuntMine(mobj_t *thismine, mobj_t *punter)
if (!thismine || P_MobjWasRemoved(thismine))
return;
if (thismine->type == MT_SSMINE_SHIELD) // Create a new mine
//This guarantees you hit a mine being dragged
if (thismine->type == MT_SSMINE_SHIELD) // Create a new mine, and clean up the old one
{
mine = P_SpawnMobj(thismine->x, thismine->y, thismine->z, MT_SSMINE);
P_SetTarget(&mine->target, thismine->target);
@ -3320,7 +3326,19 @@ void K_PuntMine(mobj_t *thismine, mobj_t *punter)
mine->flags2 = thismine->flags2;
mine->floorz = thismine->floorz;
mine->ceilingz = thismine->ceilingz;
//Since we aren't using P_KillMobj, we need to clean up the hnext reference
{
P_SetTarget(&thismine->target->hnext, NULL); //target is the player who owns the mine
thismine->target->player->kartstuff[k_bananadrag] = 0;
thismine->target->player->kartstuff[k_itemheld] = 0;
if (--thismine->target->player->kartstuff[k_itemamount] <= 0)
thismine->target->player->kartstuff[k_itemtype] = KITEM_NONE;
}
P_RemoveMobj(thismine);
}
else
mine = thismine;
@ -3870,6 +3888,62 @@ void K_DropItems(player_t *player)
K_StripItems(player);
}
void K_DropRocketSneaker(player_t *player)
{
mobj_t *shoe = player->mo;
fixed_t flingangle;
boolean leftshoe = true; //left shoe is first
if (!(player->mo && !P_MobjWasRemoved(player->mo) && player->mo->hnext && !P_MobjWasRemoved(player->mo->hnext)))
return;
while ((shoe = shoe->hnext) && !P_MobjWasRemoved(shoe))
{
if (shoe->type != MT_ROCKETSNEAKER)
return; //woah, not a rocketsneaker, bail! safeguard in case this gets used when you're holding non-rocketsneakers
shoe->flags2 &= ~MF2_DONTDRAW;
shoe->flags &= ~MF_NOGRAVITY;
shoe->angle += ANGLE_45;
if (shoe->eflags & MFE_VERTICALFLIP)
shoe->z -= shoe->height;
else
shoe->z += shoe->height;
//left shoe goes off tot eh left, right shoe off to the right
if (leftshoe)
flingangle = -(ANG60);
else
flingangle = ANG60;
S_StartSound(shoe, shoe->info->deathsound);
P_SetObjectMomZ(shoe, 8*FRACUNIT, false);
P_InstaThrust(shoe, R_PointToAngle2(shoe->target->x, shoe->target->y, shoe->x, shoe->y)+flingangle, 16*FRACUNIT);
shoe->momx += shoe->target->momx;
shoe->momy += shoe->target->momy;
shoe->momz += shoe->target->momz;
shoe->extravalue2 = 1;
leftshoe = false;
}
P_SetTarget(&player->mo->hnext, NULL);
player->kartstuff[k_rocketsneakertimer] = 0;
}
void K_DropKitchenSink(player_t *player)
{
if (!(player->mo && !P_MobjWasRemoved(player->mo) && player->mo->hnext && !P_MobjWasRemoved(player->mo->hnext)))
return;
if (player->mo->hnext->type != MT_SINK_SHIELD)
return; //so we can just call this function regardless of what is being held
P_KillMobj(player->mo->hnext, NULL, NULL);
P_SetTarget(&player->mo->hnext, NULL);
}
// When an item in the hnext chain dies.
void K_RepairOrbitChain(mobj_t *orbit)
{
@ -4490,6 +4564,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
fast->momx = 3*player->mo->momx/4;
fast->momy = 3*player->mo->momy/4;
fast->momz = 3*player->mo->momz/4;
P_SetTarget(&fast->target, player->mo); // easier lua access
K_MatchGenericExtraFlags(fast, player->mo);
}
@ -5195,12 +5270,12 @@ void K_KartUpdatePosition(player_t *player)
//
void K_StripItems(player_t *player)
{
K_DropRocketSneaker(player);
K_DropKitchenSink(player);
player->kartstuff[k_itemtype] = KITEM_NONE;
player->kartstuff[k_itemamount] = 0;
player->kartstuff[k_itemheld] = 0;
player->kartstuff[k_rocketsneakertimer] = 0;
if (!player->kartstuff[k_itemroulette] || player->kartstuff[k_roulettetype] != 2)
{
player->kartstuff[k_itemroulette] = 0;
@ -8634,7 +8709,7 @@ void K_drawKartFreePlay(UINT32 flashtime)
return;
V_DrawKartString((BASEVIDWIDTH - (LAPS_X+1)) - (12*9), // mirror the laps thingy
LAPS_Y+3, V_SNAPTOBOTTOM|V_SNAPTORIGHT, "FREE PLAY");
LAPS_Y+3, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, "FREE PLAY");
}
static void K_drawDistributionDebugger(void)

View File

@ -11,7 +11,7 @@
#define KART_FULLTURN 800
UINT8 colortranslations[MAXTRANSLATIONS][16];
extern UINT8 colortranslations[MAXTRANSLATIONS][16];
extern const char *KartColor_Names[MAXSKINCOLORS];
extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2];
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor);
@ -55,6 +55,8 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue);
INT32 K_GetKartDriftSparkValue(player_t *player);
void K_KartUpdatePosition(player_t *player);
void K_DropItems(player_t *player);
void K_DropRocketSneaker(player_t *player);
void K_DropKitchenSink(player_t *player);
void K_StripItems(player_t *player);
void K_StripOther(player_t *player);
void K_MomentumToFacing(player_t *player);

View File

@ -17,6 +17,7 @@
#include "d_player.h"
#include "g_game.h"
#include "p_local.h"
#include "d_clisrv.h"
#include "lua_script.h"
#include "lua_libs.h"
@ -118,7 +119,7 @@ static int lib_iterateDisplayplayers(lua_State *L)
for (i++; i < MAXSPLITSCREENPLAYERS; i++)
{
if (!playeringame[displayplayers[i]] || i > splitscreen)
if (i > splitscreen || !playeringame[displayplayers[i]])
return 0; // Stop! There are no more players for us to go through. There will never be a player gap in displayplayers.
if (!players[displayplayers[i]].mo)
@ -139,6 +140,8 @@ static int lib_getDisplayplayers(lua_State *L)
lua_Integer i = luaL_checkinteger(L, 2);
if (i < 0 || i >= MAXSPLITSCREENPLAYERS)
return luaL_error(L, "displayplayers[] index %d out of range (0 - %d)", i, MAXSPLITSCREENPLAYERS-1);
if (i > splitscreen)
return 0;
if (!playeringame[displayplayers[i]])
return 0;
if (!players[displayplayers[i]].mo)
@ -385,6 +388,8 @@ static int player_get(lua_State *L)
else if (fastcmp(field,"fovadd"))
lua_pushfixed(L, plr->fovadd);
#endif
else if (fastcmp(field,"ping"))
lua_pushinteger(L, playerpingtable[( plr - players )]);
else {
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));

View File

@ -16,6 +16,7 @@
#include "doomdef.h"
#include "command.h"
#include "m_argv.h"
#include "m_misc.h"
/** \brief number of arg
*/
@ -166,7 +167,7 @@ void M_FindResponseFile(void)
if (!file)
I_Error("No more free memory for the response file");
if (fread(file, size, 1, handle) != 1)
I_Error("Couldn't read response file because %s", strerror(ferror(handle)));
I_Error("Couldn't read response file because %s", M_FileError(handle));
fclose(handle);
// keep all the command line arguments following @responsefile

View File

@ -32,6 +32,7 @@
#include "sounds.h"
#include "s_sound.h"
#include "i_system.h"
#include "i_threads.h"
// Addfile
#include "filesrch.h"
@ -118,6 +119,12 @@ typedef enum
NUM_QUITMESSAGES
} text_enum;
#ifdef HAVE_THREADS
I_mutex m_menu_mutex;
#endif
M_waiting_mode_t m_waiting_mode = M_NOT_WAITING;
const char *quitmsg[NUM_QUITMESSAGES];
// Stuff for customizing the player select screen Tails 09-22-2003
@ -1039,7 +1046,7 @@ enum
FIRSTSERVERLINE
};
static menuitem_t MP_RoomMenu[] =
menuitem_t MP_RoomMenu[] =
{
{IT_STRING | IT_CALL, NULL, "<Offline Mode>", M_ChooseRoom, 9},
{IT_DISABLED, NULL, "", M_ChooseRoom, 18},
@ -2896,7 +2903,6 @@ boolean M_Responder(event_t *ev)
//make sure the game doesn't still think we're in a netgame.
if (!Playing() && netgame && multiplayer)
{
MSCloseUDPSocket(); // Clean up so we can re-open the connection later.
netgame = false;
multiplayer = false;
}
@ -3304,6 +3310,30 @@ void M_SetupNextMenu(menu_t *menudef)
{
INT16 i;
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef)
{
I_lock_mutex(&ms_QueryId_mutex);
{
ms_QueryId++;
}
I_unlock_mutex(ms_QueryId_mutex);
}
if (currentMenu == &MP_ConnectDef)
{
I_lock_mutex(&ms_ServerList_mutex);
{
if (ms_ServerList)
{
free(ms_ServerList);
ms_ServerList = NULL;
}
}
I_unlock_mutex(ms_ServerList_mutex);
}
#endif/*HAVE_THREADS*/
if (currentMenu->quitroutine)
{
// If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH
@ -3361,6 +3391,19 @@ void M_Ticker(void)
if (--vidm_testingmode == 0)
setmodeneeded = vidm_previousmode + 1;
}
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
I_lock_mutex(&ms_ServerList_mutex);
{
if (ms_ServerList)
{
CL_QueryServerList(ms_ServerList);
free(ms_ServerList);
ms_ServerList = NULL;
}
}
I_unlock_mutex(ms_ServerList_mutex);
#endif
}
//
@ -4833,7 +4876,7 @@ static boolean M_AddonsRefresh(void)
else if (majormods && !prevmajormods)
{
S_StartSound(NULL, sfx_s221);
message = va("%c%s\x80\nGameplay has now been modified.\nIf you wish to play Record Attack mode, restart the game to clear existing addons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
message = va("%c%s\x80\nYou've loaded a gameplay-modifying addon.\n\nRecord Attack has been disabled, but you\ncan still play alone in local Multiplayer.\n\nIf you wish to play Record Attack mode, restart the game to disable loaded addons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
prevmajormods = majormods;
}
@ -8327,22 +8370,65 @@ static INT32 menuRoomIndex = 0;
static void M_DrawRoomMenu(void)
{
static int frame = -12;
int dot_frame;
char text[4];
const char *rmotd;
const char *waiting_message;
int dots;
if (m_waiting_mode)
{
dot_frame = frame / 4;
dots = dot_frame + 3;
strcpy(text, " ");
if (dots > 0)
{
if (dot_frame < 0)
dot_frame = 0;
strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame));
}
if (++frame == 12)
frame = -12;
currentMenu->menuitems[0].text = text;
}
// use generic drawer for cursor, items and title
M_DrawGenericMenu();
V_DrawString(currentMenu->x - 16, currentMenu->y, highlightflags, M_GetText("Select a room"));
M_DrawTextBox(144, 24, 20, 20);
if (m_waiting_mode == M_NOT_WAITING)
{
M_DrawTextBox(144, 24, 20, 20);
if (itemOn == 0)
rmotd = M_GetText("Don't connect to the Master Server.");
else
rmotd = room_list[itemOn-1].motd;
if (itemOn == 0)
rmotd = M_GetText("Don't connect to the Master Server.");
else
rmotd = room_list[itemOn-1].motd;
rmotd = V_WordWrap(0, 20*8, 0, rmotd);
V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd);
rmotd = V_WordWrap(0, 20*8, 0, rmotd);
V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd);
}
if (m_waiting_mode)
{
// Display a little "please wait" message.
M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3);
if (m_waiting_mode == M_WAITING_VERSION)
waiting_message = "Checking for updates...";
else
waiting_message = "Fetching room info...";
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, waiting_message);
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait.");
}
}
static void M_DrawConnectMenu(void)
@ -8416,6 +8502,14 @@ static void M_DrawConnectMenu(void)
localservercount = serverlistcount;
M_DrawGenericMenu();
if (m_waiting_mode)
{
// Display a little "please wait" message.
M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Searching for servers...");
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait.");
}
}
static boolean M_CancelConnect(void)
@ -8497,10 +8591,10 @@ void M_SortServerList(void)
#ifndef NONET
#ifdef UPDATE_ALERT
static boolean M_CheckMODVersion(void)
static boolean M_CheckMODVersion(int id)
{
char updatestring[500];
const char *updatecheck = GetMODVersion();
const char *updatecheck = GetMODVersion(id);
if(updatecheck)
{
sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck);
@ -8509,7 +8603,64 @@ static boolean M_CheckMODVersion(void)
} else
return true;
}
#endif/*UPDATE_ALERT*/
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
static void
Check_new_version_thread (int *id)
{
int hosting;
int okay;
okay = 0;
#ifdef UPDATE_ALERT
if (M_CheckMODVersion(*id))
#endif
{
I_lock_mutex(&ms_QueryId_mutex);
{
okay = ( *id == ms_QueryId );
}
I_unlock_mutex(ms_QueryId_mutex);
if (okay)
{
I_lock_mutex(&m_menu_mutex);
{
m_waiting_mode = M_WAITING_ROOMS;
hosting = ( currentMenu->prevMenu == &MP_ServerDef );
}
I_unlock_mutex(m_menu_mutex);
GetRoomsList(hosting, *id);
}
}
else
{
I_lock_mutex(&ms_QueryId_mutex);
{
okay = ( *id == ms_QueryId );
}
I_unlock_mutex(ms_QueryId_mutex);
}
if (okay)
{
I_lock_mutex(&m_menu_mutex);
{
if (m_waiting_mode)
{
m_waiting_mode = M_NOT_WAITING;
MP_RoomMenu[0].text = "<Offline Mode>";
}
}
I_unlock_mutex(m_menu_mutex);
}
free(id);
}
#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/
static void M_ConnectMenu(INT32 choice)
{
@ -8538,18 +8689,21 @@ static void M_ConnectMenuModChecks(INT32 choice)
if (modifiedgame)
{
M_StartMessage(M_GetText("Addons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing addons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
M_StartMessage(M_GetText("You have addons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\nSRB2Kart will automatically add\neverything you need when you join.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
return;
}
M_ConnectMenu(-1);
}
static UINT32 roomIds[NUM_LIST_ROOMS];
UINT32 roomIds[NUM_LIST_ROOMS];
static void M_RoomMenu(INT32 choice)
{
INT32 i;
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
int *id;
#endif
(void)choice;
@ -8562,34 +8716,54 @@ static void M_RoomMenu(INT32 choice)
if (rendermode == render_soft)
I_FinishUpdate(); // page flip or blit buffer
if (GetRoomsList(currentMenu == &MP_ServerDef) < 0)
return;
#ifdef UPDATE_ALERT
if (!M_CheckMODVersion())
return;
#endif
for (i = 1; i < NUM_LIST_ROOMS+1; ++i)
MP_RoomMenu[i].status = IT_DISABLED;
memset(roomIds, 0, sizeof(roomIds));
for (i = 0; room_list[i].header.buffer[0]; i++)
{
if(*room_list[i].name != '\0')
{
MP_RoomMenu[i+1].text = room_list[i].name;
roomIds[i] = room_list[i].id;
MP_RoomMenu[i+1].status = IT_STRING|IT_CALL;
}
}
MP_RoomDef.prevMenu = currentMenu;
M_SetupNextMenu(&MP_RoomDef);
#ifdef MASTERSERVER
#ifdef HAVE_THREADS
#ifdef UPDATE_ALERT
m_waiting_mode = M_WAITING_VERSION;
#else/*UPDATE_ALERT*/
m_waiting_mode = M_WAITING_ROOMS;
#endif/*UPDATE_ALERT*/
MP_RoomMenu[0].text = "";
id = malloc(sizeof *id);
I_lock_mutex(&ms_QueryId_mutex);
{
*id = ms_QueryId;
}
I_unlock_mutex(ms_QueryId_mutex);
I_spawn_thread("check-new-version",
(I_thread_fn)Check_new_version_thread, id);
#else/*HAVE_THREADS*/
#ifdef UPDATE_ALERT
if (M_CheckMODVersion(0))
#endif/*UPDATE_ALERT*/
{
GetRoomsList(currentMenu->prevMenu == &MP_ServerDef, 0);
}
#endif/*HAVE_THREADS*/
#endif/*MASTERSERVER*/
}
static void M_ChooseRoom(INT32 choice)
{
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
I_lock_mutex(&ms_QueryId_mutex);
{
ms_QueryId++;
}
I_unlock_mutex(ms_QueryId_mutex);
#endif
if (choice == 0)
ms_RoomId = -1;
else

View File

@ -17,6 +17,8 @@
#include "d_event.h"
#include "command.h"
#include "i_threads.h"
#include "mserv.h"
#include "r_things.h" // for SKINNAMESIZE
//
@ -72,6 +74,18 @@ typedef enum
} menumessagetype_t;
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype);
typedef enum
{
M_NOT_WAITING,
M_WAITING_VERSION,
M_WAITING_ROOMS,
M_WAITING_SERVERS,
}
M_waiting_mode_t;
extern M_waiting_mode_t m_waiting_mode;
// Called by linux_x/i_video_xshm.c
void M_QuitResponse(INT32 ch);
@ -161,6 +175,9 @@ typedef struct menuitem_s
extern menuitem_t PlayerMenu[MAXSKINS];
extern menuitem_t MP_RoomMenu[];
extern UINT32 roomIds[NUM_LIST_ROOMS];
typedef struct menu_s
{
const char *menutitlepic;
@ -176,6 +193,10 @@ typedef struct menu_s
void M_SetupNextMenu(menu_t *menudef);
void M_ClearMenus(boolean callexitmenufunc);
#ifdef HAVE_THREADS
extern I_mutex m_menu_mutex;
#endif
extern menu_t *currentMenu;
extern menu_t MainDef;

View File

@ -23,6 +23,8 @@
#include <unistd.h>
#endif
#include <errno.h>
// Extended map support.
#include <ctype.h>
@ -505,7 +507,7 @@ void M_FirstLoadConfig(void)
CV_InitFilterVar();
// load config, make sure those commands doesnt require the screen...
COM_BufInsertText(va("exec \"%s\"\n", configfile));
COM_BufInsertText(va("exec \"%s\" -sync\n", configfile));
// no COM_BufExecute() needed; that does it right away
// don't filter anymore vars and don't let this convsvar be changed
@ -2363,3 +2365,13 @@ void M_SetupMemcpy(void)
M_Memcpy = cpu_cpy;
#endif
}
/** Return the appropriate message for a file error or end of file.
*/
const char *M_FileError(FILE *fp)
{
if (ferror(fp))
return strerror(errno);
else
return "end-of-file";
}

View File

@ -100,6 +100,8 @@ void strcatbf(char *s1, const char *s2, const char *s3);
void M_SetupMemcpy(void);
const char *M_FileError(FILE *handle);
// counting bits, for weapon ammo code, usually
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
// Copyright (C) 2020 by James R.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@ -13,7 +14,7 @@
#ifndef _MSERV_H_
#define _MSERV_H_
#define MASTERSERVERS21 // MasterServer v2.1
#include "i_threads.h"
// lowered from 32 due to menu changes
#define NUM_LIST_ROOMS 16
@ -64,33 +65,47 @@ typedef struct
// ================================ GLOBALS ===============================
extern consvar_t cv_masterserver, cv_servername;
extern consvar_t cv_masterserver_update_rate;
extern consvar_t cv_masterserver_timeout;
extern consvar_t cv_masterserver_debug;
extern consvar_t cv_masterserver_token;
// < 0 to not connect (usually -1) (offline mode)
// == 0 to show all rooms, not a valid hosting room
// anything else is whatever room the MS assigns to that number (online mode)
INT16 ms_RoomId;
extern INT16 ms_RoomId;
const char *GetMasterServerPort(void);
const char *GetMasterServerIP(void);
#ifdef HAVE_THREADS
extern int ms_QueryId;
extern I_mutex ms_QueryId_mutex;
void MSOpenUDPSocket(void);
void MSCloseUDPSocket(void);
void SendAskInfoViaMS(INT32 node, tic_t asktime);
extern msg_server_t *ms_ServerList;
extern I_mutex ms_ServerList_mutex;
#endif
void RegisterServer(void);
void UnregisterServer(void);
void MasterClient_Ticker(void);
const msg_server_t *GetShortServersList(INT32 room);
INT32 GetRoomsList(boolean hosting);
msg_server_t *GetShortServersList(INT32 room, int id);
INT32 GetRoomsList(boolean hosting, int id);
#ifdef UPDATE_ALERT
const char *GetMODVersion(void);
char *GetMODVersion(int id);
void GetMODVersion_Console(void);
#endif
extern msg_rooms_t room_list[NUM_LIST_ROOMS+1];
void AddMServCommands(void);
/* HTTP */
void HMS_set_api (char *api);
int HMS_fetch_rooms (int joining, int id);
int HMS_register (void);
int HMS_unlist (void);
int HMS_update (void);
void HMS_list_servers (void);
msg_server_t * HMS_fetch_servers (msg_server_t *list, int room, int id);
int HMS_compare_mod_version (char *buffer, size_t size_of_buffer);
#endif

View File

@ -8517,6 +8517,7 @@ void A_SPBChase(mobj_t *actor)
//fast->momz = (3*actor->momz)/4;
fast->color = SKINCOLOR_RED;
fast->colorized = true;
P_SetTarget(&fast->target, actor); // easier lua access
K_MatchGenericExtraFlags(fast, actor);
}

View File

@ -8312,18 +8312,7 @@ void P_MobjThinker(mobj_t *mobj)
if (!mobj->extravalue2)
{
if (mobj->eflags & MFE_VERTICALFLIP)
mobj->z -= mobj->height;
else
mobj->z += mobj->height;
S_StartSound(mobj, mobj->info->deathsound);
P_SetObjectMomZ(mobj, 8*FRACUNIT, false);
P_InstaThrust(mobj, R_PointToAngle2(mobj->target->x, mobj->target->y, mobj->x, mobj->y)+ANGLE_90, 16*FRACUNIT);
mobj->momx += mobj->target->momx;
mobj->momy += mobj->target->momy;
mobj->momz += mobj->target->momz;
mobj->extravalue2 = 1;
K_DropRocketSneaker(mobj->target->player);
}
else if (P_IsObjectOnGround(mobj))
{

View File

@ -1408,7 +1408,7 @@ static void P_LoadRawSideDefs2(void *data)
UINT16 i;
INT32 num;
size_t j;
UINT32 cr, cg, cb;
RGBA_t color;
for (i = 0; i < numsides; i++)
{
@ -1490,23 +1490,21 @@ static void P_LoadRawSideDefs2(void *data)
// encore mode colormaps!
// do it like software by aproximating a color to a palette index, and then convert it to its encore variant and then back to a color code.
// do this for both the start and fade colormaps.
cr = (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0);
cg = (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8);
cb = (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16);
color.s.red = (HEX2INT(col[1]) << 4) + HEX2INT(col[2]);
color.s.green = (HEX2INT(col[3]) << 4) + HEX2INT(col[4]);
color.s.blue = (HEX2INT(col[5]) << 4) + HEX2INT(col[6]);
#ifdef GLENCORE
if (encoremap)
{
j = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)];
j = encoremap[NearestColor(color.s.red, color.s.green, color.s.blue)];
//CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", j, encoremap[j]); -- moved encoremap upwards for optimisation
cr = pLocalPalette[j].s.red;
cg = pLocalPalette[j].s.green;
cb = pLocalPalette[j].s.blue;
color = pLocalPalette[j]; // note: this sets alpha to 255, we will reset it below
}
#endif
sec->extra_colormap->rgba = cr + cg + cb;
color.s.alpha = 0; // reset/init the alpha, so the addition below will work correctly
sec->extra_colormap->rgba = color.rgba;
// alpha
if (msd->toptexture[7])
@ -1533,23 +1531,21 @@ static void P_LoadRawSideDefs2(void *data)
col = msd->bottomtexture;
// do the exact same thing as above here.
cr = (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0);
cg = (HEX2INT(col[3]) << 12) + (HEX2INT(col[4]) << 8);
cb = (HEX2INT(col[5]) << 20) + (HEX2INT(col[6]) << 16);
color.s.red = (HEX2INT(col[1]) << 4) + HEX2INT(col[2]);
color.s.green = (HEX2INT(col[3]) << 4) + HEX2INT(col[4]);
color.s.blue = (HEX2INT(col[5]) << 4) + HEX2INT(col[6]);
#ifdef GLENCORE
if (encoremap)
{
j = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)];
j = encoremap[NearestColor(color.s.red, color.s.green, color.s.blue)];
//CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", j, encoremap[j]); -- moved encoremap upwards for optimisation
cr = pLocalPalette[j].s.red;
cg = pLocalPalette[j].s.green;
cb = pLocalPalette[j].s.blue;
color = pLocalPalette[j]; // note: this sets alpha to 255, we will reset it below
}
#endif
sec->extra_colormap->fadergba = cr + cg + cb;
color.s.alpha = 0; // reset/init the alpha, so the addition below will work correctly
sec->extra_colormap->fadergba = color.rgba;
// alpha
if (msd->bottomtexture[7])

View File

@ -726,9 +726,9 @@ void P_Ticker(boolean run)
if (exitcountdown > 1)
exitcountdown--;
if (indirectitemcooldown > 1)
if (indirectitemcooldown > 0)
indirectitemcooldown--;
if (hyubgone > 1)
if (hyubgone > 0)
hyubgone--;
if (G_BattleGametype())

View File

@ -7487,13 +7487,14 @@ void P_ResetCamera(player_t *player, camera_t *thiscam)
boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled)
{
static UINT8 lookbackdelay[4] = {0,0,0,0};
static boolean lookbackactive[MAXSPLITSCREENPLAYERS];
static UINT8 lookbackdelay[MAXSPLITSCREENPLAYERS];
UINT8 num;
angle_t angle = 0, focusangle = 0, focusaiming = 0;
fixed_t x, y, z, dist, height, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight;
fixed_t x, y, z, dist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight;
fixed_t pan, xpan, ypan;
INT32 camrotate;
boolean camstill, lookback;
boolean camstill, lookback, lookbackdown;
UINT8 timeover;
mobj_t *mo;
fixed_t f1, f2;
@ -7684,15 +7685,19 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
camstill = true;
else if (lookback || lookbackdelay[num]) // SRB2kart - Camera flipper
{
#define MAXLOOKBACKDELAY 2
camspeed = FRACUNIT;
if (lookback)
{
camrotate += 180;
lookbackdelay[num] = 2;
lookbackdelay[num] = MAXLOOKBACKDELAY;
}
else
lookbackdelay[num]--;
}
lookbackdown = (lookbackdelay[num] == MAXLOOKBACKDELAY) != lookbackactive[num];
lookbackactive[num] = (lookbackdelay[num] == MAXLOOKBACKDELAY);
#undef MAXLOOKBACKDELAY
if (mo->eflags & MFE_VERTICALFLIP)
camheight += thiscam->height;
@ -7735,8 +7740,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
thiscam->angle = angle;
}
height = camheight;
// sets ideal cam pos
dist = camdist;
@ -7745,10 +7748,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
dist += abs(thiscam->momz)/4;
if (player->kartstuff[k_boostcam])
{
dist -= FixedMul(11*dist/16, player->kartstuff[k_boostcam]);
height -= FixedMul(height, player->kartstuff[k_boostcam]);
}
x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist);
y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist);
@ -8070,6 +8070,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
thiscam->aiming = ANGLE_22h;
}
if (lookbackdown)
P_MoveChaseCamera(player, thiscam, false);
return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming);
}

View File

@ -1142,7 +1142,7 @@ void R_SetupFrame(player_t *player, boolean skybox)
aimingangle = player->aiming;
viewangle = viewmobj->angle;
if (/*!demo.playback && */player->playerstate != PST_DEAD)
if (!demo.playback && player->playerstate != PST_DEAD)
{
if (player == &players[consoleplayer])
{

View File

@ -402,7 +402,7 @@ static visplane_t *new_visplane(unsigned hash)
visplane_t *check = freetail;
if (!check)
{
check = calloc(2, sizeof (*check));
check = calloc(1, sizeof (*check));
if (check == NULL) I_Error("%s: Out of memory", "new_visplane"); // FIXME: ugly
}
else

View File

@ -236,7 +236,7 @@ void S_StopSoundByNum(sfxenum_t sfxnum);
#ifdef MUSICSLOT_COMPATIBILITY
// For compatibility with code/scripts relying on older versions
// This is a list of all the "special" slot names and their associated numbers
const char *compat_special_music_slots[16];
extern const char *compat_special_music_slots[16];
#endif
#endif

View File

@ -83,6 +83,11 @@ else
SDL_LDFLAGS+=-lSDL2_mixer
endif
ifndef NOTHREADS
OPTS+=-DHAVE_THREADS
OBJS+=$(OBJDIR)/i_threads.o
endif
ifdef SDL_TTF
OPTS+=-DHAVE_TTF
SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz

View File

@ -249,6 +249,7 @@
<ClInclude Include="..\lzf.h" />
<ClInclude Include="..\md5.h" />
<ClInclude Include="..\mserv.h" />
<ClInclude Include="..\http-mserv.h" />
<ClInclude Include="..\m_aatree.h" />
<ClInclude Include="..\m_anigif.h" />
<ClInclude Include="..\m_argv.h" />
@ -399,6 +400,7 @@
<ClCompile Include="..\lzf.c" />
<ClCompile Include="..\md5.c" />
<ClCompile Include="..\mserv.c" />
<ClCompile Include="..\http-mserv.c" />
<ClCompile Include="..\m_aatree.c" />
<ClCompile Include="..\m_anigif.c" />
<ClCompile Include="..\m_argv.c" />

View File

@ -291,6 +291,9 @@
<ClInclude Include="..\mserv.h">
<Filter>I_Interface</Filter>
</ClInclude>
<ClInclude Include="..\http-mserv.h">
<Filter>I_Interface</Filter>
</ClInclude>
<ClInclude Include="..\lua_hook.h">
<Filter>LUA</Filter>
</ClInclude>
@ -663,6 +666,9 @@
<ClCompile Include="..\mserv.c">
<Filter>I_Interface</Filter>
</ClCompile>
<ClCompile Include="..\http-mserv.c">
<Filter>I_Interface</Filter>
</ClCompile>
<ClCompile Include="..\lua_baselib.c">
<Filter>LUA</Filter>
</ClCompile>

View File

@ -2782,6 +2782,50 @@
RelativePath="..\mserv.h"
>
</File>
<File
RelativePath="..\http-mserv.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\http-mserv.h"
>
</File>
</Filter>
<Filter
Name="M_Misc"

View File

@ -168,6 +168,7 @@ static char returnWadPath[256];
#include "../i_video.h"
#include "../i_sound.h"
#include "../i_system.h"
#include "../i_threads.h"
#include "../screen.h" //vid.WndParent
#include "../d_net.h"
#include "../g_game.h"
@ -3134,6 +3135,10 @@ INT32 I_StartupSystem(void)
SDL_version SDLlinked;
SDL_VERSION(&SDLcompiled)
SDL_GetVersion(&SDLlinked);
#ifdef HAVE_THREADS
I_start_threads();
I_AddExitFunc(I_stop_threads);
#endif
I_StartupConsole();
#ifdef NEWSIGNALHANDLER
I_Fork();
@ -3612,10 +3617,14 @@ static void pathonly(char *s)
static const char *searchWad(const char *searchDir)
{
static char tempsw[256] = "";
filequery_t fsquery;
filestatus_t fstemp;
fsquery.filename = tempsw;
strcpy(tempsw, WADKEYWORD1);
fstemp = filesearch(tempsw,searchDir,NULL,true,20);
fsquery.status = FS_NOTFOUND;
fstemp = filesearch(1,&fsquery,searchDir,false,true,20,NULL);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);
@ -3623,7 +3632,7 @@ static const char *searchWad(const char *searchDir)
}
strcpy(tempsw, WADKEYWORD2);
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
fstemp = filesearch(1, &fsquery, searchDir, false, true, 20, NULL);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);

396
src/sdl/i_threads.c Normal file
View File

@ -0,0 +1,396 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file i_threads.c
/// \brief Multithreading abstraction
#include "../doomdef.h"
#include "../i_threads.h"
#include <SDL.h>
typedef void * (*Create_fn)(void);
struct Link;
struct Thread;
typedef struct Link * Link;
typedef struct Thread * Thread;
struct Link
{
void * data;
Link next;
Link prev;
};
struct Thread
{
I_thread_fn entry;
void * userdata;
SDL_Thread * thread;
};
static Link i_thread_pool;
static Link i_mutex_pool;
static Link i_cond_pool;
static I_mutex i_thread_pool_mutex;
static I_mutex i_mutex_pool_mutex;
static I_mutex i_cond_pool_mutex;
static SDL_atomic_t i_threads_running = {1};
static SDL_threadID i_main_thread_id;
static Link
Insert_link (
Link * head,
Link link
){
link->prev = NULL;
link->next = (*head);
if ((*head))
(*head)->prev = link;
(*head) = link;
return link;
}
static void
Free_link (
Link * head,
Link link
){
if (link->prev)
link->prev->next = link->next;
else
(*head) = link->next;
if (link->next)
link->next->prev = link->prev;
free(link->data);
free(link);
}
static Link
New_link (void *data)
{
Link link;
link = malloc(sizeof *link);
if (! link)
abort();
link->data = data;
return link;
}
static void *
Identity (
Link * pool_anchor,
I_mutex pool_mutex,
void ** anchor,
Create_fn create_fn
){
void * id;
id = SDL_AtomicGetPtr(anchor);
if (! id)
{
I_lock_mutex(&pool_mutex);
{
id = SDL_AtomicGetPtr(anchor);
if (! id)
{
id = (*create_fn)();
if (! id)
abort();
Insert_link(pool_anchor, New_link(id));
SDL_AtomicSetPtr(anchor, id);
}
}
I_unlock_mutex(pool_mutex);
}
return id;
}
static int
Worker (
Link link
){
Thread th;
th = link->data;
(*th->entry)(th->userdata);
if (SDL_AtomicGet(&i_threads_running))
{
I_lock_mutex(&i_thread_pool_mutex);
{
if (SDL_AtomicGet(&i_threads_running))
{
SDL_DetachThread(th->thread);
Free_link(&i_thread_pool, link);
}
}
I_unlock_mutex(i_thread_pool_mutex);
}
return 0;
}
void
I_spawn_thread (
const char * name,
I_thread_fn entry,
void * userdata
){
Link link;
Thread th;
th = malloc(sizeof *th);
if (! th)
abort();/* this is pretty GNU of me */
th->entry = entry;
th->userdata = userdata;
I_lock_mutex(&i_thread_pool_mutex);
{
link = Insert_link(&i_thread_pool, New_link(th));
if (SDL_AtomicGet(&i_threads_running))
{
th->thread = SDL_CreateThread(
(SDL_ThreadFunction)Worker,
name,
link
);
if (! th->thread)
abort();
}
}
I_unlock_mutex(i_thread_pool_mutex);
}
int
I_thread_is_stopped (void)
{
return ( ! SDL_AtomicGet(&i_threads_running) );
}
int
I_on_main_thread (void)
{
return ( SDL_ThreadID() == i_main_thread_id );
}
void
I_start_threads (void)
{
i_thread_pool_mutex = SDL_CreateMutex();
i_mutex_pool_mutex = SDL_CreateMutex();
i_cond_pool_mutex = SDL_CreateMutex();
if (!(
i_thread_pool_mutex &&
i_mutex_pool_mutex &&
i_cond_pool_mutex
)){
abort();
}
i_main_thread_id = SDL_ThreadID();
}
void
I_stop_threads (void)
{
Link link;
Link next;
Thread th;
SDL_mutex * mutex;
SDL_cond * cond;
if (i_threads_running.value)
{
/* rely on the good will of thread-san */
SDL_AtomicSet(&i_threads_running, 0);
I_lock_mutex(&i_thread_pool_mutex);
{
for (
link = i_thread_pool;
link;
link = next
){
next = link->next;
th = link->data;
SDL_WaitThread(th->thread, NULL);
free(th);
free(link);
}
}
I_unlock_mutex(i_thread_pool_mutex);
for (
link = i_mutex_pool;
link;
link = next
){
next = link->next;
mutex = link->data;
SDL_DestroyMutex(mutex);
free(link);
}
for (
link = i_cond_pool;
link;
link = next
){
next = link->next;
cond = link->data;
SDL_DestroyCond(cond);
free(link);
}
SDL_DestroyMutex(i_thread_pool_mutex);
SDL_DestroyMutex(i_mutex_pool_mutex);
SDL_DestroyMutex(i_cond_pool_mutex);
}
}
void
I_lock_mutex (
I_mutex * anchor
){
SDL_mutex * mutex;
if (! i_threads_running.value)
return;
if (anchor == NULL)
return;
mutex = Identity(
&i_mutex_pool,
i_mutex_pool_mutex,
anchor,
(Create_fn)SDL_CreateMutex
);
if (SDL_LockMutex(mutex) == -1)
abort();
}
void
I_unlock_mutex (
I_mutex id
){
if (! i_threads_running.value)
return;
if (id == NULL)
return;
if (SDL_UnlockMutex(id) == -1)
abort();
}
void
I_hold_cond (
I_cond * cond_anchor,
I_mutex mutex_id
){
SDL_cond * cond;
if (! i_threads_running.value)
return;
if (cond_anchor == NULL || mutex_id == NULL)
return;
cond = Identity(
&i_cond_pool,
i_cond_pool_mutex,
cond_anchor,
(Create_fn)SDL_CreateCond
);
if (SDL_CondWait(cond, mutex_id) == -1)
abort();
}
void
I_wake_one_cond (
I_cond * anchor
){
SDL_cond * cond;
if (! i_threads_running.value)
return;
if (anchor == NULL)
return;
cond = Identity(
&i_cond_pool,
i_cond_pool_mutex,
anchor,
(Create_fn)SDL_CreateCond
);
if (SDL_CondSignal(cond) == -1)
abort();
}
void
I_wake_all_cond (
I_cond * anchor
){
SDL_cond * cond;
if (! i_threads_running.value)
return;
if (anchor == NULL)
return;
cond = Identity(
&i_cond_pool,
i_cond_pool_mutex,
anchor,
(Create_fn)SDL_CreateCond
);
if (SDL_CondBroadcast(cond) == -1)
abort();
}

View File

@ -110,6 +110,27 @@ static void var_cleanup(void)
internal_volume = 100;
}
static const char* get_zlib_error(int zErr)
{
switch (zErr)
{
case Z_ERRNO:
return "Z_ERRNO";
case Z_STREAM_ERROR:
return "Z_STREAM_ERROR";
case Z_DATA_ERROR:
return "Z_DATA_ERROR";
case Z_MEM_ERROR:
return "Z_MEM_ERROR";
case Z_BUF_ERROR:
return "Z_BUF_ERROR";
case Z_VERSION_ERROR:
return "Z_VERSION_ERROR";
default:
return "unknown error";
}
}
/// ------------------------
/// Audio System
/// ------------------------
@ -371,51 +392,11 @@ void *I_GetSfx(sfxinfo_t *sfx)
}
}
else
{
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg);
(void)inflateEnd(&stream);
}
else // Hold up, zlib's got a problem
{
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg);
Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
#else
return NULL; // No zlib support
@ -945,73 +926,25 @@ boolean I_LoadSong(char *data, size_t len)
// Run GME on new data
if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100))
{
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
gme_start_track(gme, 0);
current_track = 0;
gme_set_equalizer(gme, &eq);
Mix_HookMusic(mix_gme, gme);
Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
return true;
}
}
else
{
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
}
CONS_Alert(CONS_ERROR, "Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg);
(void)inflateEnd(&stream);
}
else // Hold up, zlib's got a problem
{
const char *errorType;
switch (zErr)
{
case Z_ERRNO:
errorType = "Z_ERRNO"; break;
case Z_STREAM_ERROR:
errorType = "Z_STREAM_ERROR"; break;
case Z_DATA_ERROR:
errorType = "Z_DATA_ERROR"; break;
case Z_MEM_ERROR:
errorType = "Z_MEM_ERROR"; break;
case Z_BUF_ERROR:
errorType = "Z_BUF_ERROR"; break;
case Z_VERSION_ERROR:
errorType = "Z_VERSION_ERROR"; break;
default:
errorType = "unknown error";
}
CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
}
CONS_Alert(CONS_ERROR, "Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg);
Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
return false;
#else
CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n");
return true;
return false;
#endif
}
else if (!gme_open_data(data, len, &gme, 44100))
{
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
gme_set_equalizer(gme, &eq);
return true;
}
#endif
rw = SDL_RWFromMem(data, len);
@ -1082,6 +1015,8 @@ boolean I_PlaySong(boolean looping)
#ifdef HAVE_LIBGME
if (gme)
{
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
gme_set_equalizer(gme, &eq);
gme_start_track(gme, 0);
current_track = 0;
Mix_HookMusic(mix_gme, gme);

View File

@ -33,6 +33,7 @@
#endif
#include "../doomdef.h"
#include "../d_main.h"
#ifdef HWRENDER
#include "../hardware/r_opengl/r_opengl.h"
@ -154,11 +155,26 @@ boolean OglSdlSurface(INT32 w, INT32 h)
{
INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value;
static boolean first_init = false;
const char *gllogdir = NULL;
oglflags = 0;
if (!first_init)
{
if (!gllogstream)
{
gllogdir = D_Home();
#ifdef DEBUG_TO_FILE
#ifdef DEFAULTDIR
if (gllogdir)
gllogstream = fopen(va("%s/"DEFAULTDIR"/ogllog.txt",gllogdir), "wt");
else
#endif
gllogstream = fopen("./ogllog.txt", "wt");
#endif
}
gl_version = pglGetString(GL_VERSION);
gl_renderer = pglGetString(GL_RENDERER);
gl_extensions = pglGetString(GL_EXTENSIONS);

View File

@ -1173,7 +1173,10 @@ void I_StartupSound(void)
const char *sdrv_name = NULL;
#endif
#ifndef HAVE_MIXER
midi_disabled = digital_disabled = true;
#ifndef NO_MIDI
midi_disabled =
#endif
digital_disabled = true;
#endif
memset(channels, 0, sizeof (channels)); //Alam: Clean it

View File

@ -1435,7 +1435,7 @@ static boolean LoadSong(void *data, size_t lumplength, size_t selectpos)
if (fwrite(data, lumplength, 1, midfile) == 0)
{
CONS_Printf(M_GetText("Couldn't write music into file %s because %s\n"), tempname, strerror(ferror(midfile)));
CONS_Printf(M_GetText("Couldn't write music into file %s because %s\n"), tempname, M_FileError(midfile));
Z_Free(data);
fclose(midfile);
return false;

View File

@ -1797,10 +1797,12 @@ static void ST_doItemFinderIconsAndSound(void) // SRB2kart - unused.
//
static void ST_overlayDrawer(void)
{
/* SRB2kart doesn't need this stuff
//hu_showscores = auto hide score/time/rings when tab rankings are shown
if (!(hu_showscores && (netgame || multiplayer)))
{
K_drawKartHUD();
/* SRB2kart doesn't need this stuff
if (maptol & TOL_NIGHTS)
ST_drawNiGHTSHUD();
else
@ -1824,8 +1826,8 @@ static void ST_overlayDrawer(void)
)
ST_drawLives();
}
}
*/
}
// GAME OVER pic
/*if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer)))
@ -1845,8 +1847,6 @@ static void ST_overlayDrawer(void)
// Countdown timer for Race Mode
// ...moved to k_kart.c so we can take advantage of the LAPS_Y value
K_drawKartHUD();
/* SRB2kart doesn't need this stuff, I think
// If you are in overtime, put a big honkin' flashin' message on the screen.
if (G_BattleGametype() && cv_overtime.value

View File

@ -150,7 +150,10 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
{
FILE *handle;
strncpy(filenamebuf, *filename, MAX_WADPATH);
if (filenamebuf != *filename) {
// avoid overlap
strncpy(filenamebuf, *filename, MAX_WADPATH);
}
filenamebuf[MAX_WADPATH - 1] = '\0';
*filename = filenamebuf;
@ -366,7 +369,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
// read the header
if (fread(&header, 1, sizeof header, handle) < sizeof header)
{
CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header because %s\n"), strerror(ferror(handle)));
CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header because %s\n"), M_FileError(handle));
return NULL;
}
@ -389,7 +392,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
if (fseek(handle, header.infotableofs, SEEK_SET) == -1
|| fread(fileinfo, 1, i, handle) < i)
{
CONS_Alert(CONS_ERROR, M_GetText("Corrupt wadfile directory (%s)\n"), strerror(ferror(handle)));
CONS_Alert(CONS_ERROR, M_GetText("Corrupt wadfile directory (%s)\n"), M_FileError(handle));
free(fileinfov);
return NULL;
}
@ -410,7 +413,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
handle) < sizeof realsize)
{
I_Error("corrupt compressed file: %s; maybe %s", /// \todo Avoid the bailout?
filename, strerror(ferror(handle)));
filename, M_FileError(handle));
}
realsize = LONG(realsize);
if (realsize != 0)
@ -548,7 +551,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
fseek(handle, -4, SEEK_CUR);
if (fread(&zend, 1, sizeof zend, handle) < sizeof zend)
{
CONS_Alert(CONS_ERROR, "Corrupt central directory (%s)\n", strerror(ferror(handle)));
CONS_Alert(CONS_ERROR, "Corrupt central directory (%s)\n", M_FileError(handle));
return NULL;
}
numlumps = zend.entries;
@ -565,7 +568,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
if (fread(zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t))
{
CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", strerror(ferror(handle)));
CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", M_FileError(handle));
Z_Free(lumpinfo);
free(zentry);
return NULL;
@ -585,7 +588,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
fullname = malloc(zentry->namelen + 1);
if (fgets(fullname, zentry->namelen + 1, handle) != fullname)
{
CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", strerror(ferror(handle)));
CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", M_FileError(handle));
Z_Free(lumpinfo);
free(zentry);
free(fullname);
@ -844,16 +847,45 @@ void W_UnloadWadFile(UINT16 num)
*/
INT32 W_InitMultipleFiles(char **filenames, boolean addons)
{
char filenamebufs[MAX_WADFILES][MAX_WADPATH];
filequery_t q[MAX_WADFILES];
int n = 0;
int i;
INT32 rc = 1;
// will be realloced as lumps are added
for (; *filenames; filenames++)
{
if (addons && !W_VerifyNMUSlumps(*filenames))
if (FIL_FileOK(*filenames))
{
q[n].status = FS_FOUND;
q[n].filename = *filenames;
}
else
{
strcpy(filenamebufs[n], *filenames);
q[n].filename = filenamebufs[n];
}
n++;
}
findmultiplefiles(n, q, false, true, NULL);
for (i = 0; i < n; ++i)
{
if (q[i].status != FS_FOUND)
{
CONS_Alert(CONS_ERROR, M_GetText("File %s not found.\n"), q[i].filename);
continue;
}
if (addons && !W_VerifyNMUSlumps(q[i].filename))
G_SetGameModified(true, false);
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
rc &= (W_InitFile(*filenames) != INT16_MAX) ? 1 : 0;
rc &= (W_InitFile(q[i].filename) != INT16_MAX) ? 1 : 0;
}
if (!numwadfiles)
@ -1319,8 +1351,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
{
size = 0;
zerr(zErr);
(void)inflateEnd(&strm);
}
(void)inflateEnd(&strm);
}
else
{

View File

@ -28,6 +28,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "i_system.h" // I_GetFreeMem
#include "i_threads.h"
#include "i_video.h" // rendermode
#include "z_zone.h"
#include "m_misc.h" // M_Memcpy
@ -49,6 +50,16 @@ static boolean Z_calloc = false;
//#define ZDEBUG2
#endif
#ifdef HAVE_THREADS
static I_mutex z_mutex;
# define Lock_state() I_lock_mutex(&z_mutex)
# define Unlock_state() I_unlock_mutex(z_mutex)
#else/*HAVE_THREADS*/
# define Lock_state()
# define Unlock_state()
#endif/*HAVE_THREADS*/
struct memblock_s;
typedef struct
@ -172,6 +183,8 @@ void Z_Free(void *ptr)
CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line);
#endif
Lock_state();
#ifdef ZDEBUG
block = Ptr2Memblock2(ptr, "Z_Free", file, line);
#else
@ -204,6 +217,8 @@ void Z_Free(void *ptr)
#ifdef VALGRIND_DESTROY_MEMPOOL
VALGRIND_DESTROY_MEMPOOL(block);
#endif
Unlock_state();
}
// malloc() that doesn't accept failure.
@ -276,6 +291,8 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
VALGRIND_MEMPOOL_ALLOC(block, hdr, size + sizeof *hdr);
#endif
Lock_state();
block->next = head.next;
block->prev = &head;
head.next = block;
@ -304,7 +321,10 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
block->user = user;
*(void **)user = given;
}
else if (tag >= PU_PURGELEVEL)
Unlock_state();
if (user == NULL && tag >= PU_PURGELEVEL)
I_Error("Z_Malloc: attempted to allocate purgable block "
"(size %s) with no user", sizeu1(size));
@ -401,6 +421,8 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
{
memblock_t *block, *next;
Lock_state();
Z_CheckHeap(420);
for (block = head.next; block != &head; block = next)
{
@ -409,6 +431,8 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
if (block->tag >= lowtag && block->tag <= hightag)
Z_Free((UINT8 *)block->hdr + sizeof *block->hdr);
}
Unlock_state();
}
//
@ -599,6 +623,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
size_t cnt = 0;
memblock_t *rover;
Lock_state();
for (rover = head.next; rover != &head; rover = rover->next)
{
if (rover->tag < lowtag || rover->tag > hightag)
@ -606,6 +632,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
cnt += rover->size + sizeof *rover;
}
Unlock_state();
return cnt;
}
@ -618,6 +646,8 @@ void Command_Memfree_f(void)
{
UINT32 freebytes, totalbytes;
Lock_state();
Z_CheckHeap(-1);
CONS_Printf("\x82%s", M_GetText("Memory Info\n"));
CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TagsUsage(0, INT32_MAX)>>10));
@ -644,6 +674,8 @@ void Command_Memfree_f(void)
freebytes = I_GetFreeMem(&totalbytes);
CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10);
CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10);
Unlock_state();
}
#ifdef ZDEBUG
@ -659,12 +691,16 @@ static void Command_Memdump_f(void)
if ((i = COM_CheckParm("-max")))
maxtag = atoi(COM_Argv(i + 1));
Lock_state();
for (block = head.next; block != &head; block = block->next)
if (block->tag >= mintag && block->tag <= maxtag)
{
char *filename = strrchr(block->ownerfile, PATHSEP[0]);
CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline);
}
Unlock_state();
}
#endif