valence icon indicating copy to clipboard operation
valence copied to clipboard

Cryptographic chat support

Open guac42 opened this issue 1 year ago • 14 comments

Description

This adds full cryptographic chat support and all vanilla error checking in the form of an optional plugin called SecureChatPlugin. This means that if chat verification fails, clients are kicked with the proper translation keys. Commands remain to be unverified.

Suggestions to organize code are greatly appreciated, as the example is a bit of a mess at the moment.

closes #8

  • Updates chat example to cryptographically verify chat messages.
  • Create a chat type registry (necessary for sending chat messages).
  • Create PlayerSessionData struct (to prevent having 3 different structs representing the same data).
  • Fix the MessageSignature type definition in valence_protocol.
  • Fix the message filter definition in the ChatMessageS2c packet.
  • Rename the field message_count to message_index.

Test Plan

Note: Has been tested with two clients

Steps:

  1. Run the chat example

Things to consider

  • ~~Notchian servers pass the core chat verification logic off to another thread. Should we do this too? Or is this out of the scope of the example?~~
  • Verifying the client's chat mode may seem a little out of scope, but it is important to consider that notchian servers do not verify chats sent by clients with hidden chat modes.
  • ~~Where in the project should yggdrasil_session_pubkey.der be stored? Is it good where it is now?~~

guac42 avatar Mar 24 '23 08:03 guac42

Where in the project should yggdrasil_session_pubkey.der be stored? Is it good where it is now?

That should go in assets/.

rj00a avatar Mar 24 '23 11:03 rj00a

In #302 I've changed the way the registry codec is set up. Once that's finished, I'll push some changes I have stashed for the player list so progress on this PR can be made.

rj00a avatar Mar 30 '23 17:03 rj00a

The new player list was implemented in #317 :) I don't think there are any major blockers now.

rj00a avatar Apr 10 '23 09:04 rj00a

I've just completed a large reorganization of the entire project in #321. Following that, it makes sense to put all things related to chat in an optional valence_chat crate. This includes the chat type registry, packet handlers, and cryptographic verification. If you can complete that we'll be able to get this merged 😃

rj00a avatar Apr 21 '23 06:04 rj00a

I've just completed a large reorganization of the entire project in #321. Following that, it makes sense to put all things related to chat in an optional valence_chat crate. This includes the chat type registry, packet handlers, and cryptographic verification. If you can complete that we'll be able to get this merged smiley

Sounds good! I found a bug right before I went on vacation so I'll get working on fixing it and the merge conflicts :)

guac42 avatar Apr 23 '23 19:04 guac42

  • What would be required to get chat commands verified? I'd like to have this ready for valence_command.

  • Might make sense to add a secure feature to valence_chat (enabled by secure_chat feature in valence) which skips all of the verification and crypto dependencies when not enabled.

I'll look into the chat command verification once I finish the rest of the other changes and I'm working on putting all the verification behind a feature.

guac42 avatar May 08 '23 04:05 guac42

Not sure how this got closed but the PR is up to date now

guac42 avatar Sep 29 '23 23:09 guac42

You should probably remove the command bit as commands are likely getting merged very soon in either #351 or #446.

JackCrumpLeys avatar Oct 01 '23 20:10 JackCrumpLeys

You should probably remove the command bit as commands are likely getting merged very soon in either #351 or #446.

I was thinking of either doing that or waiting until #351 or #446 was merged and implementing verification for commands as well.

guac42 avatar Oct 02 '23 02:10 guac42

You should probably remove the command bit as commands are likely getting merged very soon in either #351 or #446.

I was thinking of either doing that or waiting until #351 or #446 was merged and implementing verification for commands as well.

Just found out that verification for commands is required for all verification otherwise it breaks the signed message chain. I'm working on implementing a barebones verification process for commands until #351 or #446 is merged with the proper process.

guac42 avatar Oct 03 '23 01:10 guac42

Heads up that #446 was merged. Feel free to ask me to explain any part of how the system works if you are unsure. The basics of my approach are explained in both the crate level docs and module level docs of valence_command.

JackCrumpLeys avatar Nov 09 '23 19:11 JackCrumpLeys

It looks like this pull request changed the workspace structure. Please replace assets/depgraph.svg with the following text:

depgraph.svg (Don't forget the trailing newline)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.43.0 (0)
 -->
<!-- Title: %3 Pages: 1 -->
<svg width="1309pt" height="692pt"
 viewBox="0.00 0.00 1309.14 692.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 688)">
<title>%3</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-688 1305.14,-688 1305.14,4 -4,4"/>
<!-- 0 -->
<g id="node1" class="node">
<title>0</title>
<polygon fill="none" stroke="black" points="479.5,-684 384.5,-684 384.5,-648 479.5,-648 479.5,-684"/>
<text text-anchor="middle" x="432" y="-662.3" font-family="Times,serif" font-size="14.00">java_string</text>
</g>
<!-- 1 -->
<g id="node2" class="node">
<title>1</title>
<polygon fill="none" stroke="black" points="1298.5,-468 1125.5,-468 1125.5,-432 1298.5,-432 1298.5,-468"/>
<text text-anchor="middle" x="1212" y="-446.3" font-family="Times,serif" font-size="14.00">valence_advancement</text>
</g>
<!-- 2 -->
<g id="node3" class="node">
<title>2</title>
<polygon fill="none" stroke="black" points="742.5,-396 619.5,-396 619.5,-360 742.5,-360 742.5,-396"/>
<text text-anchor="middle" x="681" y="-374.3" font-family="Times,serif" font-size="14.00">valence_server</text>
</g>
<!-- 1&#45;&gt;2 -->
<g id="edge1" class="edge">
<title>1&#45;&gt;2</title>
<path fill="none" stroke="black" d="M1125.21,-437.56C1021.26,-423.86 849.11,-401.16 752.48,-388.42"/>
<polygon fill="black" stroke="black" points="752.88,-384.95 742.51,-387.11 751.96,-391.89 752.88,-384.95"/>
</g>
<!-- 3 -->
<g id="node4" class="node">
<title>3</title>
<polygon fill="none" stroke="black" points="668.5,-324 549.5,-324 549.5,-288 668.5,-288 668.5,-324"/>
<text text-anchor="middle" x="609" y="-302.3" font-family="Times,serif" font-size="14.00">valence_entity</text>
</g>
<!-- 2&#45;&gt;3 -->
<g id="edge2" class="edge">
<title>2&#45;&gt;3</title>
<path fill="none" stroke="black" d="M663.2,-359.7C654.4,-351.14 643.62,-340.66 634,-331.3"/>
<polygon fill="black" stroke="black" points="636.2,-328.57 626.59,-324.1 631.32,-333.58 636.2,-328.57"/>
</g>
<!-- 12 -->
<g id="node5" class="node">
<title>12</title>
<polygon fill="none" stroke="black" points="821,-324 687,-324 687,-288 821,-288 821,-324"/>
<text text-anchor="middle" x="754" y="-302.3" font-family="Times,serif" font-size="14.00">valence_registry</text>
</g>
<!-- 2&#45;&gt;12 -->
<g id="edge3" class="edge">
<title>2&#45;&gt;12</title>
<path fill="none" stroke="black" d="M699.04,-359.7C708.06,-351.05 719.12,-340.45 728.94,-331.03"/>
<polygon fill="black" stroke="black" points="731.37,-333.55 736.16,-324.1 726.52,-328.5 731.37,-333.55"/>
</g>
<!-- 11 -->
<g id="node6" class="node">
<title>11</title>
<polygon fill="none" stroke="black" points="776,-252 586,-252 586,-216 776,-216 776,-252"/>
<text text-anchor="middle" x="681" y="-230.3" font-family="Times,serif" font-size="14.00">valence_server_common</text>
</g>
<!-- 3&#45;&gt;11 -->
<g id="edge4" class="edge">
<title>3&#45;&gt;11</title>
<path fill="none" stroke="black" d="M626.8,-287.7C635.6,-279.14 646.38,-268.66 656,-259.3"/>
<polygon fill="black" stroke="black" points="658.68,-261.58 663.41,-252.1 653.8,-256.57 658.68,-261.58"/>
</g>
<!-- 12&#45;&gt;11 -->
<g id="edge12" class="edge">
<title>12&#45;&gt;11</title>
<path fill="none" stroke="black" d="M735.96,-287.7C726.94,-279.05 715.88,-268.45 706.06,-259.03"/>
<polygon fill="black" stroke="black" points="708.48,-256.5 698.84,-252.1 703.63,-261.55 708.48,-256.5"/>
</g>
<!-- 7 -->
<g id="node10" class="node">
<title>7</title>
<polygon fill="none" stroke="black" points="598,-180 462,-180 462,-144 598,-144 598,-180"/>
<text text-anchor="middle" x="530" y="-158.3" font-family="Times,serif" font-size="14.00">valence_protocol</text>
</g>
<!-- 11&#45;&gt;7 -->
<g id="edge11" class="edge">
<title>11&#45;&gt;7</title>
<path fill="none" stroke="black" d="M644.06,-215.88C623.51,-206.35 597.75,-194.41 575.91,-184.28"/>
<polygon fill="black" stroke="black" points="577.36,-181.1 566.82,-180.07 574.42,-187.45 577.36,-181.1"/>
</g>
<!-- 4 -->
<g id="node7" class="node">
<title>4</title>
<polygon fill="none" stroke="black" points="458,-36 344,-36 344,0 458,0 458,-36"/>
<text text-anchor="middle" x="401" y="-14.3" font-family="Times,serif" font-size="14.00">valence_math</text>
</g>
<!-- 5 -->
<g id="node8" class="node">
<title>5</title>
<polygon fill="none" stroke="black" points="709.5,-36 608.5,-36 608.5,0 709.5,0 709.5,-36"/>
<text text-anchor="middle" x="659" y="-14.3" font-family="Times,serif" font-size="14.00">valence_nbt</text>
</g>
<!-- 6 -->
<g id="node9" class="node">
<title>6</title>
<polygon fill="none" stroke="black" points="590,-36 476,-36 476,0 590,0 590,-36"/>
<text text-anchor="middle" x="533" y="-14.3" font-family="Times,serif" font-size="14.00">valence_ident</text>
</g>
<!-- 8 -->
<g id="node11" class="node">
<title>8</title>
<polygon fill="none" stroke="black" points="532,-108 382,-108 382,-72 532,-72 532,-108"/>
<text text-anchor="middle" x="457" y="-86.3" font-family="Times,serif" font-size="14.00">valence_generated</text>
</g>
<!-- 7&#45;&gt;8 -->
<g id="edge5" class="edge">
<title>7&#45;&gt;8</title>
<path fill="none" stroke="black" d="M511.96,-143.7C502.94,-135.05 491.88,-124.45 482.06,-115.03"/>
<polygon fill="black" stroke="black" points="484.48,-112.5 474.84,-108.1 479.63,-117.55 484.48,-112.5"/>
</g>
<!-- 10 -->
<g id="node12" class="node">
<title>10</title>
<polygon fill="none" stroke="black" points="656,-108 550,-108 550,-72 656,-72 656,-108"/>
<text text-anchor="middle" x="603" y="-86.3" font-family="Times,serif" font-size="14.00">valence_text</text>
</g>
<!-- 7&#45;&gt;10 -->
<g id="edge6" class="edge">
<title>7&#45;&gt;10</title>
<path fill="none" stroke="black" d="M548.04,-143.7C557.06,-135.05 568.12,-124.45 577.94,-115.03"/>
<polygon fill="black" stroke="black" points="580.37,-117.55 585.16,-108.1 575.52,-112.5 580.37,-117.55"/>
</g>
<!-- 8&#45;&gt;4 -->
<g id="edge7" class="edge">
<title>8&#45;&gt;4</title>
<path fill="none" stroke="black" d="M443.16,-71.7C436.51,-63.39 428.42,-53.28 421.11,-44.14"/>
<polygon fill="black" stroke="black" points="423.66,-41.73 414.68,-36.1 418.2,-46.1 423.66,-41.73"/>
</g>
<!-- 8&#45;&gt;6 -->
<g id="edge8" class="edge">
<title>8&#45;&gt;6</title>
<path fill="none" stroke="black" d="M475.79,-71.7C485.17,-63.05 496.68,-52.45 506.91,-43.03"/>
<polygon fill="black" stroke="black" points="509.45,-45.45 514.43,-36.1 504.7,-40.3 509.45,-45.45"/>
</g>
<!-- 10&#45;&gt;5 -->
<g id="edge9" class="edge">
<title>10&#45;&gt;5</title>
<path fill="none" stroke="black" d="M616.84,-71.7C623.49,-63.39 631.58,-53.28 638.89,-44.14"/>
<polygon fill="black" stroke="black" points="641.8,-46.1 645.32,-36.1 636.34,-41.73 641.8,-46.1"/>
</g>
<!-- 10&#45;&gt;6 -->
<g id="edge10" class="edge">
<title>10&#45;&gt;6</title>
<path fill="none" stroke="black" d="M585.7,-71.7C577.14,-63.14 566.66,-52.66 557.3,-43.3"/>
<polygon fill="black" stroke="black" points="559.65,-40.7 550.1,-36.1 554.7,-45.65 559.65,-40.7"/>
</g>
<!-- 9 -->
<g id="node13" class="node">
<title>9</title>
<polygon fill="none" stroke="black" points="911,-684 759,-684 759,-648 911,-648 911,-684"/>
<text text-anchor="middle" x="835" y="-662.3" font-family="Times,serif" font-size="14.00">valence_build_utils</text>
</g>
<!-- 13 -->
<g id="node14" class="node">
<title>13</title>
<polygon fill="none" stroke="black" points="112,-468 0,-468 0,-432 112,-432 112,-468"/>
<text text-anchor="middle" x="56" y="-446.3" font-family="Times,serif" font-size="14.00">valence_anvil</text>
</g>
<!-- 13&#45;&gt;2 -->
<g id="edge13" class="edge">
<title>13&#45;&gt;2</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M112.25,-433.7C115.2,-433.08 118.13,-432.51 121,-432 294.74,-401.27 502.17,-387.51 609.2,-382.08"/>
<polygon fill="black" stroke="black" points="609.43,-385.58 619.24,-381.58 609.08,-378.58 609.43,-385.58"/>
</g>
<!-- 14 -->
<g id="node15" class="node">
<title>14</title>
<polygon fill="none" stroke="black" points="270,-468 130,-468 130,-432 270,-432 270,-468"/>
<text text-anchor="middle" x="200" y="-446.3" font-family="Times,serif" font-size="14.00">valence_boss_bar</text>
</g>
<!-- 14&#45;&gt;2 -->
<g id="edge14" class="edge">
<title>14&#45;&gt;2</title>
<path fill="none" stroke="black" d="M270.15,-433.6C273.14,-433.04 276.1,-432.5 279,-432 394.08,-412.07 528.83,-395.71 609.43,-386.67"/>
<polygon fill="black" stroke="black" points="609.92,-390.13 619.47,-385.55 609.14,-383.18 609.92,-390.13"/>
</g>
<!-- 15 -->
<g id="node16" class="node">
<title>15</title>
<polygon fill="none" stroke="black" points="610,-540 502,-540 502,-504 610,-504 610,-540"/>
<text text-anchor="middle" x="556" y="-518.3" font-family="Times,serif" font-size="14.00">valence_chat</text>
</g>
<!-- 16 -->
<g id="node17" class="node">
<title>16</title>
<polygon fill="none" stroke="black" points="768,-468 660,-468 660,-432 768,-432 768,-468"/>
<text text-anchor="middle" x="714" y="-446.3" font-family="Times,serif" font-size="14.00">valence_lang</text>
</g>
<!-- 15&#45;&gt;16 -->
<g id="edge15" class="edge">
<title>15&#45;&gt;16</title>
<path fill="none" stroke="black" d="M594.65,-503.88C616.25,-494.31 643.35,-482.3 666.27,-472.15"/>
<polygon fill="black" stroke="black" points="667.75,-475.32 675.47,-468.07 664.91,-468.92 667.75,-475.32"/>
</g>
<!-- 17 -->
<g id="node18" class="node">
<title>17</title>
<polygon fill="none" stroke="black" points="642,-468 490,-468 490,-432 642,-432 642,-468"/>
<text text-anchor="middle" x="566" y="-446.3" font-family="Times,serif" font-size="14.00">valence_player_list</text>
</g>
<!-- 15&#45;&gt;17 -->
<g id="edge16" class="edge">
<title>15&#45;&gt;17</title>
<path fill="none" stroke="black" d="M558.47,-503.7C559.57,-495.98 560.9,-486.71 562.13,-478.11"/>
<polygon fill="black" stroke="black" points="565.61,-478.5 563.56,-468.1 558.68,-477.51 565.61,-478.5"/>
</g>
<!-- 17&#45;&gt;2 -->
<g id="edge17" class="edge">
<title>17&#45;&gt;2</title>
<path fill="none" stroke="black" d="M594.13,-431.88C609.17,-422.72 627.87,-411.34 644.06,-401.48"/>
<polygon fill="black" stroke="black" points="646.04,-404.38 652.76,-396.19 642.4,-398.4 646.04,-404.38"/>
</g>
<!-- 18 -->
<g id="node19" class="node">
<title>18</title>
<polygon fill="none" stroke="black" points="434,-468 288,-468 288,-432 434,-432 434,-468"/>
<text text-anchor="middle" x="361" y="-446.3" font-family="Times,serif" font-size="14.00">valence_command</text>
</g>
<!-- 18&#45;&gt;2 -->
<g id="edge18" class="edge">
<title>18&#45;&gt;2</title>
<path fill="none" stroke="black" d="M434.01,-433.03C486.61,-421.52 557.22,-406.08 609.47,-394.65"/>
<polygon fill="black" stroke="black" points="610.31,-398.05 619.34,-392.49 608.82,-391.21 610.31,-398.05"/>
</g>
<!-- 19 -->
<g id="node20" class="node">
<title>19</title>
<polygon fill="none" stroke="black" points="484,-540 338,-540 338,-504 484,-504 484,-540"/>
<text text-anchor="middle" x="411" y="-518.3" font-family="Times,serif" font-size="14.00">valence_inventory</text>
</g>
<!-- 19&#45;&gt;2 -->
<g id="edge19" class="edge">
<title>19&#45;&gt;2</title>
<path fill="none" stroke="black" d="M419.94,-503.83C431.37,-483.58 453.08,-450.36 481,-432 519.18,-406.89 568.81,-393.65 609.07,-386.68"/>
<polygon fill="black" stroke="black" points="609.79,-390.11 619.09,-385.04 608.66,-383.2 609.79,-390.11"/>
</g>
<!-- 20 -->
<g id="node21" class="node">
<title>20</title>
<polygon fill="none" stroke="black" points="764,-540 628,-540 628,-504 764,-504 764,-540"/>
<text text-anchor="middle" x="696" y="-518.3" font-family="Times,serif" font-size="14.00">valence_network</text>
</g>
<!-- 20&#45;&gt;2 -->
<g id="edge20" class="edge">
<title>20&#45;&gt;2</title>
<path fill="none" stroke="black" d="M738.11,-503.87C753.18,-495.45 768.53,-483.67 777,-468 784.61,-453.93 785.13,-445.78 777,-432 769.14,-418.69 756.61,-408.48 743.16,-400.76"/>
<polygon fill="black" stroke="black" points="744.7,-397.62 734.22,-396.04 741.43,-403.81 744.7,-397.62"/>
</g>
<!-- 20&#45;&gt;16 -->
<g id="edge21" class="edge">
<title>20&#45;&gt;16</title>
<path fill="none" stroke="black" d="M700.45,-503.7C702.45,-495.9 704.87,-486.51 707.1,-477.83"/>
<polygon fill="black" stroke="black" points="710.5,-478.66 709.6,-468.1 703.72,-476.92 710.5,-478.66"/>
</g>
<!-- 21 -->
<g id="node22" class="node">
<title>21</title>
<polygon fill="none" stroke="black" points="939.5,-540 782.5,-540 782.5,-504 939.5,-504 939.5,-540"/>
<text text-anchor="middle" x="861" y="-518.3" font-family="Times,serif" font-size="14.00">valence_scoreboard</text>
</g>
<!-- 21&#45;&gt;2 -->
<g id="edge22" class="edge">
<title>21&#45;&gt;2</title>
<path fill="none" stroke="black" d="M851.63,-503.94C840.2,-484.41 819.22,-452.48 794,-432 777.96,-418.97 758.18,-408.29 739.68,-400.02"/>
<polygon fill="black" stroke="black" points="741.01,-396.78 730.44,-396.04 738.23,-403.21 741.01,-396.78"/>
</g>
<!-- 22 -->
<g id="node23" class="node">
<title>22</title>
<polygon fill="none" stroke="black" points="1054.5,-684 929.5,-684 929.5,-648 1054.5,-648 1054.5,-684"/>
<text text-anchor="middle" x="992" y="-662.3" font-family="Times,serif" font-size="14.00">valence_spatial</text>
</g>
<!-- 23 -->
<g id="node24" class="node">
<title>23</title>
<polygon fill="none" stroke="black" points="1094,-540 958,-540 958,-504 1094,-504 1094,-540"/>
<text text-anchor="middle" x="1026" y="-518.3" font-family="Times,serif" font-size="14.00">valence_weather</text>
</g>
<!-- 23&#45;&gt;2 -->
<g id="edge23" class="edge">
<title>23&#45;&gt;2</title>
<path fill="none" stroke="black" d="M989.26,-503.88C949.19,-485.41 883.01,-455.49 825,-432 796.96,-420.65 765.46,-408.94 739.09,-399.42"/>
<polygon fill="black" stroke="black" points="740.22,-396.11 729.63,-396.02 737.85,-402.69 740.22,-396.11"/>
</g>
<!-- 24 -->
<g id="node25" class="node">
<title>24</title>
<polygon fill="none" stroke="black" points="1285.5,-540 1112.5,-540 1112.5,-504 1285.5,-504 1285.5,-540"/>
<text text-anchor="middle" x="1199" y="-518.3" font-family="Times,serif" font-size="14.00">valence_world_border</text>
</g>
<!-- 24&#45;&gt;2 -->
<g id="edge24" class="edge">
<title>24&#45;&gt;2</title>
<path fill="none" stroke="black" d="M1138.99,-503.94C1075.11,-485.84 971.02,-456.52 881,-432 838.53,-420.43 790.89,-407.79 752.76,-397.76"/>
<polygon fill="black" stroke="black" points="753.34,-394.29 742.78,-395.13 751.56,-401.06 753.34,-394.29"/>
</g>
<!-- 25 -->
<g id="node26" class="node">
<title>25</title>
<polygon fill="none" stroke="black" points="624.5,-684 497.5,-684 497.5,-648 624.5,-648 624.5,-684"/>
<text text-anchor="middle" x="561" y="-662.3" font-family="Times,serif" font-size="14.00">dump_schedule</text>
</g>
<!-- 26 -->
<g id="node27" class="node">
<title>26</title>
<polygon fill="none" stroke="black" points="661.5,-612 590.5,-612 590.5,-576 661.5,-576 661.5,-612"/>
<text text-anchor="middle" x="626" y="-590.3" font-family="Times,serif" font-size="14.00">valence</text>
</g>
<!-- 25&#45;&gt;26 -->
<g id="edge25" class="edge">
<title>25&#45;&gt;26</title>
<path fill="none" stroke="black" d="M577.07,-647.7C584.94,-639.22 594.56,-628.86 603.17,-619.58"/>
<polygon fill="black" stroke="black" points="605.88,-621.81 610.12,-612.1 600.75,-617.05 605.88,-621.81"/>
</g>
<!-- 26&#45;&gt;1 -->
<g id="edge26" class="edge">
<title>26&#45;&gt;1</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.57,-592.93C793.69,-592.3 1250.83,-586.73 1294,-540 1304.86,-528.25 1301.65,-518.05 1294,-504 1287.09,-491.3 1275.68,-481.18 1263.54,-473.33"/>
<polygon fill="black" stroke="black" points="1265,-470.13 1254.62,-468.01 1261.41,-476.14 1265,-470.13"/>
</g>
<!-- 26&#45;&gt;13 -->
<g id="edge27" class="edge">
<title>26&#45;&gt;13</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.37,-591.17C523.6,-587.02 375.57,-574.44 256,-540 198.36,-523.39 135.76,-493.43 96.24,-472.89"/>
<polygon fill="black" stroke="black" points="97.67,-469.69 87.19,-468.15 94.42,-475.89 97.67,-469.69"/>
</g>
<!-- 26&#45;&gt;14 -->
<g id="edge28" class="edge">
<title>26&#45;&gt;14</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.28,-592.27C531.24,-589.89 410.62,-580.07 318,-540 281.98,-524.42 246.87,-495.68 224.45,-475.07"/>
<polygon fill="black" stroke="black" points="226.76,-472.44 217.07,-468.16 221.97,-477.55 226.76,-472.44"/>
</g>
<!-- 26&#45;&gt;15 -->
<g id="edge29" class="edge">
<title>26&#45;&gt;15</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M608.7,-575.7C600.14,-567.14 589.66,-556.66 580.3,-547.3"/>
<polygon fill="black" stroke="black" points="582.65,-544.7 573.1,-540.1 577.7,-549.65 582.65,-544.7"/>
</g>
<!-- 26&#45;&gt;18 -->
<g id="edge30" class="edge">
<title>26&#45;&gt;18</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.41,-592.13C518.94,-589.54 362,-579.4 329,-540 313.67,-521.69 326.09,-495.45 339.68,-476.2"/>
<polygon fill="black" stroke="black" points="342.51,-478.27 345.7,-468.17 336.9,-474.07 342.51,-478.27"/>
</g>
<!-- 26&#45;&gt;19 -->
<g id="edge31" class="edge">
<title>26&#45;&gt;19</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.5,-581.44C558.75,-571.1 511.49,-555.72 473.43,-543.33"/>
<polygon fill="black" stroke="black" points="474.06,-539.85 463.47,-540.08 471.89,-546.51 474.06,-539.85"/>
</g>
<!-- 26&#45;&gt;20 -->
<g id="edge32" class="edge">
<title>26&#45;&gt;20</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M643.3,-575.7C651.86,-567.14 662.34,-556.66 671.7,-547.3"/>
<polygon fill="black" stroke="black" points="674.3,-549.65 678.9,-540.1 669.35,-544.7 674.3,-549.65"/>
</g>
<!-- 26&#45;&gt;21 -->
<g id="edge33" class="edge">
<title>26&#45;&gt;21</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.69,-582.37C696.71,-571.94 750.98,-555.77 794.06,-542.94"/>
<polygon fill="black" stroke="black" points="795.32,-546.22 803.9,-540.01 793.32,-539.51 795.32,-546.22"/>
</g>
<!-- 26&#45;&gt;23 -->
<g id="edge34" class="edge">
<title>26&#45;&gt;23</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.84,-587.72C721.41,-578.8 844.5,-559.78 948,-540 948.1,-539.98 948.2,-539.96 948.31,-539.94"/>
<polygon fill="black" stroke="black" points="948.84,-543.4 957.98,-538.04 947.49,-536.53 948.84,-543.4"/>
</g>
<!-- 26&#45;&gt;24 -->
<g id="edge35" class="edge">
<title>26&#45;&gt;24</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.7,-589.83C739.67,-582.73 931.2,-564.37 1102.48,-540.02"/>
<polygon fill="black" stroke="black" points="1103.03,-543.48 1112.43,-538.59 1102.04,-536.55 1103.03,-543.48"/>
</g>
<!-- 27 -->
<g id="node28" class="node">
<title>27</title>
<polygon fill="none" stroke="black" points="474.5,-252 337.5,-252 337.5,-216 474.5,-216 474.5,-252"/>
<text text-anchor="middle" x="406" y="-230.3" font-family="Times,serif" font-size="14.00">packet_inspector</text>
</g>
<!-- 27&#45;&gt;7 -->
<g id="edge36" class="edge">
<title>27&#45;&gt;7</title>
<path fill="none" stroke="black" d="M436.33,-215.88C452.7,-206.64 473.08,-195.13 490.65,-185.21"/>
<polygon fill="black" stroke="black" points="492.56,-188.15 499.55,-180.19 489.12,-182.06 492.56,-188.15"/>
</g>
<!-- 28 -->
<g id="node29" class="node">
<title>28</title>
<polygon fill="none" stroke="black" points="741,-684 643,-684 643,-648 741,-648 741,-684"/>
<text text-anchor="middle" x="692" y="-662.3" font-family="Times,serif" font-size="14.00">playground</text>
</g>
<!-- 28&#45;&gt;26 -->
<g id="edge37" class="edge">
<title>28&#45;&gt;26</title>
<path fill="none" stroke="black" d="M675.69,-647.7C667.69,-639.22 657.93,-628.86 649.18,-619.58"/>
<polygon fill="black" stroke="black" points="651.53,-616.98 642.13,-612.1 646.44,-621.78 651.53,-616.98"/>
</g>
<!-- 29 -->
<g id="node30" class="node">
<title>29</title>
<polygon fill="none" stroke="black" points="567.5,-252 492.5,-252 492.5,-216 567.5,-216 567.5,-252"/>
<text text-anchor="middle" x="530" y="-230.3" font-family="Times,serif" font-size="14.00">stresser</text>
</g>
<!-- 29&#45;&gt;7 -->
<g id="edge38" class="edge">
<title>29&#45;&gt;7</title>
<path fill="none" stroke="black" d="M530,-215.7C530,-207.98 530,-198.71 530,-190.11"/>
<polygon fill="black" stroke="black" points="533.5,-190.1 530,-180.1 526.5,-190.1 533.5,-190.1"/>
</g>
</g>
</svg>

For reference, here is a diff against the old depgraph.svg:

diff --git a/assets/depgraph.svg b/assets/depgraph.svg
index 4cb26c5..f45ea37 100644
--- a/assets/depgraph.svg
+++ b/assets/depgraph.svg
@@ -1,420 +1,421 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Generated by graphviz version 9.0.0 (0)
+<!-- Generated by graphviz version 2.43.0 (0)
  -->
-<!-- Pages: 1 -->
-<svg width="1306pt" height="692pt"
- viewBox="0.00 0.00 1305.76 692.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<!-- Title: %3 Pages: 1 -->
+<svg width="1309pt" height="692pt"
+ viewBox="0.00 0.00 1309.14 692.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 688)">
-<polygon fill="white" stroke="none" points="-4,4 -4,-688 1301.76,-688 1301.76,4 -4,4"/>
+<title>%3</title>
+<polygon fill="white" stroke="transparent" points="-4,4 -4,-688 1305.14,-688 1305.14,4 -4,4"/>
 <!-- 0 -->
 <g id="node1" class="node">
 <title>0</title>
-<polygon fill="none" stroke="black" points="479,-684 384.25,-684 384.25,-648 479,-648 479,-684"/>
-<text text-anchor="middle" x="431.62" y="-661.33" font-family="Times,serif" font-size="14.00">java_string</text>
+<polygon fill="none" stroke="black" points="479.5,-684 384.5,-684 384.5,-648 479.5,-648 479.5,-684"/>
+<text text-anchor="middle" x="432" y="-662.3" font-family="Times,serif" font-size="14.00">java_string</text>
 </g>
 <!-- 1 -->
 <g id="node2" class="node">
 <title>1</title>
-<polygon fill="none" stroke="black" points="1294.62,-468 1122.62,-468 1122.62,-432 1294.62,-432 1294.62,-468"/>
-<text text-anchor="middle" x="1208.62" y="-445.32" font-family="Times,serif" font-size="14.00">valence_advancement</text>
+<polygon fill="none" stroke="black" points="1298.5,-468 1125.5,-468 1125.5,-432 1298.5,-432 1298.5,-468"/>
+<text text-anchor="middle" x="1212" y="-446.3" font-family="Times,serif" font-size="14.00">valence_advancement</text>
 </g>
 <!-- 2 -->
 <g id="node3" class="node">
 <title>2</title>
-<polygon fill="none" stroke="black" points="740.88,-396 618.38,-396 618.38,-360 740.88,-360 740.88,-396"/>
-<text text-anchor="middle" x="679.62" y="-373.32" font-family="Times,serif" font-size="14.00">valence_server</text>
+<polygon fill="none" stroke="black" points="742.5,-396 619.5,-396 619.5,-360 742.5,-360 742.5,-396"/>
+<text text-anchor="middle" x="681" y="-374.3" font-family="Times,serif" font-size="14.00">valence_server</text>
 </g>
 <!-- 1&#45;&gt;2 -->
 <g id="edge1" class="edge">
 <title>1&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M1122.16,-437.56C1019.27,-423.94 849.3,-401.45 752.69,-388.67"/>
-<polygon fill="black" stroke="black" points="753.16,-385.2 742.79,-387.36 752.24,-392.14 753.16,-385.2"/>
+<path fill="none" stroke="black" d="M1125.21,-437.56C1021.26,-423.86 849.11,-401.16 752.48,-388.42"/>
+<polygon fill="black" stroke="black" points="752.88,-384.95 742.51,-387.11 751.96,-391.89 752.88,-384.95"/>
 </g>
 <!-- 3 -->
 <g id="node4" class="node">
 <title>3</title>
-<polygon fill="none" stroke="black" points="667,-324 548.25,-324 548.25,-288 667,-288 667,-324"/>
-<text text-anchor="middle" x="607.62" y="-301.32" font-family="Times,serif" font-size="14.00">valence_entity</text>
+<polygon fill="none" stroke="black" points="668.5,-324 549.5,-324 549.5,-288 668.5,-288 668.5,-324"/>
+<text text-anchor="middle" x="609" y="-302.3" font-family="Times,serif" font-size="14.00">valence_entity</text>
 </g>
 <!-- 2&#45;&gt;3 -->
 <g id="edge2" class="edge">
 <title>2&#45;&gt;3</title>
-<path fill="none" stroke="black" d="M661.83,-359.7C653.35,-351.45 643.04,-341.43 633.69,-332.35"/>
-<polygon fill="black" stroke="black" points="636.16,-329.86 626.55,-325.4 631.28,-334.88 636.16,-329.86"/>
+<path fill="none" stroke="black" d="M663.2,-359.7C654.4,-351.14 643.62,-340.66 634,-331.3"/>
+<polygon fill="black" stroke="black" points="636.2,-328.57 626.59,-324.1 631.32,-333.58 636.2,-328.57"/>
 </g>
 <!-- 12 -->
 <g id="node5" class="node">
 <title>12</title>
-<polygon fill="none" stroke="black" points="818.5,-324 684.75,-324 684.75,-288 818.5,-288 818.5,-324"/>
-<text text-anchor="middle" x="751.62" y="-301.32" font-family="Times,serif" font-size="14.00">valence_registry</text>
+<polygon fill="none" stroke="black" points="821,-324 687,-324 687,-288 821,-288 821,-324"/>
+<text text-anchor="middle" x="754" y="-302.3" font-family="Times,serif" font-size="14.00">valence_registry</text>
 </g>
 <!-- 2&#45;&gt;12 -->
 <g id="edge3" class="edge">
 <title>2&#45;&gt;12</title>
-<path fill="none" stroke="black" d="M697.42,-359.7C705.9,-351.45 716.21,-341.43 725.56,-332.35"/>
-<polygon fill="black" stroke="black" points="727.97,-334.88 732.7,-325.4 723.09,-329.86 727.97,-334.88"/>
+<path fill="none" stroke="black" d="M699.04,-359.7C708.06,-351.05 719.12,-340.45 728.94,-331.03"/>
+<polygon fill="black" stroke="black" points="731.37,-333.55 736.16,-324.1 726.52,-328.5 731.37,-333.55"/>
 </g>
 <!-- 11 -->
 <g id="node6" class="node">
 <title>11</title>
-<polygon fill="none" stroke="black" points="774.25,-252 585,-252 585,-216 774.25,-216 774.25,-252"/>
-<text text-anchor="middle" x="679.62" y="-229.32" font-family="Times,serif" font-size="14.00">valence_server_common</text>
+<polygon fill="none" stroke="black" points="776,-252 586,-252 586,-216 776,-216 776,-252"/>
+<text text-anchor="middle" x="681" y="-230.3" font-family="Times,serif" font-size="14.00">valence_server_common</text>
 </g>
 <!-- 3&#45;&gt;11 -->
 <g id="edge4" class="edge">
 <title>3&#45;&gt;11</title>
-<path fill="none" stroke="black" d="M625.42,-287.7C633.9,-279.45 644.21,-269.43 653.56,-260.35"/>
-<polygon fill="black" stroke="black" points="655.97,-262.88 660.7,-253.4 651.09,-257.86 655.97,-262.88"/>
+<path fill="none" stroke="black" d="M626.8,-287.7C635.6,-279.14 646.38,-268.66 656,-259.3"/>
+<polygon fill="black" stroke="black" points="658.68,-261.58 663.41,-252.1 653.8,-256.57 658.68,-261.58"/>
 </g>
 <!-- 12&#45;&gt;11 -->
 <g id="edge12" class="edge">
 <title>12&#45;&gt;11</title>
-<path fill="none" stroke="black" d="M733.83,-287.7C725.35,-279.45 715.04,-269.43 705.69,-260.35"/>
-<polygon fill="black" stroke="black" points="708.16,-257.86 698.55,-253.4 703.28,-262.88 708.16,-257.86"/>
+<path fill="none" stroke="black" d="M735.96,-287.7C726.94,-279.05 715.88,-268.45 706.06,-259.03"/>
+<polygon fill="black" stroke="black" points="708.48,-256.5 698.84,-252.1 703.63,-261.55 708.48,-256.5"/>
 </g>
 <!-- 7 -->
 <g id="node10" class="node">
 <title>7</title>
-<polygon fill="none" stroke="black" points="597.25,-180 462,-180 462,-144 597.25,-144 597.25,-180"/>
-<text text-anchor="middle" x="529.62" y="-157.32" font-family="Times,serif" font-size="14.00">valence_protocol</text>
+<polygon fill="none" stroke="black" points="598,-180 462,-180 462,-144 598,-144 598,-180"/>
+<text text-anchor="middle" x="530" y="-158.3" font-family="Times,serif" font-size="14.00">valence_protocol</text>
 </g>
 <!-- 11&#45;&gt;7 -->
 <g id="edge11" class="edge">
 <title>11&#45;&gt;7</title>
-<path fill="none" stroke="black" d="M642.16,-215.52C622.49,-206.34 598.17,-194.99 577.19,-185.2"/>
-<polygon fill="black" stroke="black" points="578.79,-182.08 568.24,-181.02 575.82,-188.42 578.79,-182.08"/>
+<path fill="none" stroke="black" d="M644.06,-215.88C623.51,-206.35 597.75,-194.41 575.91,-184.28"/>
+<polygon fill="black" stroke="black" points="577.36,-181.1 566.82,-180.07 574.42,-187.45 577.36,-181.1"/>
 </g>
 <!-- 4 -->
 <g id="node7" class="node">
 <title>4</title>
-<polygon fill="none" stroke="black" points="458.38,-36 344.88,-36 344.88,0 458.38,0 458.38,-36"/>
-<text text-anchor="middle" x="401.62" y="-13.32" font-family="Times,serif" font-size="14.00">valence_math</text>
+<polygon fill="none" stroke="black" points="458,-36 344,-36 344,0 458,0 458,-36"/>
+<text text-anchor="middle" x="401" y="-14.3" font-family="Times,serif" font-size="14.00">valence_math</text>
 </g>
 <!-- 5 -->
 <g id="node8" class="node">
 <title>5</title>
-<polygon fill="none" stroke="black" points="709,-36 608.25,-36 608.25,0 709,0 709,-36"/>
-<text text-anchor="middle" x="658.62" y="-13.32" font-family="Times,serif" font-size="14.00">valence_nbt</text>
+<polygon fill="none" stroke="black" points="709.5,-36 608.5,-36 608.5,0 709.5,0 709.5,-36"/>
+<text text-anchor="middle" x="659" y="-14.3" font-family="Times,serif" font-size="14.00">valence_nbt</text>
 </g>
 <!-- 6 -->
 <g id="node9" class="node">
 <title>6</title>
-<polygon fill="none" stroke="black" points="590.38,-36 476.88,-36 476.88,0 590.38,0 590.38,-36"/>
-<text text-anchor="middle" x="533.62" y="-13.32" font-family="Times,serif" font-size="14.00">valence_ident</text>
+<polygon fill="none" stroke="black" points="590,-36 476,-36 476,0 590,0 590,-36"/>
+<text text-anchor="middle" x="533" y="-14.3" font-family="Times,serif" font-size="14.00">valence_ident</text>
 </g>
 <!-- 8 -->
 <g id="node11" class="node">
 <title>8</title>
-<polygon fill="none" stroke="black" points="532.38,-108 382.88,-108 382.88,-72 532.38,-72 532.38,-108"/>
-<text text-anchor="middle" x="457.62" y="-85.33" font-family="Times,serif" font-size="14.00">valence_generated</text>
+<polygon fill="none" stroke="black" points="532,-108 382,-108 382,-72 532,-72 532,-108"/>
+<text text-anchor="middle" x="457" y="-86.3" font-family="Times,serif" font-size="14.00">valence_generated</text>
 </g>
 <!-- 7&#45;&gt;8 -->
 <g id="edge5" class="edge">
 <title>7&#45;&gt;8</title>
-<path fill="none" stroke="black" d="M511.83,-143.7C503.35,-135.45 493.04,-125.43 483.69,-116.35"/>
-<polygon fill="black" stroke="black" points="486.16,-113.86 476.55,-109.4 481.28,-118.88 486.16,-113.86"/>
+<path fill="none" stroke="black" d="M511.96,-143.7C502.94,-135.05 491.88,-124.45 482.06,-115.03"/>
+<polygon fill="black" stroke="black" points="484.48,-112.5 474.84,-108.1 479.63,-117.55 484.48,-112.5"/>
 </g>
 <!-- 10 -->
 <g id="node12" class="node">
 <title>10</title>
-<polygon fill="none" stroke="black" points="655.25,-108 550,-108 550,-72 655.25,-72 655.25,-108"/>
-<text text-anchor="middle" x="602.62" y="-85.33" font-family="Times,serif" font-size="14.00">valence_text</text>
+<polygon fill="none" stroke="black" points="656,-108 550,-108 550,-72 656,-72 656,-108"/>
+<text text-anchor="middle" x="603" y="-86.3" font-family="Times,serif" font-size="14.00">valence_text</text>
 </g>
 <!-- 7&#45;&gt;10 -->
 <g id="edge6" class="edge">
 <title>7&#45;&gt;10</title>
-<path fill="none" stroke="black" d="M547.67,-143.7C556.36,-135.37 566.94,-125.22 576.48,-116.07"/>
-<polygon fill="black" stroke="black" points="578.65,-118.84 583.44,-109.39 573.8,-113.79 578.65,-118.84"/>
+<path fill="none" stroke="black" d="M548.04,-143.7C557.06,-135.05 568.12,-124.45 577.94,-115.03"/>
+<polygon fill="black" stroke="black" points="580.37,-117.55 585.16,-108.1 575.52,-112.5 580.37,-117.55"/>
 </g>
 <!-- 8&#45;&gt;4 -->
 <g id="edge7" class="edge">
 <title>8&#45;&gt;4</title>
-<path fill="none" stroke="black" d="M443.78,-71.7C437.34,-63.64 429.54,-53.89 422.41,-44.98"/>
-<polygon fill="black" stroke="black" points="425.23,-42.91 416.25,-37.29 419.77,-47.28 425.23,-42.91"/>
+<path fill="none" stroke="black" d="M443.16,-71.7C436.51,-63.39 428.42,-53.28 421.11,-44.14"/>
+<polygon fill="black" stroke="black" points="423.66,-41.73 414.68,-36.1 418.2,-46.1 423.66,-41.73"/>
 </g>
 <!-- 8&#45;&gt;6 -->
 <g id="edge8" class="edge">
 <title>8&#45;&gt;6</title>
-<path fill="none" stroke="black" d="M476.41,-71.7C485.45,-63.37 496.47,-53.22 506.41,-44.07"/>
-<polygon fill="black" stroke="black" points="508.69,-46.72 513.68,-37.37 503.95,-41.57 508.69,-46.72"/>
+<path fill="none" stroke="black" d="M475.79,-71.7C485.17,-63.05 496.68,-52.45 506.91,-43.03"/>
+<polygon fill="black" stroke="black" points="509.45,-45.45 514.43,-36.1 504.7,-40.3 509.45,-45.45"/>
 </g>
 <!-- 10&#45;&gt;5 -->
 <g id="edge9" class="edge">
 <title>10&#45;&gt;5</title>
-<path fill="none" stroke="black" d="M616.47,-71.7C622.91,-63.64 630.71,-53.89 637.84,-44.98"/>
-<polygon fill="black" stroke="black" points="640.48,-47.28 644,-37.29 635.02,-42.91 640.48,-47.28"/>
+<path fill="none" stroke="black" d="M616.84,-71.7C623.49,-63.39 631.58,-53.28 638.89,-44.14"/>
+<polygon fill="black" stroke="black" points="641.8,-46.1 645.32,-36.1 636.34,-41.73 641.8,-46.1"/>
 </g>
 <!-- 10&#45;&gt;6 -->
 <g id="edge10" class="edge">
 <title>10&#45;&gt;6</title>
-<path fill="none" stroke="black" d="M585.57,-71.7C577.38,-63.39 567.41,-53.28 558.41,-44.14"/>
-<polygon fill="black" stroke="black" points="561.06,-41.85 551.55,-37.18 556.07,-46.76 561.06,-41.85"/>
+<path fill="none" stroke="black" d="M585.7,-71.7C577.14,-63.14 566.66,-52.66 557.3,-43.3"/>
+<polygon fill="black" stroke="black" points="559.65,-40.7 550.1,-36.1 554.7,-45.65 559.65,-40.7"/>
 </g>
 <!-- 9 -->
 <g id="node13" class="node">
 <title>9</title>
-<polygon fill="none" stroke="black" points="908.12,-684 757.12,-684 757.12,-648 908.12,-648 908.12,-684"/>
-<text text-anchor="middle" x="832.62" y="-661.33" font-family="Times,serif" font-size="14.00">valence_build_utils</text>
+<polygon fill="none" stroke="black" points="911,-684 759,-684 759,-648 911,-648 911,-684"/>
+<text text-anchor="middle" x="835" y="-662.3" font-family="Times,serif" font-size="14.00">valence_build_utils</text>
 </g>
 <!-- 13 -->
 <g id="node14" class="node">
 <title>13</title>
-<polygon fill="none" stroke="black" points="111.25,-468 0,-468 0,-432 111.25,-432 111.25,-468"/>
-<text text-anchor="middle" x="55.62" y="-445.32" font-family="Times,serif" font-size="14.00">valence_anvil</text>
+<polygon fill="none" stroke="black" points="112,-468 0,-468 0,-432 112,-432 112,-468"/>
+<text text-anchor="middle" x="56" y="-446.3" font-family="Times,serif" font-size="14.00">valence_anvil</text>
 </g>
 <!-- 13&#45;&gt;2 -->
 <g id="edge13" class="edge">
 <title>13&#45;&gt;2</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M111.52,-433.77C114.59,-433.13 117.64,-432.53 120.62,-432 293.36,-401.43 499.45,-387.65 606.66,-382.16"/>
-<polygon fill="black" stroke="black" points="606.65,-385.66 616.47,-381.67 606.3,-378.67 606.65,-385.66"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M112.25,-433.7C115.2,-433.08 118.13,-432.51 121,-432 294.74,-401.27 502.17,-387.51 609.2,-382.08"/>
+<polygon fill="black" stroke="black" points="609.43,-385.58 619.24,-381.58 609.08,-378.58 609.43,-385.58"/>
 </g>
 <!-- 14 -->
 <g id="node15" class="node">
 <title>14</title>
-<polygon fill="none" stroke="black" points="269.5,-468 129.75,-468 129.75,-432 269.5,-432 269.5,-468"/>
-<text text-anchor="middle" x="199.62" y="-445.32" font-family="Times,serif" font-size="14.00">valence_boss_bar</text>
+<polygon fill="none" stroke="black" points="270,-468 130,-468 130,-432 270,-432 270,-468"/>
+<text text-anchor="middle" x="200" y="-446.3" font-family="Times,serif" font-size="14.00">valence_boss_bar</text>
 </g>
 <!-- 14&#45;&gt;2 -->
 <g id="edge14" class="edge">
 <title>14&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M269.78,-433.6C272.76,-433.04 275.72,-432.5 278.62,-432 392.78,-412.21 526.36,-395.91 606.9,-386.83"/>
-<polygon fill="black" stroke="black" points="606.86,-390.35 616.4,-385.76 606.08,-383.4 606.86,-390.35"/>
+<path fill="none" stroke="black" d="M270.15,-433.6C273.14,-433.04 276.1,-432.5 279,-432 394.08,-412.07 528.83,-395.71 609.43,-386.67"/>
+<polygon fill="black" stroke="black" points="609.92,-390.13 619.47,-385.55 609.14,-383.18 609.92,-390.13"/>
 </g>
 <!-- 15 -->
 <g id="node16" class="node">
 <title>15</title>
-<polygon fill="none" stroke="black" points="610.38,-540 502.88,-540 502.88,-504 610.38,-504 610.38,-540"/>
-<text text-anchor="middle" x="556.62" y="-517.33" font-family="Times,serif" font-size="14.00">valence_chat</text>
+<polygon fill="none" stroke="black" points="610,-540 502,-540 502,-504 610,-504 610,-540"/>
+<text text-anchor="middle" x="556" y="-518.3" font-family="Times,serif" font-size="14.00">valence_chat</text>
 </g>
 <!-- 16 -->
 <g id="node17" class="node">
 <title>16</title>
-<polygon fill="none" stroke="black" points="766.38,-468 658.88,-468 658.88,-432 766.38,-432 766.38,-468"/>
-<text text-anchor="middle" x="712.62" y="-445.32" font-family="Times,serif" font-size="14.00">valence_lang</text>
+<polygon fill="none" stroke="black" points="768,-468 660,-468 660,-432 768,-432 768,-468"/>
+<text text-anchor="middle" x="714" y="-446.3" font-family="Times,serif" font-size="14.00">valence_lang</text>
 </g>
 <!-- 15&#45;&gt;16 -->
 <g id="edge15" class="edge">
 <title>15&#45;&gt;16</title>
-<path fill="none" stroke="black" d="M595.59,-503.52C616.14,-494.29 641.56,-482.89 663.46,-473.06"/>
-<polygon fill="black" stroke="black" points="664.82,-476.29 672.51,-469 661.95,-469.9 664.82,-476.29"/>
+<path fill="none" stroke="black" d="M594.65,-503.88C616.25,-494.31 643.35,-482.3 666.27,-472.15"/>
+<polygon fill="black" stroke="black" points="667.75,-475.32 675.47,-468.07 664.91,-468.92 667.75,-475.32"/>
 </g>
 <!-- 17 -->
 <g id="node18" class="node">
 <title>17</title>
-<polygon fill="none" stroke="black" points="641.12,-468 490.12,-468 490.12,-432 641.12,-432 641.12,-468"/>
-<text text-anchor="middle" x="565.62" y="-445.32" font-family="Times,serif" font-size="14.00">valence_player_list</text>
+<polygon fill="none" stroke="black" points="642,-468 490,-468 490,-432 642,-432 642,-468"/>
+<text text-anchor="middle" x="566" y="-446.3" font-family="Times,serif" font-size="14.00">valence_player_list</text>
 </g>
 <!-- 15&#45;&gt;17 -->
 <g id="edge16" class="edge">
 <title>15&#45;&gt;17</title>
-<path fill="none" stroke="black" d="M558.85,-503.7C559.8,-496.32 560.93,-487.52 561.99,-479.25"/>
-<polygon fill="black" stroke="black" points="565.43,-479.97 563.23,-469.61 558.49,-479.08 565.43,-479.97"/>
+<path fill="none" stroke="black" d="M558.47,-503.7C559.57,-495.98 560.9,-486.71 562.13,-478.11"/>
+<polygon fill="black" stroke="black" points="565.61,-478.5 563.56,-468.1 558.68,-477.51 565.61,-478.5"/>
 </g>
 <!-- 17&#45;&gt;2 -->
 <g id="edge17" class="edge">
 <title>17&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M594.1,-431.52C608.63,-422.6 626.48,-411.63 642.12,-402.03"/>
-<polygon fill="black" stroke="black" points="643.53,-405.27 650.23,-397.05 639.87,-399.3 643.53,-405.27"/>
+<path fill="none" stroke="black" d="M594.13,-431.88C609.17,-422.72 627.87,-411.34 644.06,-401.48"/>
+<polygon fill="black" stroke="black" points="646.04,-404.38 652.76,-396.19 642.4,-398.4 646.04,-404.38"/>
 </g>
 <!-- 18 -->
 <g id="node19" class="node">
 <title>18</title>
-<polygon fill="none" stroke="black" points="433.5,-468 287.75,-468 287.75,-432 433.5,-432 433.5,-468"/>
-<text text-anchor="middle" x="360.62" y="-445.32" font-family="Times,serif" font-size="14.00">valence_command</text>
+<polygon fill="none" stroke="black" points="434,-468 288,-468 288,-432 434,-432 434,-468"/>
+<text text-anchor="middle" x="361" y="-446.3" font-family="Times,serif" font-size="14.00">valence_command</text>
 </g>
 <!-- 18&#45;&gt;2 -->
 <g id="edge18" class="edge">
 <title>18&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M433.81,-432.94C485.74,-421.55 555.13,-406.32 606.94,-394.95"/>
-<polygon fill="black" stroke="black" points="607.55,-398.4 616.57,-392.84 606.05,-391.56 607.55,-398.4"/>
+<path fill="none" stroke="black" d="M434.01,-433.03C486.61,-421.52 557.22,-406.08 609.47,-394.65"/>
+<polygon fill="black" stroke="black" points="610.31,-398.05 619.34,-392.49 608.82,-391.21 610.31,-398.05"/>
 </g>
 <!-- 19 -->
 <g id="node20" class="node">
 <title>19</title>
-<polygon fill="none" stroke="black" points="485.12,-540 340.12,-540 340.12,-504 485.12,-504 485.12,-540"/>
-<text text-anchor="middle" x="412.62" y="-517.33" font-family="Times,serif" font-size="14.00">valence_inventory</text>
+<polygon fill="none" stroke="black" points="484,-540 338,-540 338,-504 484,-504 484,-540"/>
+<text text-anchor="middle" x="411" y="-518.3" font-family="Times,serif" font-size="14.00">valence_inventory</text>
 </g>
 <!-- 19&#45;&gt;2 -->
 <g id="edge19" class="edge">
 <title>19&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M421.19,-503.84C432.17,-483.59 453.14,-450.37 480.62,-432 518.04,-406.99 566.77,-393.76 606.64,-386.77"/>
-<polygon fill="black" stroke="black" points="607.11,-390.24 616.41,-385.17 605.98,-383.34 607.11,-390.24"/>
+<path fill="none" stroke="black" d="M419.94,-503.83C431.37,-483.58 453.08,-450.36 481,-432 519.18,-406.89 568.81,-393.65 609.07,-386.68"/>
+<polygon fill="black" stroke="black" points="609.79,-390.11 619.09,-385.04 608.66,-383.2 609.79,-390.11"/>
 </g>
 <!-- 20 -->
 <g id="node21" class="node">
 <title>20</title>
-<polygon fill="none" stroke="black" points="763.25,-540 628,-540 628,-504 763.25,-504 763.25,-540"/>
-<text text-anchor="middle" x="695.62" y="-517.33" font-family="Times,serif" font-size="14.00">valence_network</text>
+<polygon fill="none" stroke="black" points="764,-540 628,-540 628,-504 764,-504 764,-540"/>
+<text text-anchor="middle" x="696" y="-518.3" font-family="Times,serif" font-size="14.00">valence_network</text>
 </g>
 <!-- 20&#45;&gt;2 -->
 <g id="edge20" class="edge">
 <title>20&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M737.65,-503.52C752.4,-495.1 767.35,-483.41 775.62,-468 783.2,-453.9 783.76,-445.78 775.62,-432 768.11,-419.26 756.31,-409.37 743.52,-401.78"/>
-<polygon fill="black" stroke="black" points="745.4,-398.81 734.94,-397.13 742.06,-404.97 745.4,-398.81"/>
+<path fill="none" stroke="black" d="M738.11,-503.87C753.18,-495.45 768.53,-483.67 777,-468 784.61,-453.93 785.13,-445.78 777,-432 769.14,-418.69 756.61,-408.48 743.16,-400.76"/>
+<polygon fill="black" stroke="black" points="744.7,-397.62 734.22,-396.04 741.43,-403.81 744.7,-397.62"/>
 </g>
 <!-- 20&#45;&gt;16 -->
 <g id="edge21" class="edge">
 <title>20&#45;&gt;16</title>
-<path fill="none" stroke="black" d="M699.83,-503.7C701.62,-496.32 703.75,-487.52 705.76,-479.25"/>
-<polygon fill="black" stroke="black" points="709.15,-480.12 708.11,-469.58 702.35,-478.47 709.15,-480.12"/>
+<path fill="none" stroke="black" d="M700.45,-503.7C702.45,-495.9 704.87,-486.51 707.1,-477.83"/>
+<polygon fill="black" stroke="black" points="710.5,-478.66 709.6,-468.1 703.72,-476.92 710.5,-478.66"/>
 </g>
 <!-- 21 -->
 <g id="node22" class="node">
 <title>21</title>
-<polygon fill="none" stroke="black" points="937.75,-540 781.5,-540 781.5,-504 937.75,-504 937.75,-540"/>
-<text text-anchor="middle" x="859.62" y="-517.33" font-family="Times,serif" font-size="14.00">valence_scoreboard</text>
+<polygon fill="none" stroke="black" points="939.5,-540 782.5,-540 782.5,-504 939.5,-504 939.5,-540"/>
+<text text-anchor="middle" x="861" y="-518.3" font-family="Times,serif" font-size="14.00">valence_scoreboard</text>
 </g>
 <!-- 21&#45;&gt;2 -->
 <g id="edge22" class="edge">
 <title>21&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M850.05,-503.59C838.57,-484.03 817.7,-452.36 792.62,-432 777.16,-419.44 758.22,-409.06 740.31,-400.93"/>
-<polygon fill="black" stroke="black" points="741.86,-397.79 731.3,-397 739.06,-404.2 741.86,-397.79"/>
+<path fill="none" stroke="black" d="M851.63,-503.94C840.2,-484.41 819.22,-452.48 794,-432 777.96,-418.97 758.18,-408.29 739.68,-400.02"/>
+<polygon fill="black" stroke="black" points="741.01,-396.78 730.44,-396.04 738.23,-403.21 741.01,-396.78"/>
 </g>
 <!-- 22 -->
 <g id="node23" class="node">
 <title>22</title>
-<polygon fill="none" stroke="black" points="1051,-684 926.25,-684 926.25,-648 1051,-648 1051,-684"/>
-<text text-anchor="middle" x="988.62" y="-661.33" font-family="Times,serif" font-size="14.00">valence_spatial</text>
+<polygon fill="none" stroke="black" points="1054.5,-684 929.5,-684 929.5,-648 1054.5,-648 1054.5,-684"/>
+<text text-anchor="middle" x="992" y="-662.3" font-family="Times,serif" font-size="14.00">valence_spatial</text>
 </g>
 <!-- 23 -->
 <g id="node24" class="node">
 <title>23</title>
-<polygon fill="none" stroke="black" points="1091.25,-540 956,-540 956,-504 1091.25,-504 1091.25,-540"/>
-<text text-anchor="middle" x="1023.62" y="-517.33" font-family="Times,serif" font-size="14.00">valence_weather</text>
+<polygon fill="none" stroke="black" points="1094,-540 958,-540 958,-504 1094,-504 1094,-540"/>
+<text text-anchor="middle" x="1026" y="-518.3" font-family="Times,serif" font-size="14.00">valence_weather</text>
 </g>
 <!-- 23&#45;&gt;2 -->
 <g id="edge23" class="edge">
 <title>23&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M986.34,-503.52C946.41,-485.01 881.02,-455.3 823.62,-432 796.52,-421 766.17,-409.68 740.35,-400.34"/>
-<polygon fill="black" stroke="black" points="741.6,-397.08 731.01,-396.98 739.23,-403.66 741.6,-397.08"/>
+<path fill="none" stroke="black" d="M989.26,-503.88C949.19,-485.41 883.01,-455.49 825,-432 796.96,-420.65 765.46,-408.94 739.09,-399.42"/>
+<polygon fill="black" stroke="black" points="740.22,-396.11 729.63,-396.02 737.85,-402.69 740.22,-396.11"/>
 </g>
 <!-- 24 -->
 <g id="node25" class="node">
 <title>24</title>
-<polygon fill="none" stroke="black" points="1281.62,-540 1109.62,-540 1109.62,-504 1281.62,-504 1281.62,-540"/>
-<text text-anchor="middle" x="1195.62" y="-517.33" font-family="Times,serif" font-size="14.00">valence_world_border</text>
+<polygon fill="none" stroke="black" points="1285.5,-540 1112.5,-540 1112.5,-504 1285.5,-504 1285.5,-540"/>
+<text text-anchor="middle" x="1199" y="-518.3" font-family="Times,serif" font-size="14.00">valence_world_border</text>
 </g>
 <!-- 24&#45;&gt;2 -->
 <g id="edge24" class="edge">
 <title>24&#45;&gt;2</title>
-<path fill="none" stroke="black" d="M1134.83,-503.58C1071.26,-485.43 968.55,-456.3 879.62,-432 837.37,-420.45 789.98,-407.88 751.94,-397.88"/>
-<polygon fill="black" stroke="black" points="752.99,-394.53 742.43,-395.38 751.21,-401.3 752.99,-394.53"/>
+<path fill="none" stroke="black" d="M1138.99,-503.94C1075.11,-485.84 971.02,-456.52 881,-432 838.53,-420.43 790.89,-407.79 752.76,-397.76"/>
+<polygon fill="black" stroke="black" points="753.34,-394.29 742.78,-395.13 751.56,-401.06 753.34,-394.29"/>
 </g>
 <!-- 25 -->
 <g id="node26" class="node">
 <title>25</title>
-<polygon fill="none" stroke="black" points="623.75,-684 497.5,-684 497.5,-648 623.75,-648 623.75,-684"/>
-<text text-anchor="middle" x="560.62" y="-661.33" font-family="Times,serif" font-size="14.00">dump_schedule</text>
+<polygon fill="none" stroke="black" points="624.5,-684 497.5,-684 497.5,-648 624.5,-648 624.5,-684"/>
+<text text-anchor="middle" x="561" y="-662.3" font-family="Times,serif" font-size="14.00">dump_schedule</text>
 </g>
 <!-- 26 -->
 <g id="node27" class="node">
 <title>26</title>
-<polygon fill="none" stroke="black" points="660.62,-612 590.62,-612 590.62,-576 660.62,-576 660.62,-612"/>
-<text text-anchor="middle" x="625.62" y="-589.33" font-family="Times,serif" font-size="14.00">valence</text>
+<polygon fill="none" stroke="black" points="661.5,-612 590.5,-612 590.5,-576 661.5,-576 661.5,-612"/>
+<text text-anchor="middle" x="626" y="-590.3" font-family="Times,serif" font-size="14.00">valence</text>
 </g>
 <!-- 25&#45;&gt;26 -->
 <g id="edge25" class="edge">
 <title>25&#45;&gt;26</title>
-<path fill="none" stroke="black" d="M576.69,-647.7C584.33,-639.47 593.6,-629.48 602.02,-620.42"/>
-<polygon fill="black" stroke="black" points="604.47,-622.92 608.71,-613.21 599.34,-618.16 604.47,-622.92"/>
+<path fill="none" stroke="black" d="M577.07,-647.7C584.94,-639.22 594.56,-628.86 603.17,-619.58"/>
+<polygon fill="black" stroke="black" points="605.88,-621.81 610.12,-612.1 600.75,-617.05 605.88,-621.81"/>
 </g>
 <!-- 26&#45;&gt;1 -->
 <g id="edge26" class="edge">
 <title>26&#45;&gt;1</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.04,-592.92C792.57,-592.24 1247.65,-586.53 1290.62,-540 1301.48,-528.25 1298.27,-518.05 1290.62,-504 1284.04,-491.9 1273.38,-482.15 1261.88,-474.46"/>
-<polygon fill="black" stroke="black" points="1263.76,-471.51 1253.4,-469.28 1260.11,-477.48 1263.76,-471.51"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.57,-592.93C793.69,-592.3 1250.83,-586.73 1294,-540 1304.86,-528.25 1301.65,-518.05 1294,-504 1287.09,-491.3 1275.68,-481.18 1263.54,-473.33"/>
+<polygon fill="black" stroke="black" points="1265,-470.13 1254.62,-468.01 1261.41,-476.14 1265,-470.13"/>
 </g>
 <!-- 26&#45;&gt;13 -->
 <g id="edge27" class="edge">
 <title>26&#45;&gt;13</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.36,-591.15C523.9,-586.97 376.06,-574.31 256.62,-540 199.55,-523.6 137.6,-494.26 97.79,-473.77"/>
-<polygon fill="black" stroke="black" points="99.5,-470.71 89.01,-469.2 96.27,-476.92 99.5,-470.71"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.37,-591.17C523.6,-587.02 375.57,-574.44 256,-540 198.36,-523.39 135.76,-493.43 96.24,-472.89"/>
+<polygon fill="black" stroke="black" points="97.67,-469.69 87.19,-468.15 94.42,-475.89 97.67,-469.69"/>
 </g>
 <!-- 26&#45;&gt;14 -->
 <g id="edge28" class="edge">
 <title>26&#45;&gt;14</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.18,-592.14C531.57,-589.58 411.8,-579.5 319.62,-540 283.63,-524.58 248.36,-496.4 225.48,-475.87"/>
-<polygon fill="black" stroke="black" points="227.9,-473.34 218.16,-469.16 223.17,-478.5 227.9,-473.34"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.28,-592.27C531.24,-589.89 410.62,-580.07 318,-540 281.98,-524.42 246.87,-495.68 224.45,-475.07"/>
+<polygon fill="black" stroke="black" points="226.76,-472.44 217.07,-468.16 221.97,-477.55 226.76,-472.44"/>
 </g>
 <!-- 26&#45;&gt;15 -->
 <g id="edge29" class="edge">
 <title>26&#45;&gt;15</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M608.57,-575.7C600.38,-567.39 590.41,-557.28 581.41,-548.14"/>
-<polygon fill="black" stroke="black" points="584.06,-545.85 574.55,-541.18 579.07,-550.76 584.06,-545.85"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M608.7,-575.7C600.14,-567.14 589.66,-556.66 580.3,-547.3"/>
+<polygon fill="black" stroke="black" points="582.65,-544.7 573.1,-540.1 577.7,-549.65 582.65,-544.7"/>
 </g>
 <!-- 26&#45;&gt;18 -->
 <g id="edge30" class="edge">
 <title>26&#45;&gt;18</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.27,-592.09C519.28,-589.43 363.38,-579.17 330.62,-540 315.75,-522.21 326.66,-496.72 339.3,-477.58"/>
-<polygon fill="black" stroke="black" points="342.13,-479.63 345.06,-469.45 336.42,-475.58 342.13,-479.63"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.41,-592.13C518.94,-589.54 362,-579.4 329,-540 313.67,-521.69 326.09,-495.45 339.68,-476.2"/>
+<polygon fill="black" stroke="black" points="342.51,-478.27 345.7,-468.17 336.9,-474.07 342.51,-478.27"/>
 </g>
 <!-- 26&#45;&gt;19 -->
 <g id="edge31" class="edge">
 <title>26&#45;&gt;19</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.45,-581.44C559.59,-571.3 513.93,-556.29 476.61,-544.03"/>
-<polygon fill="black" stroke="black" points="477.85,-540.75 467.26,-540.95 475.67,-547.4 477.85,-540.75"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M590.5,-581.44C558.75,-571.1 511.49,-555.72 473.43,-543.33"/>
+<polygon fill="black" stroke="black" points="474.06,-539.85 463.47,-540.08 471.89,-546.51 474.06,-539.85"/>
 </g>
 <!-- 26&#45;&gt;20 -->
 <g id="edge32" class="edge">
 <title>26&#45;&gt;20</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M642.93,-575.7C651.24,-567.39 661.35,-557.28 670.48,-548.14"/>
-<polygon fill="black" stroke="black" points="672.85,-550.72 677.45,-541.17 667.9,-545.77 672.85,-550.72"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M643.3,-575.7C651.86,-567.14 662.34,-556.66 671.7,-547.3"/>
+<polygon fill="black" stroke="black" points="674.3,-549.65 678.9,-540.1 669.35,-544.7 674.3,-549.65"/>
 </g>
 <!-- 26&#45;&gt;21 -->
 <g id="edge33" class="edge">
 <title>26&#45;&gt;21</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M660.91,-582.44C695.09,-572.22 747.85,-556.44 790.42,-543.7"/>
-<polygon fill="black" stroke="black" points="791.26,-547.11 799.83,-540.89 789.25,-540.4 791.26,-547.11"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.69,-582.37C696.71,-571.94 750.98,-555.77 794.06,-542.94"/>
+<polygon fill="black" stroke="black" points="795.32,-546.22 803.9,-540.01 793.32,-539.51 795.32,-546.22"/>
 </g>
 <!-- 26&#45;&gt;23 -->
 <g id="edge34" class="edge">
 <title>26&#45;&gt;23</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M660.88,-587.81C718.13,-579.25 835.08,-561.19 944.41,-540.37"/>
-<polygon fill="black" stroke="black" points="945,-543.82 954.16,-538.5 943.68,-536.95 945,-543.82"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.84,-587.72C721.41,-578.8 844.5,-559.78 948,-540 948.1,-539.98 948.2,-539.96 948.31,-539.94"/>
+<polygon fill="black" stroke="black" points="948.84,-543.4 957.98,-538.04 947.49,-536.53 948.84,-543.4"/>
 </g>
 <!-- 26&#45;&gt;24 -->
 <g id="edge35" class="edge">
 <title>26&#45;&gt;24</title>
-<path fill="none" stroke="black" stroke-dasharray="1,5" d="M660.88,-589.87C738.15,-582.83 928.39,-564.58 1098.05,-540.32"/>
-<polygon fill="black" stroke="black" points="1098.3,-543.82 1107.7,-538.93 1097.3,-536.89 1098.3,-543.82"/>
+<path fill="none" stroke="black" stroke-dasharray="1,5" d="M661.7,-589.83C739.67,-582.73 931.2,-564.37 1102.48,-540.02"/>
+<polygon fill="black" stroke="black" points="1103.03,-543.48 1112.43,-538.59 1102.04,-536.55 1103.03,-543.48"/>
 </g>
 <!-- 27 -->
 <g id="node28" class="node">
 <title>27</title>
-<polygon fill="none" stroke="black" points="474,-252 337.25,-252 337.25,-216 474,-216 474,-252"/>
-<text text-anchor="middle" x="405.62" y="-229.32" font-family="Times,serif" font-size="14.00">packet_inspector</text>
+<polygon fill="none" stroke="black" points="474.5,-252 337.5,-252 337.5,-216 474.5,-216 474.5,-252"/>
+<text text-anchor="middle" x="406" y="-230.3" font-family="Times,serif" font-size="14.00">packet_inspector</text>
 </g>
 <!-- 27&#45;&gt;7 -->
 <g id="edge36" class="edge">
 <title>27&#45;&gt;7</title>
-<path fill="none" stroke="black" d="M436.6,-215.52C452.55,-206.51 472.19,-195.42 489.31,-185.76"/>
-<polygon fill="black" stroke="black" points="490.74,-188.97 497.73,-181 487.3,-182.87 490.74,-188.97"/>
+<path fill="none" stroke="black" d="M436.33,-215.88C452.7,-206.64 473.08,-195.13 490.65,-185.21"/>
+<polygon fill="black" stroke="black" points="492.56,-188.15 499.55,-180.19 489.12,-182.06 492.56,-188.15"/>
 </g>
 <!-- 28 -->
 <g id="node29" class="node">
 <title>28</title>
-<polygon fill="none" stroke="black" points="739.12,-684 642.12,-684 642.12,-648 739.12,-648 739.12,-684"/>
-<text text-anchor="middle" x="690.62" y="-661.33" font-family="Times,serif" font-size="14.00">playground</text>
+<polygon fill="none" stroke="black" points="741,-684 643,-684 643,-648 741,-648 741,-684"/>
+<text text-anchor="middle" x="692" y="-662.3" font-family="Times,serif" font-size="14.00">playground</text>
 </g>
 <!-- 28&#45;&gt;26 -->
 <g id="edge37" class="edge">
 <title>28&#45;&gt;26</title>
-<path fill="none" stroke="black" d="M674.56,-647.7C666.92,-639.47 657.65,-629.48 649.23,-620.42"/>
-<polygon fill="black" stroke="black" points="651.91,-618.16 642.54,-613.21 646.78,-622.92 651.91,-618.16"/>
+<path fill="none" stroke="black" d="M675.69,-647.7C667.69,-639.22 657.93,-628.86 649.18,-619.58"/>
+<polygon fill="black" stroke="black" points="651.53,-616.98 642.13,-612.1 646.44,-621.78 651.53,-616.98"/>
 </g>
 <!-- 29 -->
 <g id="node30" class="node">
 <title>29</title>
-<polygon fill="none" stroke="black" points="566.88,-252 492.38,-252 492.38,-216 566.88,-216 566.88,-252"/>
-<text text-anchor="middle" x="529.62" y="-229.32" font-family="Times,serif" font-size="14.00">stresser</text>
+<polygon fill="none" stroke="black" points="567.5,-252 492.5,-252 492.5,-216 567.5,-216 567.5,-252"/>
+<text text-anchor="middle" x="530" y="-230.3" font-family="Times,serif" font-size="14.00">stresser</text>
 </g>
 <!-- 29&#45;&gt;7 -->
 <g id="edge38" class="edge">
 <title>29&#45;&gt;7</title>
-<path fill="none" stroke="black" d="M529.62,-215.7C529.62,-208.41 529.62,-199.73 529.62,-191.54"/>
-<polygon fill="black" stroke="black" points="533.13,-191.62 529.63,-181.62 526.13,-191.62 533.13,-191.62"/>
+<path fill="none" stroke="black" d="M530,-215.7C530,-207.98 530,-198.71 530,-190.11"/>
+<polygon fill="black" stroke="black" points="533.5,-190.1 530,-180.1 526.5,-190.1 533.5,-190.1"/>
 </g>
 </g>
 </svg>

github-actions[bot] avatar Nov 15 '23 22:11 github-actions[bot]

The chat signing system allows servers to be modify chat messages.

On my Paper based server I'm using a chat modification plugin called Carbon which can produce the following output (once configured properly) image

Would this PR support it? I know I would need to make my own code to make the formatting I want.

Also, has this PR been tested behind a proxy like Velocity? If not, I can do the testing.

ajh123 avatar Jul 06 '24 08:07 ajh123

On my Paper based server I'm using a chat modification plugin called Carbon which ... Would this PR support it? I know I would need to make my own code to make the formatting I want.

I think I've found my answer.

On this line https://github.com/guac42/valence/blob/7ac1f2b45c22a6b94da5bd8acbce55b88910caae/examples/chat.rs#L99 would I just need to modify what sender_name and message are based on what I want?

Edit:

send_chat_message should probably have another version that supports Text objects. This will use the Chat Formatting section of the Player Chat Message packet. Not sure which chat type Carbon uses.

ajh123 avatar Jul 06 '24 08:07 ajh123