luciensadi / AwakeMUD

The Community Edition fork of the 'Awakened Worlds' Shadowrun 3 MUD codebase.
Other
55 stars 30 forks source link

Various matrix fixes #735

Closed jdevnull closed 2 months ago

jdevnull commented 4 months ago

(snipped) Start here: https://github.com/luciensadi/AwakeMUD/pull/735#issuecomment-2126371998

jdevnull commented 4 months ago

Colus' statement at https://discord.com/channels/564618629467996170/564621949842751508/1217174615449927842 that trap doors should drop you directly into the target node makes sense to me, so here's the code for it.

After https://discord.com/channels/564618629467996170/1216675006164242432, what I'm thinking is to give each host a linked list of entrances (similar to how they each have a linked list of exits), and to populate the lists at the time of load. But I can't seem to find where in the code the hosts are loaded from the database....

luciensadi commented 4 months ago

Game world loading is in db.cpp, with various loaders called from boot_world(). If you follow DB_BOOT_MTX through, you'll eventually hit discrete_load(), which sends you to parse_host(), which is the actual host loading function for individual hosts. In this case though, you'd probably just want to stick your list-building code after the world loads, probably right around the commented-out "Creating Help Indexes" line or even after boot_world() itself is called.

While I won't stop you from adding a linked list of entrances, remember that if that list is full of pointers, you're going to have to update every list every time a host is moved around in memory or an exit is created/deleted/etc. I recommend testing under Valgrind if you're adding something like that since it will have a higher chance of catching mistakes (it regularly catches mine when I do things along those lines since the code is full of spaghetti).

jdevnull commented 3 months ago

In newmatrix.cpp, matrix_update() starts from matrix[1], but db.cpp functions start from matrix[0]. Is matrix[0] an actual host?

luciensadi commented 3 months ago

In newmatrix.cpp, matrix_update() starts from matrix[1], but db.cpp functions start from matrix[0]. Is matrix[0] an actual host?

No. It exists, but it's host vnum 0 which is not used for anything in the game. 1-indexing is teeeeechnically a bug, but it has no game impact and might be a workaround for a crash related to updating a host with a ton of nulled fields, so I'd leave it be.

Edit: Actually, I'd personally fix it and debug locally to guarantee it worked, but again it'd have no in-game impact, so it'd just be me scratching an itch

jdevnull commented 3 months ago

Notes on current PR:

  1. When attempting to logon to a local subsystem that has a trapdoor, the original code immediately sets the host for the system test to the destination host. The end result was that the local subsystem's encryption actually doesn't matter (in addition to the problem that there's no way to decrypt the destination host's access through a backdoor). Current PR will check the local subsystem first for encryption, forwards to the destination host if it's not encrypted, and ignores the destination host's access encryption because these are supposed to be back doors.
  2. Current PR also provides each host with a linked list of entrances, which is reset and re-populated from every hosts' linked list of exits (via collate_host_entrances()) after boot_world() (db.cpp) loads all the matrix hosts, and again whenever host changes are saved to disk (hedit.cpp). These entrance lists are then used to check for decker presence when we want to re-encrypt hosts in matrix_update() (newmatrix.cpp).

Related to that, every time matrix_update() is called (which is every 2 IRL seconds), if time_info.hours == 0, then we check to re-encrypt each and every host that doesn't have a decker in the area. So this means that the re-encryption code is executed 60 times during the hour of midnight. I'm thinking of changing this to something like checking only once (using some kind of flag similar to payreset) but with an interval of every 6 hours, but maybe what's already here should be reviewed and tested first.

luciensadi commented 3 months ago

Thanks for submitting! I'm behind on reviewing PRs, but will try to take a look this week. Is this ready for review or still in progress?

jdevnull commented 3 months ago

Ready!

luciensadi commented 3 months ago

The change here is pretty complex, and I think I have my head around it but am not positive. Did this all work as expected when you tested it?

jdevnull commented 3 months ago

Well, the code chunks seem to do what I want them to do when I tested them separately, but I haven't tested it integrated into the mud. Difficulty is that my only real linux machine at the moment is my work computer, so I'm a bit limited on what I can install on there.

An option might be installing it on the WSL side of my win11 laptop... hmm.

jdevnull commented 2 months ago

Missed some interactions. When attempting to logon to a subsystem, the code only checks the ACCESS subsystem for encryption instead of where the trap door actually is.

jdevnull commented 2 months ago

Alright, revised how I approached handling trap doors, so here's the current summary of what this PR does:

  1. Each host now has a linked list of entrances. If host A has an exit to host B, if host B is A's parent (so that logon LTG/RTG in A sends you to B), or if A has a subsystem trap door that leads to B, then A is an entrance to B (and so is added to B's linked list of entrances). These lists are re-populated on boot and when saving builder matrix changes.
  2. So long as there is no decker in host B or at any of the entrances to B, then B's subsystems are permitted to re-encrypt.
  3. Separated out the matrix updates that should be checked no more than once an hour into matrix_hour_update(). This way we're not checking all the subsystems for re-encryption every 2 seconds during whichever mud hour host sysops are reviewing security. We also no longer need the payreset lock.
  4. System tests against trap doors target the local subsystem instead of the destination host. This allows the scope of the system_test function to remain as it was while making the following fixes: (1) encryption of the local subsystem now needs to be decrypted before using the trap door, and (2) encryption of the destination host's access no longer makes the trap door impenetrable.
  5. Added host alert state decay (active to passive, passive to no alert), sharing the same requirements as for subsystem re-encryption. This is checked every 2 mud hours so that alert decay has a similar timescale as physical mob alert/alarm states.

Tested with a decker in the vicinity of The Cave / Waterfall hosts in Portland. Did NOT test builder actions (since I'm entirely unfamiliar with being a builder).

This should address the following bug reports: https://discord.com/channels/564618629467996170/1208653573676597248 https://discord.com/channels/564618629467996170/1209262641349005363 https://discord.com/channels/564618629467996170/1219900280926240821 https://discord.com/channels/564618629467996170/1218574342565138484 https://discord.com/channels/564618629467996170/1242383821022826498 (and others)

jdevnull commented 2 months ago

And a few more changes:

  1. Corrected calculation of remaining hacking pool when resisting an attack (esp. so that it doesn't look like a cold ASIST is using pool dice).
  2. Running the medic utility can use hacking pool dice (SR3 pg 207).
  3. Only one armor program (the first found) applies to damage resistance.
luciensadi commented 2 months ago

LGTM, thanks for all your hard work here!

luciensadi commented 1 month ago

FYI the linked list of entrances causes invalid memory access when editing an existing host and 'X'ing out. I think it's trying to clear entrances related to the editing struct and failing when it finds none?