Historically CC has supported two modes when working with file handles
(and HTTP requests):
- Text mode, which reads/write using UTF-8.
- Binary mode, which reads/writes the raw bytes.
However, this can be confusing at times. CC/Lua doesn't actually support
unicode, so any characters beyond the 0.255 range were replaced with
'?'. This meant that most of the time you were better off just using
binary mode.
This commit unifies text and binary mode - we now /always/ read the raw
bytes of the file, rather than converting to/from UTF-8. Binary mode now
only specifies whether handle.read() returns a number (and .write(123)
writes a byte rather than coercing to a string).
- Refactor the entire handle hierarchy. We now have an AbstractMount
base class, which has the concrete implementation of all methods. The
public-facing classes then re-export these methods by annotating
them with @LuaFunction.
These implementations are based on the
Binary{Readable,Writable}Handle classes. The Encoded{..}Handle
versions are now entirely removed.
- As we no longer need to use BufferedReader/BufferedWriter, we can
remove quite a lot of logic in Filesystem to handle wrapping
closeable objects.
- Add a new WritableMount.openFile method, which generalises
openForWrite/openForAppend to accept OpenOptions. This allows us to
support update mode (r+, w+) in fs.open.
- fs.open now uses the new handle types, and supports update (r+, w+)
mode.
- http.request now uses the new readable handle type. We no longer
encode the request body to UTF-8, nor decode the response from UTF-8.
- Websockets now return text frame's contents directly, rather than
converting it from UTF-8. Sending text frames now attempts to treat
the passed string as UTF-8, rather than treating it as latin1.
- Update Cobalt to 0.8.0, switching our Lua version to 5.2(ish).
- Remove our `load` wrapper, as we no longer need to inject _ENV into
the enviroment table.
- Update the parser to handle labels and goto. This doesn't check that
gotos are well formed, but at least means the parser doesn't fall
over on them.
- Update our docs to reflect the changes to Cobalt.
This is largely based on our existing wiki page. I've pruned out a
couple of entries which I think are largely irrelevant (config file
splitting, Java API changes).
10/10 job by me of changing nothing since 1.13. Shame to break that
streak really.
Historically we've used copy-cat to provide a web-based emulator for
running example code on our documentation site. However, copy-cat is
often out-of-date with CC:T, which means example snippets fail when you
try to run them!
This commit vendors in copy-cat (or rather an updated version of it)
into CC:T itself, allowing us to ensure the emulator is always in sync
with the mod.
While the ARCHITECTURE.md documentation goes into a little bit more
detail here, the general implementation is as follows
- In project/src/main we implement the core of the emulator. This
includes a basic reimplementation of some of CC's classes to work on
the web (mostly the HTTP API and ComputerThread), and some additional
code to expose the computers to Javascript.
- This is all then compiled to Javascript using [TeaVM][1] (we actually
use a [personal fork of it][2] as there's a couple of changes I've
not upstreamed yet).
- The Javascript side then pulls in the these compiled classes (and
the CC ROM) and hooks them up to [cc-web-term][3] to display the
actual computer.
- As we're no longer pulling in copy-cat, we can simplify our bundling
system a little - we now just compile to ESM modules directly.
[1]: https://github.com/konsoletyper/teavm
[2]: https://github.com/SquidDev/teavm/tree/squid-patches
[3]: https://github.com/squiddev-cc/cc-web-term
- Document that settings.set doesn't persist values. I think this
closes#1512 - haven't heard back from them.
- Add missing close reasons to the websocket_closed event. Closes#1493.
- Mention what values are preserved by os.queueEvent. This is just the
same as modem.transmit. Closes#1490.
Modrinth proxies images hosted on non-trusted domains through wsrv.nl,
for understandable reasons. However, wsrv.nl blocks tweaked.cc - I'm not
sure why. Instead we reference the image on GH directly, which works!
Also:
- Fix the modrinthSyncBody task pointing to a missing file.
- Update the licenses of a few files, post getting permission from
people. <3 all.
- Standardise our badges a little, adding a modrinth badge.
- Mention Fabric and Forge support.
- Don't include MC version in the Modrinth version number. I feel this
was required at some point, but apparently not any more! This also
allows us to use Modrinth for the Forge update JSON.
- Fix several inaccuracies with several files not marking Dan's
authorship. Most of these are new files, where the code was moved from
somewhere else:
- In the public API: IDynamicLuaObject, ILuaAPI, TaskCallbakc,
IDynamicPeripheral, UpgradeBase
- In the ROM: fs, http, require
- Do not mark Dan as an author for entirely new code. This affects
DetailHelpers, DropConsumer, FluidData, InventoryMethods, ItemDetails,
MonitorRenderState, NoTermComputerScreen, Palette, PlatformHelperImpl,
UploadFileMessage, the Terminal tests, and any speaker-related files.
- Relicence many files under the MPL where we have permission to do
so. See #1339 for further details.
Thank you to everyone who has contributed so far! Cannot overstate how
appreciated it is <3.
- Several files where @MCJack123 is the exclusive contributor. He has
signed over all contributions to "any OSI-approved license". Thank
you!
- Various the file handle classes: Looking at these again, I don't
think they contain any of the original code.
- Timeouts are now driven by an interrupt system, rather than polling.
While we do not impose memory limits, this should close#1333.
- Update the table library to largely match Lua 5.4:
- Add table.move
- Table methods (with the exception of foreach/foreachi) now use
metamethods (closes#1088).
There's still some remaining quirks (for instance, table.insert
accepts values out-of-bounds), but I think that's fine.
- Cobalt's threaded-coroutine system is gone (load now supports
yielding), so we no longer track coroutine metrics.
- Type errors now use __name. See #1355, though this does not apply to
CC methods (either on the Java or CraftOS side), so is not enough to
resolve it.
See https://github.com/SquidDev/Cobalt/compare/v0.6.0...v0.7.0 for the
full delta.
This adds SPDX license headers to all source code files, following the
REUSE[1] specification. This does not include any asset files (such as
generated JSON files, or textures). While REUSE does support doing so
with ".license" files, for now we define these licences using the
.reuse/dep5 file.
[1]: https://reuse.software/
Just ran[^1] over the codebase. Turns out we'd duplicated one of the
changelog entries entirely - I suspect due to a version merge gone
wrong!
[^1]: https://github.com/crate-ci/typos/
This removes the patching of fs and http, and replaces them with their
own standard Lua APIs. This makes the bios a little simpler, and means
we can move the documentation in line.
- Add a new file_transfer event. This has the signature
"file_transfer", TransferredFiles.
TransferredFiles has a single method getFiles(), which returns a list
of all transferred files.
- Add a new "import" program which waits for a file_transfer event and
writes files to the current directory.
- If a file_transfer event is not handled (i.e. its getFiles() method
is not called) within 5 seconds on the client, we display a toast
informing the user on how to upload a file.
- Add a new Node plugin. This automatically installs npm dependencies
and provides a "NpxExecToDir" to dir task. This allows us to make the
doc website task dependencies a little nicer, by simply chaining
tasks together, rather than doing dependsOn + `input.files(the other
task output)`.
- Switch over to CurseForgeGradle from CurseGradle. The latter is
super clunky to use in non-Groovy languages.
- Copy our Modrinth description body to our repo, and add support for
syncing it. We'll still have to do CF manually I think.
I was going to do something productive tonight, but then this happened.
Whatever, I'm retired, I'm allowed to make my entire existence just
adding 50px to things. Heck, maybe I'll do the same tomorrow too.
- Add a TOC to the Local IPs page.
- Increase the echo delay in our speaker audio page to 1.5s. This
sounds much better and is less clashy than 1s. Also add a
sleep(0) (eww, I know) to fix timeouts on some browsers/computers.
- Move Lua feature compat to a new "reference" section. Still haven't
figured out how to structure these docs - open to any ideas really.
- Mention FFmpeg as an option for converting to DFPWM (closes#1075).
- Allow data-mount to override built-in files. See my comment in #1069.
- Start making the summary lines for modules a little better. Just say
what the module does, rather than "The X API does Y" or "Provides Y".
There's still a lot of work to be done here.
- Bundle prism.js on the page, so we can highlight non-Lua code.
- Copy our local_ips wiki page to the main docs.
Speakers can now play arbitrary PCM audio, sampled at 48kHz and with a
resolution of 8 bits. Programs can build up buffers of audio locally,
play it using `speaker.playAudio`, where it is encoded to DFPWM, sent
across the network, decoded, and played on the client.
`speaker.playAudio` may return false when a chunk of audio has been
submitted but not yet sent to the client. In this case, the program
should wait for a speaker_audio_empty event and try again, repeating
until it works.
While the API is a little odd, this gives us fantastic flexibility (we
can play arbitrary streams of audio) while still being resilient in the
presence of server lag (either TPS or on the computer thread).
Some other notes:
- There is a significant buffer on both the client and server, which
means that sound take several seconds to finish after playing has
started. One can force it to be stopped playing with the new
`speaker.stop` call.
- This also adds a `cc.audio.dfpwm` module, which allows encoding and
decoding DFPWM1a audio files.
- I spent so long writing the documentation for this. Who knows if it'll
be helpful!
Peripherals can now have multiple types:
- A single primary type. This is the same as the current idea of a
type - some identifier which (mostly) uniquely identifies this kind
of peripheral. For instance, "speaker" or "minecraft:chest".
- 0 or more "additional" types. These are more like traits, and
describe what other behaviour the peripheral has - is it an
inventory? Does it supply additional peripherals (like a wired
modem)?.
This is mostly intended for the generic peripheral system, but it might
prove useful elsewhere too - we'll have to see!
- peripheral.getType (and modem.getTypeRemote) now returns 1 or more
values, rather than exactly one.
- Add a new peripheral.hasType (and modem.hasTypeRemote) function which
determines if a peripheral has the given type (primary or
additional).
- Change peripheral.find and all internal peripheral methods to use
peripheral.hasType instead.
- Update the peripherals program to show all types
This effectively allows you to do things like
`peripheral.find("inventory")` to find all inventories.
This also rewrites the introduction to the peripheral API, hopefully
making it a little more useful.
Let's see how this goes.
- Update references to the new repo
- Use rrsync on the server, meaning make-doc.sh uploads relative to the
website root.
- Bump Gradle wrapper to 7.2. Not related to this change, but possibly
fixes running under Java 16. Possibly.
It's probably the lowest traffic module :p.
Also (somewhat) improve the deprecated messages in os.loadAPI. We really
need a proper article on require and converting from os.loadAPI.
This uses pre-commit [1] to check patches are well formed and run
several linters on them. We currently do some boring things (check files
are syntactically valid) as well as some project-specific ones:
- Run illuaminate on the Lua files
- Run checkstyle on Java
[1]: https://pre-commit.com/