diff --git a/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/README.md b/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/README.md
new file mode 100644
index 000000000000..141473c10f93
--- /dev/null
+++ b/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/README.md
@@ -0,0 +1 @@
+[见主文档](/projects/1.20/assets/modrinth-mediatransport/mediatransport)
\ No newline at end of file
diff --git a/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/lang/en_us.flatten.json5 b/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/lang/en_us.flatten.json5
new file mode 100644
index 000000000000..006f1a5db9ea
--- /dev/null
+++ b/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/lang/en_us.flatten.json5
@@ -0,0 +1,369 @@
+{
+ mediatransport: {
+ book: {
+ category: {
+ interop: {
+ figura: {
+ "": "Figura",
+ desc: "It appears that these constructs called $(thing)avatars/$ are quite powerful, if a bit annoying to work with."
+ }
+ }
+ },
+ patterns: {
+ figura: {
+ "": "Transport Patterns",
+ intro: "",
+ send_fsb: "Sends the iota on the top of the stack into the ether to be received by my current avatar. Can fail for $(l:hexcasting:interop/figura/mishaps)various reasons$(/l). Always costs a fixed 1 'sending power.'",
+ send_other: "Sends the iota on the top of the stack to be received by the player second from the top of the stack. It seems to have a separate receiver from the other one. Usually costs 2 'sending power', but this could be different depending on the server configuration.",
+ recv_fsb: "Retrieves the next iota from the $(thing)inbound queue/$, or $(l:hexcasting:interop/figura/mishaps)mishaps$(/l) if the queue is empty.",
+ check_queue: "Queries the number of iotas in the queue.",
+ check_rate_limit: "Queries the amount of 'sending power' remaining.",
+ send_server_info_a: "Asks Nature to send information about its preferences to my current avatar. Costs 1 'spending power'. See $(l:https://penguinencounter.github.io/mediatransport/v/latest/main/en_us/mediatransport_virtual/protocol)the online protocol documentation$(/l) for details.",
+ send_server_info_b: "Asks Nature to send information about its preferences to my current avatar. Costs 1 'spending power'. See $(l:hexcasting:mediatransport_virtual/protocol)the protocol documentation$(/l) for details.",
+ },
+ },
+ interop: {
+ figura: {
+ about: {
+ "": "Transports",
+ "1": "I appear to have discovered the notes of a collective of people who have also discovered the techniques of _Hexcasting. I've copied down what I could understand of the notes, but the last part is so filled with jargon as to be incomprehensible. Perhaps I need to understand more about the artistry of these '$(thing)avatars/$' I see mentioned throughout?",
+ "2": "It appears that Nature created new patterns for communicating specifically with $(thing)avatars/$ after the artists used more primitive methods to communicate rapidly. As seems to be standard, Nature has twisted the appearance of the now-familiar iotas in exchange for this increased efficiency and throughput; they appear as boxes and random symbols by my eyes.",
+ "3": "The $(thing)avatars/$ and their artists seem to not have this problem, and have figured out how to decode the mess. Here's the rest of their notes for reference. To be honest, I don't understand much of what's going on here.",
+ "A": "We've discovered (created?) a few new spells. They facilitate direct communication between avatars and hexes; no more getting kicked for spam!$(br2)Some of the more data-oriented of us have decoded the format. The entire thing is byte-aligned and uses $(#8bf)buffers/$ for data transfer. (that means we have to remember to close them!)",
+ "B": "Based on what we've seen, each iota starts with a single-byte $(#8bf)type/$ followed by zero or more bytes of $(#8bf)data/$. All multibyte forms are big endian. (that's the default for the Buffer read methods)$(br2)",
+ "C1": "Unfortunately, due to annoying restrictions with this unwieldy notebook, it's difficult to express the format in more detail here. Perhaps it would be easier in a $(l:https://penguinencounter.github.io/mediatransport/v/latest/main/en_us/mediatransport_virtual/protocol)more flexible medium$(/l)?",
+ "C2": "The format in its entirety is described here: $(l:hexcasting:mediatransport_virtual/protocol)Iota Transport Protocol$(/l)",
+ "D": "Moreover, Nature doesn't take kindly to being asked to send megabytes of data at a time; to prevent such (ab)use, there is a system of so-called \"sending power\". It refills quite rapidly (under normal circumstances), and every transmission-related action consumes some.",
+ "E": "When you run out of \"sending power\", trying to submit more iota will result in a mishap. To avoid running into the limit, $(l:hexcasting:patterns/figura#mediatransport:check_rate_limit)Quota's Reflection$(/l) can be useful."
+ },
+ mishaps: {
+ "": "Transport Mishaps",
+ "1": "Various things can go wrong when interacting with the esoteric language of avatar transports.",
+ // first italic part is the same as first part of the mishap text
+ init_fail: "$(italic)Figura server isn't initialized .../$$(br2)Occurs if the server is misconfigured or if this universe is an \"integrated server\". Causes grey sparks and a general feeling of disappointment.",
+ bad_type: "$(italic)can't send ... because that type of iota can't be sent/$$(br2)That type of iota can't be submitted to Nature for transmission. Causes black sparks.$(br2)$(italic)Need support for an iota type? Ask on $(l:https://github.com/penguinencounter/mediatransport/issues)GitHub$(/l)!/$",
+ corrupted: "$(italic)can't send ... because it's corrupted or ill-formed/$$(br2)Something has gone horribly wrong. Causes black sparks, and probably should be reported on the relevant GitHub issue tracker.",
+ matrix_too_large: "$(italic)can't send ... because it's too big$(br)can't send ... because it has too many rows$(br)can't send ... because it has too many columns/$$(br2)The matrix you're trying to send has too many entries to be sent, or more than 255 rows or columns. Causes black sparks.",
+ iota_too_large: "$(italic)can't send: calculated size at least .../$$(br2)The iota you're sending is larger than the maximum allowed size. Causes black sparks.$(br2)$(italic)Note: Server administrators can change the limit in the config./$",
+ iota_too_large_inter: "$(italic)can't send to other players: calculated size at least .../$$(br2)The iota you're sending to another player's avatar is larger than the maximum allowed size. Causes black sparks.$(br2)$(italic)Note: Server administrators can change the limit in the config./$",
+ radio_silence: "Tried to accept an iota, but there's nothing to accept (i.e. the queue is empty.) Causes white sparks and the screams of $(k)the tormented minds/$ to echo within my ears.",
+ rate_limit_exceeded: "I ran out of 'sending power'. Perhaps I should consider consolidating usages of Submit Iota? Causes orange sparks and the sound of something breaking.",
+ "2": "it looks like most of these errors only occur when $(italic)sending/$ (well, \"submitting\") data from within nature's domain. nature seems to be much more lenient in accepting bad data... in that it doesn't crash anything and instead outputs its favorite flavor of not-error: garbage!$(br)unfortunately this makes it hard to determine why data isn't making it across the boundary. we've compiled a list of reasons to look out for:",
+ "3": "- data is of a type (that's the first byte) that nature has no representation for$(br)- the transmission is missing some data at the end$(br)- the data is too large (seems like this could be different limit than the one going in the other direction...)$(br)- a variant of the above: the same matrix size restrictions apply (though it's impossible to have too many rows or columns, the total area could still be too much)",
+ "4": "also note that lists can also partially fail to transfer, leading to the entire decoder potentially derailing and interpreting types as data and vice versa. good luck!"
+ }
+ }
+ },
+ pluralizations: {
+ // 0, 1, "" (any)
+ byte: {
+ "1": "%s byte",
+ "": "%s bytes"
+ }
+ },
+ channels: {
+ "": "FSB Channels",
+ "A1": "These were hastily scribbled in the margins of something... I can't quite remember. Odd.",
+ "A2": "$(li)$(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l) - transport_received/$$(li)$(l:hexcasting:patterns/figura#mediatransport:send_other)Submit Iota II$(/l) - transport_external_received/$$(li)$(l:hexcasting:patterns/figura#mediatransport:recv_fsb)Accept Iota$(/l) - transport_send",
+ "og": "How to shout at Nature correctly (and vice versa)",
+ "B1": "... oh, I remember now!",
+ doc: {
+ "1": "Data sent via Submit Iota is sent to server_packets.transport_received, like so:",
+ "code1": "\
+ .function server_packets.transport_received(data)\n\
+ . data:close()\n\
+ .end\n\
+ ",
+ "2": "Data from other casters via Submit Iota II are sent to a different channel: server_packets.transport_external_received",
+ "code2": "\
+ .function server_packets.transport_external_received(data)\n\
+ . data:close()\n\
+ .end\n\
+ ",
+ "3": "Finally, to send data, use :sendPacket with \"transport_send\":",
+ "code3": "\
+ .server_packets:sendPacket(\"transport_send\", buffer)\n\
+ .buffer:close()\n\
+ "
+ }
+ },
+ protocol: {
+ "": "Iota Transport Protocol",
+ "1": "Ah, the freedom! I've drawn up some diagrams of the format.",
+ // text in {curly brackets} are keywords. Don't translate the text inside.
+ // btw this section uses HTML
+ "notice": "This documentation is for protocol {sym:protocol_version} 1.",
+ "intro1": "As previously described, an iota consists of a single-byte {symdef:type} followed by some amount of {symr:data}, depending on the type.",
+ "intro2": "Each iota type has a different {sym:type} value and has a different format for {symr:data}.",
+ stdtypes: "Built-in types",
+ garbage: {
+ "": "ff: Garbage",
+ "description": "All these types have no data. Also, since Garbage is used to represent decoding failures, it's generally a bad idea to create it on purpose.",
+ },
+ truefalse: {
+ "": "02: True and 03: False",
+ },
+ "null": {
+ "": "04: Null",
+ },
+ double: {
+ "": "05: Double",
+ "description": "Finally, something interesting! Hexcasting uses IEEE 754 double-width floats (that's 8 bytes, 64 bits), so that's what's being used here for {symdef:double_value}."
+ },
+ pattern: {
+ "": "06: Pattern",
+ "description": "In honor of Hexxy, patterns are type 6. They're a bit complicated:",
+ "1": "First is a byte representing the {symdef:dir}. This is based on some internal representation, and appears to be as follows: 0 = north east, 1 = east, 2 = south east, 3 = south west, 4 = west, and 5 = north west.",
+ "2": "Next is a four-byte integer holding the number of angles in the pattern (effectively, strokes minus 1, or the {symdef:pattern_len})",
+ "3": "Following that are the {symdef:angles}, each 1 byte. Once again this appears to be based on some internal representation, as follows: 0 = forward, 1 = right, 2 = right back, 3 = back, 4 = left back, and 5 = left."
+ },
+ vec3: {
+ "": "07: Vector",
+ "description": "A vector is three doubles in sequence - {symdef:vec_x}, {symdef:vec_y}, and {symdef:vec_z}."
+ },
+ list: {
+ "": "08: List",
+ "description": "Lists are the primary structuring tool that Hexcasting has, and are similar to patterns - first is a four-byte {symdef:list_len}, followed by that many iota of any type.",
+ "warning": "It seems that avatars being able to bring entire structures of iota into being is a bit too much for Nature (...well, by default); you may receive garbage in return"
+ },
+ moreiotas: "MoreIotas types",
+ string: {
+ "": "01: String",
+ "description": "Strings, like the rest of the variable-length iotas, have a 4-byte {symdef:str_len} followed by the data (in this case, the {symdef:string}.) Strings are expected to be encoded in UTF-8."
+ },
+ matrix: {
+ "": "40: Matrix",
+ "description": "Matrices are two-dimensional arrays of doubles.",
+ "1": "First is a single byte for the number of {symdef:rows}, followed by another byte for the number of {symdef:cols}.",
+ "2": "This is followed by the {symdef:matrix_contents} of the matrix - one double for each entry. Each row is written out in sequence (ex. for a 2 by 2 matrix, the order would be row 1 column 1, followed by row 1 column 2, and then row 2 after that)"
+ },
+ hexpose: "Hexpose types",
+ text: {
+ "": "50: Text",
+ "description": "It appears that this format is not suitable for communicating the decorative properties of text (also called 'display') iota. Nevertheless, the actual text content can be transmitted. Text iota have the same format as strings:"
+ },
+ meta: "Non-iotas",
+ meta_intro: "These don't seem to represent iota at all! They can't be sent to Nature and only appear under special circumstances.",
+ server_info: {
+ "": "fe: Configuration Data",
+ "description": "This glob of information is Nature's repsonse to Query Configuration.",
+ "1": "First is the protocol's {symdef:protocol_version} as a two-byte 'short'. This documentation is written for version 1.",
+ "2": "Next is the maximum amount of data that can be sent with Submit Iota, in bytes.",
+ "3": "That is followed by the maximum amount of data that can be sent with Submit Iota II...",
+ "4": "and the maximum amount of data that can be received from an avatar.",
+ "5": "That's followed by the maximum amount of 'sending power' that can be held at a time, as a double precision floating point...",
+ "6": "and how much 'sending power' is regained per tick...",
+ "7": "and finally, how much 'sending power' Submit Iota II costs."
+ },
+ // that's the end of the HTML
+ },
+ api: {
+ "": "Figura API Documentation",
+ "1": "This was attached as a supplementary document to the other notes I found.",
+ // We are once again in HTML land
+ intro1: "It seems that the avatar side of the communication isn't without complexity, either - due to a complete lack of wiki maintenance ...less than optimal bookkeeping practices, the only source of information about the systems to interact with Nature seem to be the built-in documentation, which leaves much to be desired.",
+ intro2: "(If one is curious about that, it seems to be available via the incantation /figura docs globals server_packets and its various branches.)",
+ intro3: "To act as reference material in the meantime, I have created this supplementary document, which should hopefully provide the reader with a reasonable understanding of how the API works.",
+ overview: {
+ "": "Overview of server_packets",
+ "1": "Internally called ServerPacketsAPI, server_packets functions very similarly to the much more familiar pings, with a few slight differences.",
+ "2": "To receive data, use the function definition syntax you're probably familiar with:",
+ // this is a codeblock! keep the '\n\' on the right of each line, as well as the '.' at the beginning.
+ // probably don't translate code
+ "code1": "\
+ .function server_packets.packet_id(data)\n\
+ . -- Handle data here!\n\
+ .end\n\
+ ",
+ "3": "Compared to pings, server_packets receivers always have exactly one parameter, through which a {sym:Buffer} is passed containing the packet's data.",
+ "4": "Make sure to close the {sym:Buffer} you are given! If you don't, the buffer slot will continue to be considered \"used\" and you will eventually run out of buffers (from my research, most people are unaware there is a limit on buffer count at all, but it exists as part of the permissions system and this is one of the easiest ways to have latent bugs.)",
+ "5": "The other main difference from pings is that sending data is explicit and not activated by calling the receiver function - that means calling server_packets.packet_id() does not send anything. To send packets, use server_packets:sendPacket(id, data), where id is a string and data is a Buffer.",
+ "6": "Make sure to rewind the Buffer before sending it.",
+ },
+ buffers: {
+ "": "Quick Introduction to {symdef:Buffer}s",
+ "h1": "The canonical documentation for Buffers is accessible via the incantation /figura docs globals data Buffer.",
+ "h2": "It's also available on FIGS or the Figura Wiki.",
+ "1": "Buffers provide a convenient interface for reading structured data like the one Nature provides. It's almost like it's based on something else...",
+ manage: {
+ new: {
+ "": "Creating new buffers: data:createBuffer()",
+ "1": "To create a new buffer, use data:createBuffer(), which returns a new Buffer object.",
+ "2": "You can also specify the initial allocated size by providing it as an argument to createBuffer, but this is not required unless you're working under really tight permissions constraints as Figura will auto-expand buffers by default.",
+ },
+ close: {
+ "": "Cleaning up after yourself: :close()",
+ "1": "As mentioned in the warning callout above, there is a limit on the number of buffers you can have, and it's tied to the permission system.",
+ "2": "On Default, the limit is 4 buffers.",
+ "3": "On High, the limit is 16 buffers.",
+ "4": "On MAX, the limit is 32 buffers.",
+ "5": "To free up a buffer, call close() on it. This will render the contents unusable."
+ },
+ code1: "\
+ .local buf = data:createBuffer()\n\
+ .-- (later...)\n\
+ .buf:close()\n\
+ ",
+ setPosition: {
+ "": "Moving the cursor around: :setPosition(pos)",
+ "1": "Buffers function with a 'cursor' that moves around the data as you read and write to it.",
+ "2": "Each time data is read or written, that action is taken at the position of the cursor and the cursor is automatically advanced to the next byte. This makes it convenient to read or write many values in sequence.",
+ "3": "However, it is still useful to be able to move the cursor around manually - notably, to read back the data written to a buffer, the cursor has to be moved (\"rewound\") back to position 0:",
+ code: "\
+ .buf:writeByte(5)\n\
+ .buf:writeDouble(3.14159)\n\
+ .buf:setPosition(0) -- move back to the beginning\n\
+ "
+ },
+ },
+ write: {
+ "": "Writing Data",
+ "hat": "This section only discusses types that Nature cares about. Other types are supported by buffers - to see that, go to the canonical documentation.",
+ "1": "There are methods to write data in various formats to a buffer. They all move the cursor to the end of the data written, so calling them multiple times in sequence will concatenate the data.",
+ "2": "For things described as 'x-byte integers', use these names:",
+ "3": "For 'doubles', use:",
+ methods: {
+ write: ":write(n): 1 byte, such as {sym:type}, {sym:dir} for patterns, and {sym:rows} and {sym:cols} for matrices.",
+ writeInt: ":writeInt(n): 4 bytes, which is primarily used to describe the length of things",
+ writeDouble: ":writeDouble(n): 8 bytes, used for both the {sym:double_value} of numbers and the {sym:vec_x}, {sym:vec_y}, and {sym:vec_z} of vectors."
+ }
+ },
+ read: {
+ "": "Reading Data",
+ "1": "Similar to writing data, Buffers are versatile in what they can read. Each read method also similarily moves the cursor to the end of the data read.",
+ methods: {
+ read: ":read(): 1 byte, such as {sym:type}, {sym:dir} for patterns, and {sym:rows} and {sym:cols} for matrices.",
+ readShort: ":readShort(): 2 bytes - the protocol {sym:protocol_version}",
+ readInt: ":readInt(): 4 bytes, usually lengths but also quite a few configuration parameters",
+ readDouble: ":readDouble(): 8 bytes, used for both the {sym:double_value} of numbers and the {sym:vec_x}, {sym:vec_y}, and {sym:vec_z} of vectors, as well as the sending power-related configuration values."
+ }
+ },
+ },
+ // End of HTML
+ },
+ // here's a bunch of things that the renderer puts together
+ // to form all of those symbols and markup
+ symbols: {
+ type: "type",
+ data: "data",
+ value: "value",
+ dir: "dir", // direction
+ length: "length", // length
+ angles: "angles",
+ x: "x",
+ y: "y",
+ z: "z",
+ iotas: "iotas",
+ string: "string",
+ contents: "contents",
+ rows: "rows",
+ cols: "cols", // columns
+ rowscols: "rows*cols",
+ version: "version",
+ max_send: "max_send",
+ max_inter_send: "max_inter",
+ max_recv: "max_recv",
+ max_power: "max_power",
+ power_regen_rate: "power_regen_rate",
+ inter_cost: "inter_cost",
+ Buffer: "Buffer", // Don't translate - Figura type
+ },
+ admin: {
+ // These entries are only rendered in hexdoc, so we don't have to worry
+ // about not overflowing the page!
+ fsb: {
+ "": "About FSB",
+ "1": "mediatransport relies on $(n)Figura Server Backend/$ (also called $(n)FSB/$) to function. FSB is a feature in the development builds of Figura for 1.20.1 that enables hosting avatars and pings on the server itself instead of relying on the global backend.",
+ "2": "FSB $(n)doesn't work on Singleplayer/$ or LAN worlds, so you might want to host a dedicated server to test your hexes out. Thanks for playing our addon! :)$(br2)$(l:https://github.com/penguinencounter/Figura/releases/tag/figura-fsb-placeholder)Figura FSB builds on GitHub$(/l)",
+ },
+ config: {
+ "": "mediatransport config",
+ "1": "mediatransport has various server configuration options to limit what data can be sent between avatars and casting environments.",
+ maxSize: {
+ "": "Size Restrictions",
+ "1": "All values in bytes.$(br2)$(n)maximumSendSize/$: maximum amount of data that can be sent through $(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l).$(br2)$(n)maximumInterSendSize/$: maximum amount of data that can be sent through $(l:hexcasting:patterns/figura#mediatransport:send_other)Submit Iota II$(/l).$(br2)$(n)maximumRecvSize/$: maximum amount of data that can be received from Figura. If this is exceeded, garbage will be pushed into the queue instead of the actual data.$(br2)$(n)matrixMaxArea/$: MoreIotas only; sets the maximum matrix area (width * height) that can be sent or received, separately from other restrictions and the maximum row/column count of 255."
+ },
+ filterIntro: {
+ "": "Filters",
+ "1": "mediatransport has three separate $(italic)filter/$ configuration sets for controlling what types of iota can be sent. Each one has a $(n)mode/$ and a $(n)list of entries/$.$(br2)The $(n)mode/$ can either be $(bold)\"Block\"/$ (forbids certain types, 'blocklist') or $(bold)\"Allow\"/$ (only allows certain types, 'allowlist').$(br2)The list contains the list of resource locations to apply the filter with. For example, to disallow sending lists, set the $(n)mode/$ to $(bold)\"Block\"/$ and the list to $(bold)[\"hexcasting:list\"]/$.$(br2)Note that allowing an iota type won't magically make it sendable if mediatransport lacks encoders or decoders for that type."
+ },
+ sendFilters: {
+ "": "Sending Filters",
+ "1": "Just like the size limits, there are separate filters for $(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l) and $(l:hexcasting:patterns/figura#mediatransport:send_other)Submit Iota II$(/l).$(br2)$(n)sendFilter/$ and $(n)sendFilterMode/$ apply to Submit Iota. $(n)interSendFilter/$ and $(n)interSendFilterMode/$ apply to Submit Iota II.$(br2)If an iota is blocked by these filters, it will cause an 'bad type' mishap on the relevant iota (even if it's nested in a list.)"
+ },
+ recvFilters: {
+ "": "Receiving Filters",
+ "1": "$(n)recvFilter/$ and $(n)recvFilterMode/$ control what types of iota can be received from Figura.$(br2)Any iota that are blocked by this filter are replaced with Garbage, but any containing iota will be unaffected. (ex. a list containing an invalid iota will be received as a list containing garbage instead, provided lists are allowed.)"
+ },
+ ratelimits: {
+ "": "Rate Limits",
+ "1": "'Sending power' is really just a number that goes up over time until it hits a limit for each player. The system is balance around one usage of $(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l) consuming 1.00 'power'.$(br2)$(li)$(n)rateLimitChargePerTick/$ controls how quickly 'power' recharges. The default of 1.0 means that on average a player can only use Submit Iota once every tick./$$(li)$(n)rateLimitMaxValue/$ is the maximum 'power' that players can hold on to at once. Setting this below 1 means that Submit Iota will always fail. Setting this greater than 1 lets players send in 'bursts' without running into the rate limit as long as their overall rate remains below the limit./$$(li)$(n)interSendConstMultiplier/$ lets you configure how much Submit Iota II costs relative to Submit Iota. Because Submit Iota costs 1, this is effectively the price of Submit Iota II"
+ },
+ }
+ },
+ figura_see_also_1: "I've cataloged the rest of the details in these entries.",
+ see_also: "See Also",
+ index: {
+ "": "Transports: Index",
+ desc: "An index of all the entries related to transports and Figura.",
+ },
+ blank: "$(#b0b0b0)this page left blank for layout purposes/$",
+ blank_dark: "$(#504060)this page left blank for layout purposes/$",
+ },
+ // "can't send (iota) because..."
+ not_sendable: {
+ bad_type: "that type of iota can't be sent",
+ corrupt: "it's corrupted or ill-formed",
+ matrix_too_big: "it's too big",
+ matrix_too_many_rows: "it has too many rows (max 255)",
+ matrix_too_many_cols: "it has too many columns (max 255)",
+ },
+ radio_silence_options: {
+ // translators: good luck, sorry (you can replace all of these with the 'help' one if you want)
+ crickets: "*crickets*",
+ ellipsis: "......",
+ help: "Receiving queue is empty",
+ eof: "java.util.NoSuchElementException: collection is empty",
+ insanity: "You hear whispering, but you can't make it out.",
+ informal: "there's nothing here.",
+ },
+ mishap_names: {
+ init_fail: "Transport Init Failure",
+ bad_type: "Not a Submittable Iota",
+ corrupted: "Corrupt Iota",
+ matrix_too_large: "Matrix Too Large",
+ iota_too_large: "Send Too Large",
+ iota_too_large_inter: "Send Other Too Large",
+ radio_silence: "Nothing to Accept",
+ rate_limit_exceeded: "Too Fast",
+ },
+ },
+ hexcasting: {
+ action: {
+ "mediatransport:": {
+ send_fsb: "Submit Iota",
+ send_other: "Submit Iota II",
+ recv_fsb: "Accept Iota",
+ check_queue: "Semaphore's Reflection",
+ check_rate_limit: "Quota's Reflection",
+ send_server_info: "Query Configuration",
+ },
+ // use this to add shortened versions of pattern names if the full name won't fit in the ingame book
+ // you don't need to add an entry for every pattern - the above value will be used as a default
+ book: {
+ "mediatransport:": {
+ check_queue: "Semaphore's Refl.",
+ },
+ },
+ },
+ mishap: {
+ not_sendable: "can't send %s",
+ not_sendable_ex: "can't send %s because %s",
+ too_large_to_send: "can't send: calculated size at least %s B, but server configured limit is %s B",
+ too_large_to_send_inter: "can't send to other players: calculated size at least %s B, but server configured limit is %s B",
+ fsb_not_initialized: "Figura server isn't initialized (tell your local admin to use a dedicated server and install FSB)",
+ radio_silence: "%s", // see mediatransport.radio_silence_options
+ rate_limit_exceeded: "Sending data too fast (%s required, %s available; +%s/tick, max %s)",
+ }
+ },
+}
\ No newline at end of file
diff --git a/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/packer-policy.json b/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/packer-policy.json
new file mode 100644
index 000000000000..6d43c70a2e79
--- /dev/null
+++ b/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport/packer-policy.json
@@ -0,0 +1,6 @@
+[
+ {
+ "type": "indirect",
+ "source": "projects/1.20/assets/modrinth-mediatransport/mediatransport"
+ }
+]
\ No newline at end of file
diff --git a/projects/1.20/assets/modrinth-mediatransport/mediatransport/README.md b/projects/1.20/assets/modrinth-mediatransport/mediatransport/README.md
new file mode 100644
index 000000000000..bafeb4eba552
--- /dev/null
+++ b/projects/1.20/assets/modrinth-mediatransport/mediatransport/README.md
@@ -0,0 +1,16 @@
+### 总概
+
+```mermaid
+flowchart LR
+ 1.20.1 -->|indirect| 1.20.1-fabric
+```
+
+```
+1.20.1
+ └── 1.20.1-fabric
+```
+
+### 链接区域
+
+- [1.20.1](/projects/1.20/assets/modrinth-mediatransport/mediatransport)
+- [1.20.1-fabric](/projects/1.20-fabric/assets/modrinth-mediatransport/mediatransport)
\ No newline at end of file
diff --git a/projects/1.20/assets/modrinth-mediatransport/mediatransport/lang/en_us.flatten.json5 b/projects/1.20/assets/modrinth-mediatransport/mediatransport/lang/en_us.flatten.json5
new file mode 100644
index 000000000000..006f1a5db9ea
--- /dev/null
+++ b/projects/1.20/assets/modrinth-mediatransport/mediatransport/lang/en_us.flatten.json5
@@ -0,0 +1,369 @@
+{
+ mediatransport: {
+ book: {
+ category: {
+ interop: {
+ figura: {
+ "": "Figura",
+ desc: "It appears that these constructs called $(thing)avatars/$ are quite powerful, if a bit annoying to work with."
+ }
+ }
+ },
+ patterns: {
+ figura: {
+ "": "Transport Patterns",
+ intro: "",
+ send_fsb: "Sends the iota on the top of the stack into the ether to be received by my current avatar. Can fail for $(l:hexcasting:interop/figura/mishaps)various reasons$(/l). Always costs a fixed 1 'sending power.'",
+ send_other: "Sends the iota on the top of the stack to be received by the player second from the top of the stack. It seems to have a separate receiver from the other one. Usually costs 2 'sending power', but this could be different depending on the server configuration.",
+ recv_fsb: "Retrieves the next iota from the $(thing)inbound queue/$, or $(l:hexcasting:interop/figura/mishaps)mishaps$(/l) if the queue is empty.",
+ check_queue: "Queries the number of iotas in the queue.",
+ check_rate_limit: "Queries the amount of 'sending power' remaining.",
+ send_server_info_a: "Asks Nature to send information about its preferences to my current avatar. Costs 1 'spending power'. See $(l:https://penguinencounter.github.io/mediatransport/v/latest/main/en_us/mediatransport_virtual/protocol)the online protocol documentation$(/l) for details.",
+ send_server_info_b: "Asks Nature to send information about its preferences to my current avatar. Costs 1 'spending power'. See $(l:hexcasting:mediatransport_virtual/protocol)the protocol documentation$(/l) for details.",
+ },
+ },
+ interop: {
+ figura: {
+ about: {
+ "": "Transports",
+ "1": "I appear to have discovered the notes of a collective of people who have also discovered the techniques of _Hexcasting. I've copied down what I could understand of the notes, but the last part is so filled with jargon as to be incomprehensible. Perhaps I need to understand more about the artistry of these '$(thing)avatars/$' I see mentioned throughout?",
+ "2": "It appears that Nature created new patterns for communicating specifically with $(thing)avatars/$ after the artists used more primitive methods to communicate rapidly. As seems to be standard, Nature has twisted the appearance of the now-familiar iotas in exchange for this increased efficiency and throughput; they appear as boxes and random symbols by my eyes.",
+ "3": "The $(thing)avatars/$ and their artists seem to not have this problem, and have figured out how to decode the mess. Here's the rest of their notes for reference. To be honest, I don't understand much of what's going on here.",
+ "A": "We've discovered (created?) a few new spells. They facilitate direct communication between avatars and hexes; no more getting kicked for spam!$(br2)Some of the more data-oriented of us have decoded the format. The entire thing is byte-aligned and uses $(#8bf)buffers/$ for data transfer. (that means we have to remember to close them!)",
+ "B": "Based on what we've seen, each iota starts with a single-byte $(#8bf)type/$ followed by zero or more bytes of $(#8bf)data/$. All multibyte forms are big endian. (that's the default for the Buffer read methods)$(br2)",
+ "C1": "Unfortunately, due to annoying restrictions with this unwieldy notebook, it's difficult to express the format in more detail here. Perhaps it would be easier in a $(l:https://penguinencounter.github.io/mediatransport/v/latest/main/en_us/mediatransport_virtual/protocol)more flexible medium$(/l)?",
+ "C2": "The format in its entirety is described here: $(l:hexcasting:mediatransport_virtual/protocol)Iota Transport Protocol$(/l)",
+ "D": "Moreover, Nature doesn't take kindly to being asked to send megabytes of data at a time; to prevent such (ab)use, there is a system of so-called \"sending power\". It refills quite rapidly (under normal circumstances), and every transmission-related action consumes some.",
+ "E": "When you run out of \"sending power\", trying to submit more iota will result in a mishap. To avoid running into the limit, $(l:hexcasting:patterns/figura#mediatransport:check_rate_limit)Quota's Reflection$(/l) can be useful."
+ },
+ mishaps: {
+ "": "Transport Mishaps",
+ "1": "Various things can go wrong when interacting with the esoteric language of avatar transports.",
+ // first italic part is the same as first part of the mishap text
+ init_fail: "$(italic)Figura server isn't initialized .../$$(br2)Occurs if the server is misconfigured or if this universe is an \"integrated server\". Causes grey sparks and a general feeling of disappointment.",
+ bad_type: "$(italic)can't send ... because that type of iota can't be sent/$$(br2)That type of iota can't be submitted to Nature for transmission. Causes black sparks.$(br2)$(italic)Need support for an iota type? Ask on $(l:https://github.com/penguinencounter/mediatransport/issues)GitHub$(/l)!/$",
+ corrupted: "$(italic)can't send ... because it's corrupted or ill-formed/$$(br2)Something has gone horribly wrong. Causes black sparks, and probably should be reported on the relevant GitHub issue tracker.",
+ matrix_too_large: "$(italic)can't send ... because it's too big$(br)can't send ... because it has too many rows$(br)can't send ... because it has too many columns/$$(br2)The matrix you're trying to send has too many entries to be sent, or more than 255 rows or columns. Causes black sparks.",
+ iota_too_large: "$(italic)can't send: calculated size at least .../$$(br2)The iota you're sending is larger than the maximum allowed size. Causes black sparks.$(br2)$(italic)Note: Server administrators can change the limit in the config./$",
+ iota_too_large_inter: "$(italic)can't send to other players: calculated size at least .../$$(br2)The iota you're sending to another player's avatar is larger than the maximum allowed size. Causes black sparks.$(br2)$(italic)Note: Server administrators can change the limit in the config./$",
+ radio_silence: "Tried to accept an iota, but there's nothing to accept (i.e. the queue is empty.) Causes white sparks and the screams of $(k)the tormented minds/$ to echo within my ears.",
+ rate_limit_exceeded: "I ran out of 'sending power'. Perhaps I should consider consolidating usages of Submit Iota? Causes orange sparks and the sound of something breaking.",
+ "2": "it looks like most of these errors only occur when $(italic)sending/$ (well, \"submitting\") data from within nature's domain. nature seems to be much more lenient in accepting bad data... in that it doesn't crash anything and instead outputs its favorite flavor of not-error: garbage!$(br)unfortunately this makes it hard to determine why data isn't making it across the boundary. we've compiled a list of reasons to look out for:",
+ "3": "- data is of a type (that's the first byte) that nature has no representation for$(br)- the transmission is missing some data at the end$(br)- the data is too large (seems like this could be different limit than the one going in the other direction...)$(br)- a variant of the above: the same matrix size restrictions apply (though it's impossible to have too many rows or columns, the total area could still be too much)",
+ "4": "also note that lists can also partially fail to transfer, leading to the entire decoder potentially derailing and interpreting types as data and vice versa. good luck!"
+ }
+ }
+ },
+ pluralizations: {
+ // 0, 1, "" (any)
+ byte: {
+ "1": "%s byte",
+ "": "%s bytes"
+ }
+ },
+ channels: {
+ "": "FSB Channels",
+ "A1": "These were hastily scribbled in the margins of something... I can't quite remember. Odd.",
+ "A2": "$(li)$(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l) - transport_received/$$(li)$(l:hexcasting:patterns/figura#mediatransport:send_other)Submit Iota II$(/l) - transport_external_received/$$(li)$(l:hexcasting:patterns/figura#mediatransport:recv_fsb)Accept Iota$(/l) - transport_send",
+ "og": "How to shout at Nature correctly (and vice versa)",
+ "B1": "... oh, I remember now!",
+ doc: {
+ "1": "Data sent via Submit Iota is sent to server_packets.transport_received, like so:",
+ "code1": "\
+ .function server_packets.transport_received(data)\n\
+ . data:close()\n\
+ .end\n\
+ ",
+ "2": "Data from other casters via Submit Iota II are sent to a different channel: server_packets.transport_external_received",
+ "code2": "\
+ .function server_packets.transport_external_received(data)\n\
+ . data:close()\n\
+ .end\n\
+ ",
+ "3": "Finally, to send data, use :sendPacket with \"transport_send\":",
+ "code3": "\
+ .server_packets:sendPacket(\"transport_send\", buffer)\n\
+ .buffer:close()\n\
+ "
+ }
+ },
+ protocol: {
+ "": "Iota Transport Protocol",
+ "1": "Ah, the freedom! I've drawn up some diagrams of the format.",
+ // text in {curly brackets} are keywords. Don't translate the text inside.
+ // btw this section uses HTML
+ "notice": "This documentation is for protocol {sym:protocol_version} 1.",
+ "intro1": "As previously described, an iota consists of a single-byte {symdef:type} followed by some amount of {symr:data}, depending on the type.",
+ "intro2": "Each iota type has a different {sym:type} value and has a different format for {symr:data}.",
+ stdtypes: "Built-in types",
+ garbage: {
+ "": "ff: Garbage",
+ "description": "All these types have no data. Also, since Garbage is used to represent decoding failures, it's generally a bad idea to create it on purpose.",
+ },
+ truefalse: {
+ "": "02: True and 03: False",
+ },
+ "null": {
+ "": "04: Null",
+ },
+ double: {
+ "": "05: Double",
+ "description": "Finally, something interesting! Hexcasting uses IEEE 754 double-width floats (that's 8 bytes, 64 bits), so that's what's being used here for {symdef:double_value}."
+ },
+ pattern: {
+ "": "06: Pattern",
+ "description": "In honor of Hexxy, patterns are type 6. They're a bit complicated:",
+ "1": "First is a byte representing the {symdef:dir}. This is based on some internal representation, and appears to be as follows: 0 = north east, 1 = east, 2 = south east, 3 = south west, 4 = west, and 5 = north west.",
+ "2": "Next is a four-byte integer holding the number of angles in the pattern (effectively, strokes minus 1, or the {symdef:pattern_len})",
+ "3": "Following that are the {symdef:angles}, each 1 byte. Once again this appears to be based on some internal representation, as follows: 0 = forward, 1 = right, 2 = right back, 3 = back, 4 = left back, and 5 = left."
+ },
+ vec3: {
+ "": "07: Vector",
+ "description": "A vector is three doubles in sequence - {symdef:vec_x}, {symdef:vec_y}, and {symdef:vec_z}."
+ },
+ list: {
+ "": "08: List",
+ "description": "Lists are the primary structuring tool that Hexcasting has, and are similar to patterns - first is a four-byte {symdef:list_len}, followed by that many iota of any type.",
+ "warning": "It seems that avatars being able to bring entire structures of iota into being is a bit too much for Nature (...well, by default); you may receive garbage in return"
+ },
+ moreiotas: "MoreIotas types",
+ string: {
+ "": "01: String",
+ "description": "Strings, like the rest of the variable-length iotas, have a 4-byte {symdef:str_len} followed by the data (in this case, the {symdef:string}.) Strings are expected to be encoded in UTF-8."
+ },
+ matrix: {
+ "": "40: Matrix",
+ "description": "Matrices are two-dimensional arrays of doubles.",
+ "1": "First is a single byte for the number of {symdef:rows}, followed by another byte for the number of {symdef:cols}.",
+ "2": "This is followed by the {symdef:matrix_contents} of the matrix - one double for each entry. Each row is written out in sequence (ex. for a 2 by 2 matrix, the order would be row 1 column 1, followed by row 1 column 2, and then row 2 after that)"
+ },
+ hexpose: "Hexpose types",
+ text: {
+ "": "50: Text",
+ "description": "It appears that this format is not suitable for communicating the decorative properties of text (also called 'display') iota. Nevertheless, the actual text content can be transmitted. Text iota have the same format as strings:"
+ },
+ meta: "Non-iotas",
+ meta_intro: "These don't seem to represent iota at all! They can't be sent to Nature and only appear under special circumstances.",
+ server_info: {
+ "": "fe: Configuration Data",
+ "description": "This glob of information is Nature's repsonse to Query Configuration.",
+ "1": "First is the protocol's {symdef:protocol_version} as a two-byte 'short'. This documentation is written for version 1.",
+ "2": "Next is the maximum amount of data that can be sent with Submit Iota, in bytes.",
+ "3": "That is followed by the maximum amount of data that can be sent with Submit Iota II...",
+ "4": "and the maximum amount of data that can be received from an avatar.",
+ "5": "That's followed by the maximum amount of 'sending power' that can be held at a time, as a double precision floating point...",
+ "6": "and how much 'sending power' is regained per tick...",
+ "7": "and finally, how much 'sending power' Submit Iota II costs."
+ },
+ // that's the end of the HTML
+ },
+ api: {
+ "": "Figura API Documentation",
+ "1": "This was attached as a supplementary document to the other notes I found.",
+ // We are once again in HTML land
+ intro1: "It seems that the avatar side of the communication isn't without complexity, either - due to a complete lack of wiki maintenance ...less than optimal bookkeeping practices, the only source of information about the systems to interact with Nature seem to be the built-in documentation, which leaves much to be desired.",
+ intro2: "(If one is curious about that, it seems to be available via the incantation /figura docs globals server_packets and its various branches.)",
+ intro3: "To act as reference material in the meantime, I have created this supplementary document, which should hopefully provide the reader with a reasonable understanding of how the API works.",
+ overview: {
+ "": "Overview of server_packets",
+ "1": "Internally called ServerPacketsAPI, server_packets functions very similarly to the much more familiar pings, with a few slight differences.",
+ "2": "To receive data, use the function definition syntax you're probably familiar with:",
+ // this is a codeblock! keep the '\n\' on the right of each line, as well as the '.' at the beginning.
+ // probably don't translate code
+ "code1": "\
+ .function server_packets.packet_id(data)\n\
+ . -- Handle data here!\n\
+ .end\n\
+ ",
+ "3": "Compared to pings, server_packets receivers always have exactly one parameter, through which a {sym:Buffer} is passed containing the packet's data.",
+ "4": "Make sure to close the {sym:Buffer} you are given! If you don't, the buffer slot will continue to be considered \"used\" and you will eventually run out of buffers (from my research, most people are unaware there is a limit on buffer count at all, but it exists as part of the permissions system and this is one of the easiest ways to have latent bugs.)",
+ "5": "The other main difference from pings is that sending data is explicit and not activated by calling the receiver function - that means calling server_packets.packet_id() does not send anything. To send packets, use server_packets:sendPacket(id, data), where id is a string and data is a Buffer.",
+ "6": "Make sure to rewind the Buffer before sending it.",
+ },
+ buffers: {
+ "": "Quick Introduction to {symdef:Buffer}s",
+ "h1": "The canonical documentation for Buffers is accessible via the incantation /figura docs globals data Buffer.",
+ "h2": "It's also available on FIGS or the Figura Wiki.",
+ "1": "Buffers provide a convenient interface for reading structured data like the one Nature provides. It's almost like it's based on something else...",
+ manage: {
+ new: {
+ "": "Creating new buffers: data:createBuffer()",
+ "1": "To create a new buffer, use data:createBuffer(), which returns a new Buffer object.",
+ "2": "You can also specify the initial allocated size by providing it as an argument to createBuffer, but this is not required unless you're working under really tight permissions constraints as Figura will auto-expand buffers by default.",
+ },
+ close: {
+ "": "Cleaning up after yourself: :close()",
+ "1": "As mentioned in the warning callout above, there is a limit on the number of buffers you can have, and it's tied to the permission system.",
+ "2": "On Default, the limit is 4 buffers.",
+ "3": "On High, the limit is 16 buffers.",
+ "4": "On MAX, the limit is 32 buffers.",
+ "5": "To free up a buffer, call close() on it. This will render the contents unusable."
+ },
+ code1: "\
+ .local buf = data:createBuffer()\n\
+ .-- (later...)\n\
+ .buf:close()\n\
+ ",
+ setPosition: {
+ "": "Moving the cursor around: :setPosition(pos)",
+ "1": "Buffers function with a 'cursor' that moves around the data as you read and write to it.",
+ "2": "Each time data is read or written, that action is taken at the position of the cursor and the cursor is automatically advanced to the next byte. This makes it convenient to read or write many values in sequence.",
+ "3": "However, it is still useful to be able to move the cursor around manually - notably, to read back the data written to a buffer, the cursor has to be moved (\"rewound\") back to position 0:",
+ code: "\
+ .buf:writeByte(5)\n\
+ .buf:writeDouble(3.14159)\n\
+ .buf:setPosition(0) -- move back to the beginning\n\
+ "
+ },
+ },
+ write: {
+ "": "Writing Data",
+ "hat": "This section only discusses types that Nature cares about. Other types are supported by buffers - to see that, go to the canonical documentation.",
+ "1": "There are methods to write data in various formats to a buffer. They all move the cursor to the end of the data written, so calling them multiple times in sequence will concatenate the data.",
+ "2": "For things described as 'x-byte integers', use these names:",
+ "3": "For 'doubles', use:",
+ methods: {
+ write: ":write(n): 1 byte, such as {sym:type}, {sym:dir} for patterns, and {sym:rows} and {sym:cols} for matrices.",
+ writeInt: ":writeInt(n): 4 bytes, which is primarily used to describe the length of things",
+ writeDouble: ":writeDouble(n): 8 bytes, used for both the {sym:double_value} of numbers and the {sym:vec_x}, {sym:vec_y}, and {sym:vec_z} of vectors."
+ }
+ },
+ read: {
+ "": "Reading Data",
+ "1": "Similar to writing data, Buffers are versatile in what they can read. Each read method also similarily moves the cursor to the end of the data read.",
+ methods: {
+ read: ":read(): 1 byte, such as {sym:type}, {sym:dir} for patterns, and {sym:rows} and {sym:cols} for matrices.",
+ readShort: ":readShort(): 2 bytes - the protocol {sym:protocol_version}",
+ readInt: ":readInt(): 4 bytes, usually lengths but also quite a few configuration parameters",
+ readDouble: ":readDouble(): 8 bytes, used for both the {sym:double_value} of numbers and the {sym:vec_x}, {sym:vec_y}, and {sym:vec_z} of vectors, as well as the sending power-related configuration values."
+ }
+ },
+ },
+ // End of HTML
+ },
+ // here's a bunch of things that the renderer puts together
+ // to form all of those symbols and markup
+ symbols: {
+ type: "type",
+ data: "data",
+ value: "value",
+ dir: "dir", // direction
+ length: "length", // length
+ angles: "angles",
+ x: "x",
+ y: "y",
+ z: "z",
+ iotas: "iotas",
+ string: "string",
+ contents: "contents",
+ rows: "rows",
+ cols: "cols", // columns
+ rowscols: "rows*cols",
+ version: "version",
+ max_send: "max_send",
+ max_inter_send: "max_inter",
+ max_recv: "max_recv",
+ max_power: "max_power",
+ power_regen_rate: "power_regen_rate",
+ inter_cost: "inter_cost",
+ Buffer: "Buffer", // Don't translate - Figura type
+ },
+ admin: {
+ // These entries are only rendered in hexdoc, so we don't have to worry
+ // about not overflowing the page!
+ fsb: {
+ "": "About FSB",
+ "1": "mediatransport relies on $(n)Figura Server Backend/$ (also called $(n)FSB/$) to function. FSB is a feature in the development builds of Figura for 1.20.1 that enables hosting avatars and pings on the server itself instead of relying on the global backend.",
+ "2": "FSB $(n)doesn't work on Singleplayer/$ or LAN worlds, so you might want to host a dedicated server to test your hexes out. Thanks for playing our addon! :)$(br2)$(l:https://github.com/penguinencounter/Figura/releases/tag/figura-fsb-placeholder)Figura FSB builds on GitHub$(/l)",
+ },
+ config: {
+ "": "mediatransport config",
+ "1": "mediatransport has various server configuration options to limit what data can be sent between avatars and casting environments.",
+ maxSize: {
+ "": "Size Restrictions",
+ "1": "All values in bytes.$(br2)$(n)maximumSendSize/$: maximum amount of data that can be sent through $(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l).$(br2)$(n)maximumInterSendSize/$: maximum amount of data that can be sent through $(l:hexcasting:patterns/figura#mediatransport:send_other)Submit Iota II$(/l).$(br2)$(n)maximumRecvSize/$: maximum amount of data that can be received from Figura. If this is exceeded, garbage will be pushed into the queue instead of the actual data.$(br2)$(n)matrixMaxArea/$: MoreIotas only; sets the maximum matrix area (width * height) that can be sent or received, separately from other restrictions and the maximum row/column count of 255."
+ },
+ filterIntro: {
+ "": "Filters",
+ "1": "mediatransport has three separate $(italic)filter/$ configuration sets for controlling what types of iota can be sent. Each one has a $(n)mode/$ and a $(n)list of entries/$.$(br2)The $(n)mode/$ can either be $(bold)\"Block\"/$ (forbids certain types, 'blocklist') or $(bold)\"Allow\"/$ (only allows certain types, 'allowlist').$(br2)The list contains the list of resource locations to apply the filter with. For example, to disallow sending lists, set the $(n)mode/$ to $(bold)\"Block\"/$ and the list to $(bold)[\"hexcasting:list\"]/$.$(br2)Note that allowing an iota type won't magically make it sendable if mediatransport lacks encoders or decoders for that type."
+ },
+ sendFilters: {
+ "": "Sending Filters",
+ "1": "Just like the size limits, there are separate filters for $(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l) and $(l:hexcasting:patterns/figura#mediatransport:send_other)Submit Iota II$(/l).$(br2)$(n)sendFilter/$ and $(n)sendFilterMode/$ apply to Submit Iota. $(n)interSendFilter/$ and $(n)interSendFilterMode/$ apply to Submit Iota II.$(br2)If an iota is blocked by these filters, it will cause an 'bad type' mishap on the relevant iota (even if it's nested in a list.)"
+ },
+ recvFilters: {
+ "": "Receiving Filters",
+ "1": "$(n)recvFilter/$ and $(n)recvFilterMode/$ control what types of iota can be received from Figura.$(br2)Any iota that are blocked by this filter are replaced with Garbage, but any containing iota will be unaffected. (ex. a list containing an invalid iota will be received as a list containing garbage instead, provided lists are allowed.)"
+ },
+ ratelimits: {
+ "": "Rate Limits",
+ "1": "'Sending power' is really just a number that goes up over time until it hits a limit for each player. The system is balance around one usage of $(l:hexcasting:patterns/figura#mediatransport:send_fsb)Submit Iota$(/l) consuming 1.00 'power'.$(br2)$(li)$(n)rateLimitChargePerTick/$ controls how quickly 'power' recharges. The default of 1.0 means that on average a player can only use Submit Iota once every tick./$$(li)$(n)rateLimitMaxValue/$ is the maximum 'power' that players can hold on to at once. Setting this below 1 means that Submit Iota will always fail. Setting this greater than 1 lets players send in 'bursts' without running into the rate limit as long as their overall rate remains below the limit./$$(li)$(n)interSendConstMultiplier/$ lets you configure how much Submit Iota II costs relative to Submit Iota. Because Submit Iota costs 1, this is effectively the price of Submit Iota II"
+ },
+ }
+ },
+ figura_see_also_1: "I've cataloged the rest of the details in these entries.",
+ see_also: "See Also",
+ index: {
+ "": "Transports: Index",
+ desc: "An index of all the entries related to transports and Figura.",
+ },
+ blank: "$(#b0b0b0)this page left blank for layout purposes/$",
+ blank_dark: "$(#504060)this page left blank for layout purposes/$",
+ },
+ // "can't send (iota) because..."
+ not_sendable: {
+ bad_type: "that type of iota can't be sent",
+ corrupt: "it's corrupted or ill-formed",
+ matrix_too_big: "it's too big",
+ matrix_too_many_rows: "it has too many rows (max 255)",
+ matrix_too_many_cols: "it has too many columns (max 255)",
+ },
+ radio_silence_options: {
+ // translators: good luck, sorry (you can replace all of these with the 'help' one if you want)
+ crickets: "*crickets*",
+ ellipsis: "......",
+ help: "Receiving queue is empty",
+ eof: "java.util.NoSuchElementException: collection is empty",
+ insanity: "You hear whispering, but you can't make it out.",
+ informal: "there's nothing here.",
+ },
+ mishap_names: {
+ init_fail: "Transport Init Failure",
+ bad_type: "Not a Submittable Iota",
+ corrupted: "Corrupt Iota",
+ matrix_too_large: "Matrix Too Large",
+ iota_too_large: "Send Too Large",
+ iota_too_large_inter: "Send Other Too Large",
+ radio_silence: "Nothing to Accept",
+ rate_limit_exceeded: "Too Fast",
+ },
+ },
+ hexcasting: {
+ action: {
+ "mediatransport:": {
+ send_fsb: "Submit Iota",
+ send_other: "Submit Iota II",
+ recv_fsb: "Accept Iota",
+ check_queue: "Semaphore's Reflection",
+ check_rate_limit: "Quota's Reflection",
+ send_server_info: "Query Configuration",
+ },
+ // use this to add shortened versions of pattern names if the full name won't fit in the ingame book
+ // you don't need to add an entry for every pattern - the above value will be used as a default
+ book: {
+ "mediatransport:": {
+ check_queue: "Semaphore's Refl.",
+ },
+ },
+ },
+ mishap: {
+ not_sendable: "can't send %s",
+ not_sendable_ex: "can't send %s because %s",
+ too_large_to_send: "can't send: calculated size at least %s B, but server configured limit is %s B",
+ too_large_to_send_inter: "can't send to other players: calculated size at least %s B, but server configured limit is %s B",
+ fsb_not_initialized: "Figura server isn't initialized (tell your local admin to use a dedicated server and install FSB)",
+ radio_silence: "%s", // see mediatransport.radio_silence_options
+ rate_limit_exceeded: "Sending data too fast (%s required, %s available; +%s/tick, max %s)",
+ }
+ },
+}
\ No newline at end of file
diff --git a/projects/1.20/assets/modrinth-mediatransport/mediatransport/lang/zh_cn.flatten.json5 b/projects/1.20/assets/modrinth-mediatransport/mediatransport/lang/zh_cn.flatten.json5
new file mode 100644
index 000000000000..89dc4b1ec6f0
--- /dev/null
+++ b/projects/1.20/assets/modrinth-mediatransport/mediatransport/lang/zh_cn.flatten.json5
@@ -0,0 +1,369 @@
+{
+ mediatransport: {
+ book: {
+ category: {
+ interop: {
+ figura: {
+ "": "Figura",
+ desc: "这些叫作$(thing)形象/Avatar/$ 的构造体确实强大,只是操控起来有些烦人。"
+ }
+ }
+ },
+ patterns: {
+ figura: {
+ "": "传递图案",
+ intro: "",
+ send_fsb: "将栈顶 iota 发送至以太,以便我当前的形象接收。可能会因$(l:hexcasting:interop/figura/mishaps)多种理由$(/l)而失败。固定消耗 1 点“发送能量”。",
+ send_other: "将栈顶 iota 发送出去,以便栈顶往下第二位置处的玩家接收。它所用的接收器似乎独立于同类法术。通常消耗 2 点“发送能量”,但可能因为服务端配置不同而变化。",
+ recv_fsb: "从$(thing)接收队列/$中获取下一个 iota,队列为空会招致$(l:hexcasting:interop/figura/mishaps)事故$(/l)。",
+ check_queue: "获取队列中 iota 的个数。",
+ check_rate_limit: "查询剩余的“发送能量”点数。",
+ send_server_info_a: "请求自然发送其对我当前所用形象的首选项。消耗 1 点“发送能量”。详情参见$(l:https://penguinencounter.github.io/mediatransport/v/latest/main/en_us/mediatransport_virtual/protocol)在线协议文档$(/l)。",
+ send_server_info_b: "请求自然发送其对我当前所用形象的首选项。消耗 1 点“发送能量”。详情参见$(l:hexcasting:mediatransport_virtual/protocol)协议文档$(/l)。",
+ },
+ },
+ interop: {
+ figura: {
+ about: {
+ "": "传递",
+ "1": "我找到了其他发现$(hex)咒法学/$这门技艺的人的笔记。笔记中我能理解的部分都已摘抄在此,但最后一部分里到处都是术语黑话,以至于完全无法理解。也许我应该去了解了解笔记中提及许多次的“$(thing)形象/$”的学问?",
+ "2": "这些匠师与$(thing)形象/$交流时用的方法较为原始,但随后不久自然似乎就专门为此新创了图案。自然扭曲了 iota 的形态,以提高传递的效率和吞吐量,大概算是某种标准惯例吧。倘若凭肉眼观察扭曲后的 iota,看见的只会是方框和各种乱码。",
+ "3": "创作$(thing)形象/$的匠师们貌似没有遇到读不懂的问题,而且也找到了解码方法。后方是他们留下的笔记,谨供参照。不过说真的,我真不太懂到底发生了什么。",
+ "A": "我们发现(创造?)了些新法术。它们能令形象和咒术直接交流;不会再因为滥发信息被踢了!$(br2)我们中对数据了解较多的人成功解码了格式。整个协议均与字节对齐,且在数据传递中用到了 $(#8bf)Buffer/$。(换句话说,用完记得关闭!)",
+ "B": "从我们的观察出发,可以发现每个 iota 均以单个字节的$(#8bf)类型/type/$ 起始,而后跟随 0 字节或若干字节的$(#8bf)数据/data/$。所有多字节格式均采用大端序。(也是 Buffer 读取方法默认采用的。)$(br2)",
+ "C1": "可惜的是,这本笔记有不少局限,实在不够方便,没法在这里写明格式细节。也许可以在$(l:https://penguinencounter.github.io/mediatransport/v/latest/main/en_us/mediatransport_virtual/protocol)更灵活的载体$(/l)上试试看?",
+ "C2": "格式的全部细节见此:$(l:hexcasting:mediatransport_virtual/protocol)Iota 传递协议$(/l)。",
+ "D": "不过,自然并不乐意大批量传递 MiB 级别的数据;为避免此类滥用,传递时需考虑到“发送能量”。在正常情况下其能迅速恢复,而所有与传递相关的操作都会消耗发送能量。",
+ "E": "而当“发送能量”耗尽时,试图提交更多 iota 会招致事故。为避免其耗尽,可使用$(l:hexcasting:patterns/figura#mediatransport:check_rate_limit)配额之精思$(/l)加以调控。"
+ },
+ mishaps: {
+ "": "传递事故",
+ "1": "形象传递所用的语言相当深奥,若使用不当,可能会产生多种错误。",
+ // first italic part is the same as first part of the mishap text
+ init_fail: "$(italic)Figura 服务器未初始化……/$$(br2)服务端配置错误,或所处宇宙为“集成服务端”时出现。产生灰色火花,并使我生出一种失望感。",
+ bad_type: "$(italic)无法发送……因为该 iota 类型无法发送/$$(br2)自然不接受发送该类型 iota 的请求。产生黑色火花。$(br2)$(italic)想支持传递某种 iota?请到 $(l:https://github.com/penguinencounter/mediatransport/issues)GitHub$(/l) 处询问!/$",
+ corrupted: "$(italic)无法发送……因为信息损坏或格式错误/$$(br2)某些东西发生了严重的损坏。产生黑色火花,也许也应该知会相关的 GitHub 问题跟踪器。",
+ matrix_too_large: "$(italic)无法发送……因为矩阵过大$(br)无法发送……因为矩阵行数过多$(br)无法发送……因为矩阵列数过多/$$(br2)试图发送的矩阵元素过多,或行数/列数超出了 255。产生黑色火花。",
+ iota_too_large: "$(italic)无法发送:传递所用空间最少为……/$$(br2)所发送 iota 占用的空间比允许的最大值还要大。产生黑色火花。$(br2)$(italic)注意:服务器管理员可在配置中更改上限。/$",
+ iota_too_large_inter: "$(italic)无法发送至其他玩家:传递所用空间最少为……/$$(br2)向其他玩家的形象发送 iota 时,其占用的空间比允许的最大值还要大。产生黑色火花。$(br2)$(italic)注意:服务器管理员可在配置中更改上限。/$",
+ radio_silence: "试图接受 iota,而实际无 iota 可供接受(也即队列为空)。产生白色火花,并令我耳中回响起$(k)受折磨之意识/$的尖啸。",
+ rate_limit_exceeded: "“发送能量”耗尽。也许使用提交 Iota 时要再凝练些?产生橙色火花,并产生某物破碎的声音。",
+ "2": "似乎这里的大部分错误都只在从自然的领域$(italic)发送/$(或者说“提交”)数据时出现。自然对接受错误数据似乎更宽容……因为这不会导致崩溃,而是会产出它最喜爱的非错误:垃圾!$(br)不过这也让我们很难确定发送失败的原因。我们在此汇总了一份检查表:",
+ "3": "- 自然未对该数据的类型(也即首字节)提供表示方法$(br)- 传递末尾缺失数据$(br)- 数据过大(此类别的空间占用上限可能和另一种过大导致的错误不同……)$(br)- 上一条的变种,受同样的矩阵长宽限制约束(尽管只要行数或列数过多,数据必定会过大)",
+ "4": "还需注意,列表可能会部分传递失败。这可能导致解码器“出轨”,以至于将类型错误解读为数据,反过来也有可能。祝好运!"
+ }
+ }
+ },
+ pluralizations: {
+ // 0, 1, "" (any)
+ byte: {
+ "1": "%s字节",
+ "": "%s字节"
+ }
+ },
+ channels: {
+ "": "FSB 频道",
+ "A1": "这些文本摘抄自某份文件边沿处潦草写下的内容……不太记得是什么了。好奇怪。",
+ "A2": "$(li)$(l:hexcasting:patterns/figura#mediatransport:send_fsb)提交 Iota$(/l) - transport_received/$$(li)$(l:hexcasting:patterns/figura#mediatransport:send_other)提交 Iota,第二型$(/l) - transport_external_received/$$(li)$(l:hexcasting:patterns/figura#mediatransport:recv_fsb)接受 Iota$(/l) - transport_send",
+ "og": "与自然对歌的正确方法",
+ "B1": "……啊,我想起来了!",
+ doc: {
+ "1": "由提交 Iota发送的数据会送至server_packets.transport_received,如下:",
+ "code1": "\
+ .function server_packets.transport_received(data)\n\
+ . data:close()\n\
+ .end\n\
+ ",
+ "2": "其他施法者由提交 Iota,第二型发送的数据会送至另一个频道:server_packets.transport_external_received",
+ "code2": "\
+ .function server_packets.transport_external_received(data)\n\
+ . data:close()\n\
+ .end\n\
+ ",
+ "3": "最后,如需发送数据,应在:sendPacket中使用\"transport_send\":",
+ "code3": "\
+ .server_packets:sendPacket(\"transport_send\", buffer)\n\
+ .buffer:close()\n\
+ "
+ }
+ },
+ protocol: {
+ "": "Iota 传递协议",
+ "1": "啊,这才叫极致的灵活嘛!我在此记录了若干张格式图表。",
+ // text in {curly brackets} are keywords. Don't translate the text inside.
+ // btw this section uses HTML
+ "notice": "本文档适用于特定版本的协议({sym:protocol_version}:1)。",
+ "intro1": "与先前描述的一样,iota由1字节的{symdef:type}起始,后跟一定量的{symr:data},数据量由类型决定。",
+ "intro2": "每种iota都有其独特的{sym:type}值,且各类型的{symr:data}格式各不相同。",
+ stdtypes: "内置类型",
+ garbage: {
+ "": "ff:垃圾",
+ "description": "这些类型不带数据。同时因为垃圾用于表示解码错误,通常不建议专门传递垃圾。",
+ },
+ truefalse: {
+ "": "02:True和03:False",
+ },
+ "null": {
+ "": "04:Null",
+ },
+ double: {
+ "": "05:双精度浮点数",
+ "description": "终于是有点意思的东西了!咒法学采用IEEE 754双精度浮点数(即8字节、64位),此处{symdef:double_value}中使用的就是该值。"
+ },
+ pattern: {
+ "": "06:图案",
+ "description": "为致敬Hexxy,图案的类型值选用了6。图案的编码有些复杂:",
+ "1": "首先是代表{symdef:dir}的1个字节。其值与内部表示有对应关系,具体的外在表现如下:0 = 东北,1 = 东,2 = 东南,3 = 西南,4 = 西,5 = 西北。",
+ "2": "随后是图案的角度数目,为一4字节整数。其值等于笔画数减1,也等于{symdef:pattern_len}。",
+ "3": "而后是{symdef:angles}本身,各角度占1个字节。其值同样与内部表示有对应关系,具体表现如下:0 = 前方,1 = 右前方,2 = 右后方,3 = 后方,4 = 左后方,5 = 左前方。"
+ },
+ vec3: {
+ "": "07:向量",
+ "description": "向量即是按序排列的三个双精度浮点数:{symdef:vec_x}、{symdef:vec_y}、{symdef:vec_z}。"
+ },
+ list: {
+ "": "08:列表",
+ "description": "列表是咒法学中的主要结构化工具,且其表示与图案类似:首先是4字节的{symdef:list_len},后方跟随任意类型的iota表示。",
+ "warning": "形象具有一次性创造一整个iota结构的能力,自然似乎在这方面有些力不从心,没法很好地满足需求(……至少默认是这样);你有可能会接收到垃圾"
+ },
+ moreiotas: "MoreIotas类型",
+ string: {
+ "": "01:字符串",
+ "description": "字符串和其他可变长度的iota类似,开头处有一4字节的{symdef:str_len},后方再跟随数据(此类型中为{symdef:string})。字符串的预期编码为UTF-8。"
+ },
+ matrix: {
+ "": "40:矩阵",
+ "description": "矩阵是由双精度浮点数组成的二维数组。",
+ "1": "首先是1字节的{symdef:rows},后方跟随1字节的{symdef:cols}。",
+ "2": "然后是矩阵的{symdef:matrix_contents}——每个元素都是一个双精度浮点数。各行按序排列(例如2×2矩阵,其顺序如下:首先是第1行第1列的元素、而后是第1行第2列的元素,然后再跟随第2行的元素)。"
+ },
+ hexpose: "Hexpose类型",
+ text: {
+ "": "50:文本",
+ "description": "此格式似乎无法传递文本iota(又称“文形”)的装饰属性。不过无论如何,文本本身还是可以传递的。文本iota的格式与字符串一致:"
+ },
+ meta: "非iota",
+ meta_intro: "这些数据似乎并不对应某种iota!它们无法发送给自然,且只会在特殊情况下出现。",
+ server_info: {
+ "": "fe:配置数据",
+ "description": "这个信息团是自然对查询配置的回应。",
+ "1": "首先是协议的{symdef:protocol_version},为一2字节“短整型”。本文档所述协议的版本号为1。",
+ "2": "然后是提交Iota可传递数据的最大空间占用量,以字节计。",
+ "3": "随后是提交Iota,第二型可传递数据的最大空间占用量……",
+ "4": "再是形象可接收数据的最大量。",
+ "5": "而后是某时刻下“发送能量”的最大值,为一双精度浮点数……",
+ "6": "以及“发送能量”每刻的恢复量……",
+ "7": "最后,是提交Iota,第二型的“发送能量”消耗量。"
+ },
+ // that's the end of the HTML
+ },
+ api: {
+ "": "Figura API 文档",
+ "1": "我在其他笔记的补充材料中发现了这则条目。",
+ // We are once again in HTML land
+ intro1: "在数据交流中,形象端的操作也比较复杂,也许是因为完全无人维护wiki……记录实践不太有效。与自然交互所用系统的信息来源似乎只有内置文档,且许多内容尚不完善。",
+ intro2: "(如果希望查阅这些文档,可以咏唱/figura docs globals server_packets及其各个子分支。)",
+ intro3: "受此影响,我写了这篇补充文档用作参照材料,希望可以让读者对API的工作方式有一定程度的了解。",
+ overview: {
+ "": "server_packets概览",
+ "1": "server_packets的内部名称为ServerPacketsAPI,其功能和我们更为熟悉的pings类似,两者只有少量区别。",
+ "2": "接收数据时,可使用(你可能更熟悉的)函数定义语法:",
+ // this is a codeblock! keep the '\n\' on the right of each line, as well as the '.' at the beginning.
+ // probably don't translate code
+ "code1": "\
+ .function server_packets.packet_id(data)\n\
+ . -- 在此处理数据!\n\
+ .end\n\
+ ",
+ "3": "与pings相比,server_packets的接收器永远只会有一个参数,应传入内含数据包中数据的{sym:Buffer}。",
+ "4": "务必关闭你的{sym:Buffer}!倘若不关闭,Buffer槽会保持在“已使用”状态,最终会导致Buffer耗尽。(从我的研究看来,大多数人根本不知道Buffer的数量有上限。但不管怎么说,它是权限系统的一部分,而不关闭Buffer是产生潜在漏洞的最简单方式之一。)",
+ "5": "另一则和pings的区别,在于此包要求显式发送数据,而调用接收器函数并不会激活此功能。换言之,调用server_packets.packet_id()不会发送数据。发送数据包时,应当使用server_packets:sendPacket(id, data),其中id是string,而data需为Buffer。",
+ "6": "发送前务必重置Buffer指针。",
+ },
+ buffers: {
+ "": "{symdef:Buffer}快速介绍",
+ "h1": "Buffer的官方文档可通过咏唱/figura docs globals data Buffer获取。",
+ "h2": "也可在FIGS处和Figura维基处访问。",
+ "1": "Buffer是读取结构化数据(如自然提供的数据)的便捷接口。就好像它有个参考原型似的……",
+ manage: {
+ new: {
+ "": "新建Buffer:data:createBuffer()",
+ "1": "新建Buffer时,应使用data:createBuffer(),它会返回一个新Buffer对象。",
+ "2": "也可在createBuffer的参数中指定初始分配的内存大小,但除非有极其严格的限制,Figura默认会自动扩展Buffer,因此并不一定要指定此参数。",
+ },
+ close: {
+ "": "收拾残局::close()",
+ "1": "如上文所警告的,Buffer的数量有上限,且其与权限系统挂钩。",
+ "2": "处于Default等级时,上限为4个Buffer。",
+ "3": "处于High等级时,上限为16个Buffer。",
+ "4": "处于MAX等级时,上限为32个Buffer。",
+ "5": "对Buffer调用close()即可释放。释放后不可再获取其内容。"
+ },
+ code1: "\
+ .local buf = data:createBuffer()\n\
+ .-- (过一段时间之后……)\n\
+ .buf:close()\n\
+ ",
+ setPosition: {
+ "": "移动指针::setPosition(pos)",
+ "1": "读取和写入Buffer时,实际用到的是在数据中移动的“指针”。",
+ "2": "每次读写数据时,即会在指针所处位置执行对应操作,并自动将指针移动到下一字节。可借此方便地按序读写多个值。",
+ "3": "不过,手动移动指针依然有其用途。譬如说,需将写入Buffer的数据读取回来,应将指针移动到0号位置(即“重置”):",
+ code: "\
+ .buf:writeByte(5)\n\
+ .buf:writeDouble(3.14159)\n\
+ .buf:setPosition(0) -- 移回开头\n\
+ "
+ },
+ },
+ write: {
+ "": "写入数据",
+ "hat": "本节仅讨论自然会接受的类型。Buffer确实支持其他类型,如需获取列表,请参阅官方文档。",
+ "1": "有多种方法可向Buffer写入各类型的数据。它们都会将指针移至所写数据的末尾,因此连续多次调用相当于前后拼接数据。",
+ "2": "对于“x字节整数”,应使用下列方法:",
+ "3": "对于“双精度浮点数”,应使用下列方法:",
+ methods: {
+ write: ":write(n):1字节,如{sym:type}、图案的{sym:dir}、矩阵的{sym:rows}和{sym:cols}。",
+ writeInt: ":writeInt(n):4字节,通常用于描述数据的长度",
+ writeDouble: ":writeDouble(n):8字节,数的{sym:double_value}、向量的{sym:vec_x}、{sym:vec_y}、{sym:vec_z}。"
+ }
+ },
+ read: {
+ "": "读取数据",
+ "1": "与写入数据类似,Buffer也支持多种读取方法。每个读取方法同样都会将指针移至所读数据的末尾。",
+ methods: {
+ read: ":read():1字节,如{sym:type}、图案的{sym:dir}、矩阵的{sym:rows}和{sym:cols}。",
+ readShort: ":readShort():2字节,协议{sym:protocol_version}。",
+ readInt: ":readInt():4字节,通常是长度,也可以是配置参数。",
+ readDouble: ":readDouble():8字节,数的{sym:double_value}、向量的{sym:vec_x}、{sym:vec_y}、{sym:vec_z},也用于与“发送能量”相关的配置值。"
+ }
+ },
+ },
+ // End of HTML
+ },
+ // here's a bunch of things that the renderer puts together
+ // to form all of those symbols and markup
+ symbols: {
+ type: "类型",
+ data: "数据",
+ value: "值",
+ dir: "朝向", // direction
+ length: "长度", // length
+ angles: "角度",
+ x: "x",
+ y: "y",
+ z: "z",
+ iotas: "iota",
+ string: "字符串",
+ contents: "内容",
+ rows: "行数",
+ cols: "列数", // columns
+ rowscols: "行数*列数",
+ version: "版本号",
+ max_send: "最大发送",
+ max_inter_send: "最大玩家间发送",
+ max_recv: "最大接收",
+ max_power: "最大能量",
+ power_regen_rate: "能量恢复速率",
+ inter_cost: "玩家间发送消耗",
+ Buffer: "Buffer", // Don't translate - Figura type
+ },
+ admin: {
+ // These entries are only rendered in hexdoc, so we don't have to worry
+ // about not overflowing the page!
+ fsb: {
+ "": "关于 FSB",
+ "1": "mediatransport 的运作依赖于 $(n)Figura Server Backend/$(Figura 服务端后端,又称 $(n)FSB/$)。FSB 是 1.20.1 版本下 Figura 开发版的特性,允许在服务端中托管形象和 pings,而不需要通过全局后端处理。",
+ "2": "FSB $(n)在单人游戏和 LAN 世界中无效/$,因此你可能需要使用专用服务器来测试咒术。感谢你游玩我们的附属!:)$(br2)$(l:https://github.com/penguinencounter/Figura/releases/tag/figura-fsb-placeholder)GitHub 上的 Figura FSB 构建文件$(/l)",
+ },
+ config: {
+ "": "mediatransport 配置",
+ "1": "mediatransport 有多条服务端配置选项,能用于限制形象与施法环境间传递的数据。",
+ maxSize: {
+ "": "空间占用限制",
+ "1": "所用配置值均以字节为单位。$(br2)$(n)maximumSendSize/$:$(l:hexcasting:patterns/figura#mediatransport:send_fsb)提交 Iota$(/l) 可发送的最大数据量。$(br2)$(n)maximumInterSendSize/$:$(l:hexcasting:patterns/figura#mediatransport:send_other)提交 Iota,第二型$(/l)可发送的最大数据量。$(br2)$(n)maximumRecvSize/$:来自 Figura 的最大接收数据量。超出此限制会向队列压入垃圾。$(br2)$(n)matrixMaxArea/$:MoreIotas 独占;设定收发矩阵时其最大元素数(宽*高),此配置项独立于其他限制,也独立于最大行数和列数(255)配置。"
+ },
+ filterIntro: {
+ "": "过滤器",
+ "1": "mediatransport 有三个独立的$(italic)过滤器/$配置组,用以控制可以发送何种 iota。每个过滤器都由 $(n)mode/$(模式)和$(n)过滤项列表/$组成。$(br2)$(n)mode/$ 可以是 $(bold)\"Block\"/$ (黑名单,禁用特定类别)或 $(bold)\"Allow\"/$(白名单,仅允许特定类别)。$(br2)过滤项列表用于指明过滤器所作用类别的资源位置。例如,为禁用发送列表,应将 $(n)mode/$ 设置为 $(bold)\"Block\"/$,列表设置为 $(bold)[\"hexcasting:list\"]/$。$(br2)需注意,如果 mediatransport 没有适配某类型的编解码器,向白名单加入该 iota 类型并不会自动使得其可发送。"
+ },
+ sendFilters: {
+ "": "发送过滤器",
+ "1": "和空间占用限制类似,$(l:hexcasting:patterns/figura#mediatransport:send_fsb)提交 Iota$(/l) 和$(l:hexcasting:patterns/figura#mediatransport:send_other)提交 Iota,第二型$(/l)使用的过滤器是不同的。$(br2)$(n)sendFilter/$ 和 $(n)sendFilterMode/$ 适用于提交 Iota。$(n)interSendFilter/$ 和 $(n)interSendFilterMode/$ 适用于提交 Iota,第二型。$(br2)如果这些过滤器中阻挡了某种 iota,发送相关 iota 时即会招致“Iota 不可提交”事故(就算在列表中也一样)。"
+ },
+ recvFilters: {
+ "": "接收过滤器",
+ "1": "$(n)recvFilter/$ 和 $(n)recvFilterMode/$ 用于控制可从 Figura 处接收何种 iota。$(br2)此过滤器阻挡的 iota 会替换成垃圾,但包含此类型 iota 的容器不受影响。例如,在列表不被阻挡的情况下,包含非法 iota 的列表只会换为包含垃圾的列表。"
+ },
+ ratelimits: {
+ "": "速率限制",
+ "1": "“发送能量”其实只是不断随时间递增的数,其会在达到玩家的上限时停止递增。此系统的平衡性基础是单次使用$(l:hexcasting:patterns/figura#mediatransport:send_fsb)提交 Iota$(/l) 会消耗 1.00 点“能量”。$(br2)$(li)$(n)rateLimitChargePerTick/$ 控制“能量”的增长速度。默认值为 1.0,也即平均来说,玩家每一刻可使用 1 次提交 Iota。/$$(li)$(n)rateLimitMaxValue/$ 是玩家某一时刻可持有的最大“能量”值。将其设为小于 1 意味着提交 Iota 永远不会成功执行。将其设为大于 1,即可让玩家短暂无视速率上限“爆发式”发送数据,只要其综合速率未达限制即可。/$$(li)$(n)interSendConstMultiplier/$ 用于配置提交 Iota,第二型相对提交 Iota 的消耗量。因为提交 Iota 的消耗为 1,此值等价于提交 Iota,第二型的消耗。"
+ },
+ }
+ },
+ figura_see_also_1: "我在这些条目中整理了此处未提及的内容。",
+ see_also: "延伸阅读",
+ index: {
+ "": "传递:目录",
+ desc: "所有与传递和 Figura 相关条目的目录。",
+ },
+ blank: "$(#b0b0b0)应排版需求,此页留白/$",
+ blank_dark: "$(#504060)应排版需求,此页留白/$",
+ },
+ // "can't send (iota) because..."
+ not_sendable: {
+ bad_type: "该iota类型无法发送",
+ corrupt: "信息损坏或格式错误",
+ matrix_too_big: "矩阵过大",
+ matrix_too_many_rows: "矩阵行数过多(最大255行)",
+ matrix_too_many_cols: "矩阵列数过多(最大255列)",
+ },
+ radio_silence_options: {
+ // translators: good luck, sorry (you can replace all of these with the 'help' one if you want)
+ crickets: "*蟋蟀叫*",
+ ellipsis: "……",
+ help: "接收队列为空",
+ eof: "java.util.NoSuchElementException: 集合为空",
+ insanity: "你听见了低语,但你无法解读低语的意义。",
+ informal: "这里没东西。",
+ },
+ mishap_names: {
+ init_fail: "传递初始化失败",
+ bad_type: "Iota 不可提交",
+ corrupted: "Iota 损坏",
+ matrix_too_large: "矩阵过大",
+ iota_too_large: "发送过大",
+ iota_too_large_inter: "发送至其他过大",
+ radio_silence: "无可接收",
+ rate_limit_exceeded: "传递过快",
+ },
+ },
+ hexcasting: {
+ action: {
+ "mediatransport:": {
+ send_fsb: "提交 Iota",
+ send_other: "提交 Iota,第二型",
+ recv_fsb: "接受 Iota",
+ check_queue: "信号量之精思",
+ check_rate_limit: "配额之精思",
+ send_server_info: "查询配置",
+ },
+ // use this to add shortened versions of pattern names if the full name won't fit in the ingame book
+ // you don't need to add an entry for every pattern - the above value will be used as a default
+ book: {
+ "mediatransport:": {
+ check_queue: "信号量之精思",
+ },
+ },
+ },
+ mishap: {
+ not_sendable: "无法发送%s",
+ not_sendable_ex: "无法发送%s,因为%s",
+ too_large_to_send: "无法发送:传递所用空间最少为%s B,但服务端配置中的上限为%s B",
+ too_large_to_send_inter: "无法发送至其他玩家:传递所用空间最少为%s B,但服务端配置中的上限为%s B",
+ fsb_not_initialized: "Figura服务器未初始化(请告知管理员换用专用服务器,并安装FSB)",
+ radio_silence: "%s", // see mediatransport.radio_silence_options
+ rate_limit_exceeded: "数据发送速度过快(需要%s,仅%s可用;+%s/刻,最大%s)",
+ }
+ },
+}
\ No newline at end of file