illuaminate does not handle Java files, for obvious reasons. In order to
get around that, we have a series of stub files within /doc/stub which
mirrored the Java ones. While this works, it has a few problems:
- The link to source code does not work - it just links to the stub
file.
- There's no guarantee that documentation remains consistent with the
Java code. This change found several methods which were incorrectly
documented beforehand.
We now replace this with a custom Java doclet[1], which extracts doc
comments from @LuaFunction annotated methods and generates stub-files
from them. These also contain a @source annotation, which allows us to
correctly link them back to the original Java code.
There's some issues with this which have yet to be fixed. However, I
don't think any of them are major blockers right now:
- The custom doclet relies on Java 9 - I think it's /technically/
possible to do this on Java 8, but the API is significantly uglier.
This means that we need to run javadoc on a separate JVM.
This is possible, and it works locally and on CI, but is definitely
not a nice approach.
- illuaminate now requires the doc stubs to be generated in order for
the linter to pass, which does make running the linter locally much
harder (especially given the above bullet point).
We could notionally include the generated stubs (or at least a cut
down version of them) in the repo, but I'm not 100% sure about that.
[1]: https://docs.oracle.com/javase/9/docs/api/jdk/javadoc/doclet/package-summary.html
timetout, max_upload, max_download and max_websocket_message may now be
configured on a domain-by-domain basis. This uses the same system that
we use for the block/allow-list from before:
Example:
[[http.rules]]
host = "*"
action = "allow"
max_upload = 4194304
max_download = 16777216
timeout = 30000
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
This replaces the allow/block lists with a series of rules. Each rule
takes the form
[[http.rules]]
host = "127.0.0.0/8"
action = "block"
This is pretty much the same as the previous config style, in that hosts
may be domains, wildcards or in CIDR notation. However, they may also be
mixed, so you could allow a specific IP, and then block all others.
This is sufficiently useful a class, that it's worthwhile exposing it.
Hopefully we can slowly encourage other mods to migrate to it (well, at
least in 1.14), and so make error messages more consistent.
Also:
- Add Javadoc for all public methods
- Clarify the method names a little (getNumber -> getDouble,
getReal -> getFiniteDouble).
- Make the *Table methods return a Map<?,?> instead of
Map<Object, Object>.
- Adds a CheckStyle configuration which is pretty similar to CC's
existing one.
- Add the Gradle license plugin.
- Ensure the existing source code is compatible with these additional
checks.
See #239
OK, so let's get this out of the way, there's some actual changes mixed
in here too. I'm really sorry:
- Turtles can now not be renamed with unnamed item tags (previously it
would clear the name, this seemed a little unideal).
- commands.getBlock(s)Data will also include NBT.
Now, onto the horror story which is these inspection changes:
- Make a lot of methods static
- Typo fixes
- Make utility classes final + private constructor
- Lots of reformatting (ifs -> ternary, invert control flow, etc...)
- ???
- Profit!
I'm so going to regret this - can pretty much guarantee this is going to
break something.
- We now error if there are too many websockets, instead of queuing
them up. As these have a more explicit "lifetime", it could be
confusing if http.websocket just blocks indefinitely.
- Fix a CCME when cleaning up resources.
- Move all HTTP tasks to a unified "MonitoredResource" model. This
provides a uniform way of tracking object's lifetimes and disposing
of them when complete.
- Rewrite HTTP requests to use Netty instead of standard Java. This
offers several advantages:
- We have access to more HTTP verbs (mostly PATCH).
- We can now do http -> https redirects.
- We no longer need to spawn in a new thread for each HTTP request.
While we do need to run some tasks off-thread in order to resolve
IPs, it's generally a much shorter task, and so is less likely to
inflate the thread pool.
- Introduce several limits for the http API:
- There's a limit on how many HTTP requests and websockets may exist
at the same time. If the limit is reached, additional ones will be
queued up until pending requests have finished.
- HTTP requests may upload a maximum of 4Mib and download a maximum
of 16Mib (configurable).
- .getResponseCode now returns the status text, as well as the status
code.
This implements an argument format similar to LuaReqeust, as described
in dan200/ComputerCraft#515. The Lua argument checking code is a little
verbose and repetitive, but I'm not sure how to avoid that - we should
look into improving it in the future.
Closes#21
ILuaAPI has been moved to dan200.computercraft.api.lua. One creates
a new API by registering an instance of ILuaAPIFactory. This takes an
instance of IComputerSystem and returns such an API.
IComputerSystem is an extension of IComputerAccess, with methods to
access additional information about the the computer, such as its label
and filesystem.
This uses Netty's websocket functionality, meaning we do not have to
depend on another library.
As websockets do not fit neatly into the standard polling socket model,
the API is significantly more event based than CCTweaks's. One uses
http.websocket to connect, which will wait until a connection is
established and then returns the connection object (an async variant is
available).
Once you have a websocket object, you can use .send(msg) to transmit a
message. Incoming messages will fire a "websocket_message" event, with
the URL and content as arguments. A convenience method (.receive())
exists to aid waiting for valid messages.
- Adds support for blacklisting domains
- Adds support for blacklisting & whitelisting IP addresses and
IP ranges.
- Reuse threads for HTTP requests
AddressPredicate will parse a series of patterns and convert them into
regexes or CIDR ranges. When checking whether an address is accessible,
we first ensure the domain is whitelisted and isn't blacklisted.
If everything is OK, then we start create a new thread for the HTTP
request and resolve the IP, ensuring that is whitelisted & not
blacklisted. Then the normal HTTP request is continued.
However, http.checkURL also needs to resolve the IP address. In order to
avoid blocking the Lua thread, this method will return instantly and
create a new thread which will queue an event.
As both http.request and http.checkURL are now creating threads and
queuing events, some logic is abstracted into a separate HTTPTask class
- this allows us to share the thread creation, finishing and cancelling
logic.
This uses a new utility class ArgumentHelper, which provides convenience
methods for parsing arguments from an array of Objects.
The format of error messages has also changed. It now follows a format
similar to Lua's native error messages - including the invalid argument
index, the expected type and the type actually received.
- Move the encoding/decoding from the Filesystem implementation to the
individual handles.
- Move each handle into an core.apis.handles package from the main fs
API.
- Move the HTTP response to inherit from these handles.
- Allow binary handles' read function to accept a number, specifying
how many characters to read - these will be returned as a Lua string.
- Add readAll to binary handles
- Allow binary handles' write function to accept a string which is
decoded into the individual bytes.
- Add "binary" argument to http.request and friends in order to return
a binary handle.
- Ensure file handles are open when reading from/writing to them.
- Return the error message when opening a file fails.