This moves monitor networking into its own packet, rather than serialising
using NBT. This allows us to be more flexible with how monitors are
serialised.
We now compress terminal data using gzip. This reduces the packet size
of a max-sized-monitor from ~25kb to as little as 100b.
On my test set of images (what I would consider to be the extreme end of
the "reasonable" case), we have packets from 1.4kb bytes up to 12kb,
with a mean of 6kb. Even in the worst case, this is a 2x reduction in
packet size.
While this is a fantastic win for the common case, it is not abuse-proof.
One can create a terminal with high entropy (and so uncompressible). This
will still be close to the original packet size.
In order to prevent any other abuse, we also limit the amount of monitor
data a client can possibly receive to 1MB (configurable).
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
This registers IPeripheral as a capability. As a result, all (Minecraft
facing) functionality operates using LazyOptional<_>s instead.
Peripheral providers should now return a LazyOptional<IPeripheral> too.
Hopefully this will allow custom peripherals to mark themselves as
invalid (say, because a dependency has changed).
While peripheral providers are somewhat redundant, they still have their
usages. If a peripheral is applied to a large number of blocks (for
instance, all inventories) then using capabilities does incur some
memory overhead.
We also make the following changes based on the above:
- Remove the default implementation for IWiredElement, migrating the
definition to a common "Capabilities" class.
- Remove IPeripheralTile - we'll exclusively use capabilities now.
Absurdly this is the most complex change, as all TEs needed to be
migrated too.
I'm not 100% sure of the correctness of this changes so far - I've
tested it pretty well, but blocks with more complex peripheral logic
(wired/wireless modems and turtles) are still a little messy.
- Remove the "command block" peripheral provider, attaching a
capability instead.
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.
- cc.pretty.pretty now accepts two additional options:
- function_args: Show function arguments
- function_source: Show where functions are defined.
- Expose the two options as lua.* settings (defaulting function_args to
true, and function_source to false).
These are then used in the Lua REPL.
Closes#361
- Use jacoco for Java-side coverage. Our Java coverage is /terrible
(~10%), as we only really test the core libraries. Still a good thing
to track for regressions though.
- mcfly now tracks Lua side coverage. This works in several stages:
- Replace loadfile to include the whole path
- Add a debug hook which just tracks filename->(lines->count). This
is then submitted to the Java test runner.
- On test completion, we emit a luacov.report.out file.
As the debug hook is inserted by mcfly, this does not include any
computer startup (such as loading apis, or the root of bios.lua),
despite they're executed.
This would be possible to do (for instance, inject a custom header
into bios.lua). However, we're not actually testing any of the
behaviour of startup (aside from "does it not crash"), so I'm not
sure whether to include it or not. Something I'll most likely
re-evaluate.
`local varname = value` results in `varname` being inaccessible in
the next REPL input. This is often unintended and can lead to confusing
behaviour. We produce a warning when this occurs.
This uses the system described in #409, to render monitors in a more
efficient manner.
Each monitor is backed by a texture buffer object (TBO) which contains
a relatively compact encoding of the terminal state. This is then
rendered using a shader, which consumes the TBO and uses it to index
into main font texture.
As we're transmitting significantly less data to the GPU (only 3 bytes
per character), this effectively reduces any update lag to 0. FPS appears
to be up by a small fraction (10-15fps on my machine, to ~110), possibly
as we're now only drawing a single quad (though doing much more work in
the shader).
On my laptop, with its Intel integrated graphics card, I'm able to draw
120 full-sized monitors (with an effective resolution of 3972 x 2330) at
a consistent 60fps. Updates still cause a slight spike, but we always
remain above 30fps - a significant improvement over VBOs, where updates
would go off the chart.
Many thanks to @Lignum and @Lemmmy for devising this scheme, and helping
test and review it! ♥
Unknown blit colours, such as " " will be translated to black for the
background or white for the foreground. This restores the behaviour from
before #412.
- Write to a PacketBuffer instead of generating an NBT tag. This is
then converted to an NBT byte array when we send across the network.
- Pack background/foreground colours into a single byte.
This derives from some work I did back in 2017, and some of the changes
made/planned in #409. However, this patch does not change how terminals
are represented, it simply makes the transfer more compact.
This makes the patch incredibly small (100 lines!), but also limited in
what improvements it can make compared with #409. We send 26626 bytes
for a full-sized monitor. While a 2x improvement over the previous 58558
bytes, there's a lot of room for improvement.
This functions the same as shell.run, but does not tokenise the
arguments. This allows us to pass command line arguments through to
another program without having to re-quote them.
Closes#417
- Remove the parenthesis around the text (so it's now
"Computer ID: 12"), rather than "(Computer ID: 12").
- Show the tooltip if the computer has an ID and no label (as well as
when in advanced mode).
- Lint references to unknown fields of modules, excluding the keys and
colours modules. This caught several silly errors in our stub files,
but nothing else.
- Lint on using unknown globals. This highlighted a couple of really
silly mistakes. Fixes#427.
- Add documentation for fs.attributes, fs.getCapacity and pocket, as
they were not defined before.
Co-authored-by: JackMacWindows <jackmacwindowslinux@gmail.com>
- I'm excluding pocket computers, as they have such a tiny screen I'm
not sure the screen estate is worth it.
Pocket computers /generally/ aren't people's starter machine, so I
think this is fine.
- Prune the motd list, and try to make them a little shorter. I think
this list is more of the interesting ones. We can modify this list in
the future, as we get more feedback.[^1]
- Also fix paint/edit not adding an extension when they should. This
was caused by the settings rewrite, as the explicitly provided
default shadowed the one provided by bios.lua.
[^1]: ~5 months ago I asked for some feedback about enabling motds by
default. I only got something constructive back today >_>.
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.
- The store is now split into two sections:
- A list of possible options, with some metadata about them.
- A list of values which have been changed.
- settings.define can be used to register a new option. We have
migrated all existing options over to use it. This can be used to
define a default value, description, and a type the setting must have
(such as `string` or `boolean).
- settings.{set,unset,clear,load,store} operate using this value list.
This means that only values which have been changed are stored to
disk.
Furthermore, clearing/unsetting will reset to the /default/ value,
rather than removing entirely.
- The set program will now display descriptions.
- settings.{load,save} now default to `.settings` if no path is given.
This is a backport of 1.15's terminal rendering code with some further
improvements. This duplicates a fair bit of code, and is much more
efficient.
I expect the work done in #409 will supersede this, but that's unlikely
to make its way into the next release so it's worth getting this in for
now.
- Refactor a lot of common terminal code into
`FixedWithFontRenderer`. This shouldn't change any behaviour, but
makes a lot of our terminal renderers (printed pages, terminals,
monitors) a lot cleaner.
- Terminal rendering is done using a single mode/vertex format. Rather
than drawing an untextured quad for the background colours, we use an
entirely white piece of the terminal font. This allows us to batch
draws together more elegantly.
- Some minor optimisations:
- Skip rendering `"\0"` and `" "` characters. These characters occur
pretty often, especially on blank monitors and, as the font is empty
here, it is safe to skip them.
- Batch together adjacent background cells of the same colour. Again,
most terminals will have large runs of the same colour, so this is a
worthwhile optimisation.
These optimisations do mean that terminal performance is no longer
consistent as "noisy" terminals will have worse performance. This is
annoying, but still worthwhile.
- Switch monitor rendering over to use VBOs.
We also add a config option to switch between rendering backends. By
default we'll choose the best one compatible with your GPU, but there
is a config option to switch between VBOS (reasonable performance) and
display lists (bad).
When benchmarking 30 full-sized monitors rendering a static image, this
improves my FPS[^1] from 7 to 95. This is obviously an extreme case -
monitor updates are still slow, and so more frequently updating screens
will still be less than stellar.
[^1]: My graphics card is an Intel HD Graphics 520. Obviously numbers
will vary.
This would return true for any block with a fluid in it, including
waterlogged blocks. This resulted in much broken behaviour
- Turtles cannot place blocks when waterlogged (fixedd #385)
- Turtles could move into waterlogged blocks (such as fences),
replacing them.
This is relatively unoptimised right now, but should be efficient enough
for most practical applications.
- Add textutils.json_null. This will be serialized into a literal
`null`. When deserializing, and parse_null is true, this will be
returned instead of a nil.
- Add textutils.unserializeJSON (and textutils.unserializeJSON). This
is a standard compliant JSON parser (hopefully).
- Passing in nbt_style to textutils.unserializeJSON will handle
stringified NBT (no quotes around object keys, numeric suffices). We
don't currently support byte/long/int arrays - something to add in
a future commit.
- Remove stub for table.pack/table.unpack.
- Remove Lua 5.3 bitlib stub. We're not on 5.3, there's no
point emulating it.
- Change peripheral.call to correctly adjust the error level. This is a
terrible hack, but I believe the only good option.
It'd be good to remove load as well, but it's a little more complex due
to our injecting of _ENV.
Closes#363
It hasn't been http_enable for yonks - slightly worried I didn't notice
this earlier.
Also don't refer to ComputerCraft.cfg - the name has changed several
times across versions, so let's leave it ambiguous.
- Return EPOCH if a zip entry's creation/modification/access time is
missing.
- If a BasicFileAttributes.*Time method returns null, use 0 as our
time. This shouldn't happen, but is a good sanity check.
Fixes#371
This adds documentation comments to many of CC's Lua APIs, and
a couple of the Java ones, through the use of stubs. We then
export these to HTML using illuaminate [1] and upload them to our
documentation site [2].
Uploads currently occur on pushes to master and any release/tag. The
site is entirely static - there is no way to switch between versions,
etc... but hopefully we can improve this in the future.
[1]: github.com/SquidDev/illuaminate/
[2]: https://tweaked.cc/
This means we are already provided with file attributes, which halfs[^1]
the time taken to scan folders.
[^1]: This dropped the fastest scan time from ~1.3s to ~0.6. It's by no
means a perfect benchmark, but this is still an obvious improvement.
- fs.getCapacity just returns the capacity of the current drive, if
available. This will be nil on rom mounts.
- fs.attributes returns an lfs like table of various file attributes.
Currently, this contains:
- access, modification, created: When this file was last accessed,
modified and created. Time is measured in milliseconds since the
epoch, same as os.epoch("utc") and what is accepted by os.date.
- size: Same as fs.getSize
- isDir: same as fs.isDir
Closes#262
- Move timer handling to IAPIEnvironment, rather than OSAPI. This means
the environment is reset on startup/shutdown, much like normal APIs.
- Websocket.receive now accepts an optional timetout (much like
rednet.receive). This starts a timer, and waits for it to complete.
Closes#201
- contains now performs a case-insensitive comparison. While this is a
little dubious, it's required for systems like Windows, where foo and
Foo are the same folder.
- Impose a depth limit on copyRecursive. If there are any other cases
where we may try to copy a folder into itself, this should prevent
the computer entirely crashing.
See #354
- Remove Lua script to generate recipes/advancements for coloured
disks, turtle upgrades and pocket upgrades. Replacing them with Lua
ones.
- Generate most block drops via the data generator system. Aside from
cables, they all follow one of two templates.
- Remove *Stream methods on IMount/IWritableMount, and make the channel
ones the primary.
- Fix location of AbstractTurtleUpgrade
- Make IComputerAccess.getAvailablePeripheral and .getMainThreadMonitor
mandatory.
- IComputerAccess throws a specialised NotAttachedException
Most of the port is pretty simple. The main problems are regarding
changes to Minecraft's rendering system.
- Remove several rendering tweaks until Forge's compatibility it
brought up-to-date
- Map rendering for pocket computers and printouts
- Item frame rendering for printouts
- Custom block outlines for monitors and cables/wired modems
- Custom breaking progress for cables/wired modems
- Turtle "Dinnerbone" rendering is currently broken, as normals are not
correctly transformed.
- Rewrite FixedWidthFontRenderer to to the buffer in a single sweep.
In order to do this, the term_font now also bundles a "background"
section, which is just a blank region of the screen.
- Render monitors using a VBO instead of a call list. I haven't
compared performance yet, but it manages to render a 6x5 array of
_static_ monitors at almost 60fps, which seems pretty reasonable.
- Add a cc.pretty module, which provides a Wadler style pretty printer [1].
- The cc.pretty.pretty function converts an arbitrary object into a
pretty-printed document. This can then be printed to the screen with
cc.pretty.{write, print} or converted to a string with cc.pretty.render.
- Convert the Lua REPL to use the pretty printer rather than
textutils.serialise.
[1]: http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf
GPS requests are now sent and received on CHANNEL_GPS by default
instead. This means it should not be possible to distinguish
computers (and thus locate them) via their GPS requests.
"exit" now has a custom __tostring method, which prints an explanation
message. This is very similar to how Python achives the same
functionality:
lua> exit
Call exit() to exit
lua> exit()
> Actually leaves the REPL
Unfortunately we can't apply the config changes due to backwards
compatibility. This'll be something we may need to PR into Forge.
CraftTweaker support still needs to be added.
It appears that WB opens containers manually, and thus all of our stubs
network stubs are entirely ignored. Thus the only solution here is to
stub out the whole network handler code.
Thankfully this is simple enough - we do the same for Plethora and 1.14.
Fixes#328
This provides the following methods:
- dan200.computercraft.turtle.removeUpgrade(id: String)
- dan200.computercraft.turtle.removeUpgrade(stack: IItemStack)
- dan200.computercraft.turtle.addTool(id: String, craftItem: IItemStack[, toolItem: IItemStack][, kind: string])
While it's pretty minimal, it should allow for a reasonable amount of
functionality.
Closes#327 and #97.
We now use illuaminate[1]'s linting facilities to check the rom and
bios.lua for a couple of common bugs and other problems.
Right now this doesn't detect any especially important bugs, though it
has caught lots of small things (unused variables, some noisy code). In
the future, the linter will grow in scope and features, which should
allow us to be stricter and catch most issues.
As a fun aside, we started off with ~150 bugs, and illuaminate was able
to fix all but 30 of them, which is pretty neat.
[1]: https://github.com/SquidDev/illuaminate
Before it would remain the same across world reloads, and thus would be
out-of-date after leaving the first world. This architecture technically
allows for running multiple servers at once, though that's not going to
matter that soon.
This fixes them not rendering particles when broken. Particle rendering
is a little janky right now, as it uses the whole texture - we should
probably split up the texture into smaller images. Fixes#315
This should fix several issues (see #304, etc...). I'll try to get round
to PRing this into Forge at some point, though on the other hand this is
/super/ ugly.
This shouldn't matter either way - we don't expose it in the creative
menu, and there's no recipes for it. This should shut up a log message
though. Fixes#305.
This fixes monitor rendering underwater (closes#314). By default,
isSolid returns true if the render layer is SOLID. As we use CUTOUT due
to our funky TE rendering, we need to override this to return true
anyway.
This will cause some side effects, as monitors now blocking light
propagation, but I don't think that's the end of the world.
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>.
Previously we were just returning the current tile. However, if someone
was holding a reference to this inventory (such as a GUI), then it'd be
outdated and invalid once the turtle had moved.
This caused a couple of issues:
- turtle_inventory events would not be fired when moving items in the
turtle GUI.
- As of 75e2845c01, turtles would no
longer share their inventory state after moving. Thus, removing items
from a GUI using an invalid inventory would move them from an old
tile, duplicating the items.
Fixes#298, fixes#300
Not quite sure when this changed, but I'm fairly sure isMouseOver wasn't
a thing when I wrote this. Or I'm a plonker. Both are possible.
Also fixes mouse dragging not being handled in turtles.
Fixes#299
Closes#293. Doesn't really solve anything there aside from exposing the
number, but sadly there's not really anything obvious I can do on my end
- the command API just doesn't expose anything else.
- Adds cc.completions module, with a couple of helper functions for
working with the more general completion functionality (i.e. that
provided by read).
- Adds cc.shell.completions module, which provides shell-specific
completion functions.
- Add a "program completion builder", which allows you to write stuff
like this:
shell.setCompletionFunction( "rom/programs/redstone.lua",
completion.build(
{ completion.choice, { "probe", "set ", "pulse " } },
completion.side) )
Closes#232
It appears several mods inject their own drops on the LOWEST priority,
meaning that we capture the existing drops, and the other mod will clear
the (now empty) drop list and add its own, resulting in dupe bugs.
While I'd argue it's somewhat dubious doing this on the LOWEST priority,
it's not a battle I'm prepared to fight. For now, we just remove the
block/entity drop handlers, and handle all drop logic when entities are
spawned.
Fixes#288
This is the behaviour on 1.14 already, so it makes sense to backport to
1.12.
Any mod may now insert files into assets/computercraft/lua/rom, and
they'll be automatically added to the default ROM mount. This allows
other mods to easily register new programs or autorun files.
See #242
Lua 5.2+ uses loadfile(filename, mode, env), not loadfile(filename,
env). While this is a minor incompatibility, it'd be nice to be
consistent as much as possible.
We try to handle the incorrect case too, as obviously we don't want to
break existing programs.
This moves expect from the bios into a new craftos.expect module,
removing the internal _G["~expect"] definition. Apparently people were
using this irrespective of the "don't use this" comment, so we need to
find another solution.
While this does introduce some ugliness (having to load the module in
weird ways for programs, duplicating the expect function in memory), it
does allow people to use the function in a supported way, and removes
the global ugliness.
I'm not entirely sure how useful all of these will be yet - still
trying to work out what/when to test things, but hopefully this'll
be a useful datapoint.
This is equally an ugly hack, but means we're at least not constructing
entities with null worlds any more.
Ideally we could always use the turtle entity, but this will require a
bit more of a refactor.
Fixes#265
- Add Forge's "name" field to the loot tables. This doesn't resolve all
our missing loot providers, but it's a start.
- Add back GUIs for pocket computers, printouts, view computer, etc...
Equivalent to `pastebin run`, but allows running arbitrary URLs
instead.
Is this a little questionable? Yes - people shouldn't be downloading
and running code from the internet. But hey, people do that already,
so we might as well make it convenient.
So very little works, but it compiles and runs.
Things to resolve over the next few days:
- Horrible mappings (should largely be resolved by tomorrow).
- Cannot send extra data over containers - we'll have to see what Forge
does here.
- Turtle models are broken
- No block drops yet - this will largely be cherry-picking whatever I
did on Fabric.
- Weird inventory desyncs (items don't show up initially when
interacting with a CC inventory).
- Probably lots of other things.
- 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
- Make mcfly's stubbing system a little more fault-tolerant.
- Add a small utility function which redirects print, printError and
write to capture their output, rather than printing to the terminal.
This can then be matched against in order to determine a program's
output.
It's a little flakey - you can't use it multiple times in an it
block, etc... but it's a nice feature.
- Add a small couple of tests to delete as a proof-of-concept.
- Convert existing changelog over to use Markdown. This mostly involves
wrapping code in backticks, and marking things as headers where
appropriate.
- Copy all of CC:T's release notes over to the changelog. This is
somewhat more verbose than Dan's notes, but keeping them in sync
seems reasonable (and allows for automation!).
As 'require' operates relative to the current program's directory,
rather than the current directory, it meant we were trying to load files
from /rom/programs.
This is never a good idea, so we add the current directory to the
package path, allowing you to use require as one'd expect.
- Define an expect(index, actual_value, types...) helper function which
takes an argument index, value and list of permissable types and
ensures the value is of one of those types.
If not, it will produce an error message with the expected and actual
type, as well as the argument number and (if available) the function
name.
- Expose expect in the global scope as _G["~expect"], hopefully making
it clear it is internal.
- Replace most manual type checks with this helper method.
- Write tests to ensure this argument validation works as expected
Also fix a couple of bugs exposed by this refactor and the subsequent
tests:
- Make rednet checks a little more strict - rednet.close(false) is no
longer valid.
- Error when attempting to redirect the terminal to itself
(term.redirect(term)).
This only renders the bounding box on non-screen edges of the monitor,
meaning you have an uninterrupted view of the screen when hovering
hover.
Closes#219
Rendering an item worked in principle, but had several caveats:
- The terminal did not fit well within the item's texture, so we had a
rather large border.
- The "correctness" of this was very tied to Minecraft's item rendering
code. This changed a little in 1.13, causing problems like #208.
Instead we effectively reuse the computer GUI rendering code, though
also handling coloured pocket computers and rendering the modem light.
This fixes#208, and hopefully fixes#212.
Actually, many *globs*. It additionally prints the glob if no files
matched it, since that's clearer.
Also move the ComputerTestDelegate's filesystem to be disk-based. This
is what actual computers use, and the MemoryMount is a little broken.
- os.time, when given a table, will act the same as PUC Lua - returning
the seconds since the epoch. We preserve the previous string/nil
behaviour though - os.epoch("local") is equivalent to PUC's
os.time().
- os.date will now act accept a string and (optional) time, returning
an appropriate table.
Somewhat resolves the madness which was dan200/ComputerCraft#183, and
hopefully (though probably not) makes @Vexatos happy.
This changes the previous behaviour a little, but hopefully is more
sane:
- Only require the socket to be open when first calling receive. This
means if it closes while receving, you won't get an error.
This behaviour is still not perfect - the socket could have closed,
but the event not reached the user yet, but it's better.
- Listen to websocket_close events while receiving, and return null
should it match ours.
See #201
We were using += instead of =, meaning the budget always grew,
rather than growing while there was still space. As a result, computers
were never correctly rate limited.
Further more, if a computer went into a deficit, we would continue to
increase the budget by a negative amount, exponentially decreasing until
overflowing!
Yes, this is a very embarrassing mistake. I'd been aware that rate
limiting wasn't working as expected for a while, I hadn't realised
the problem would be this stupid.
This uses the same behaviour that repeaters and comparators do for
determining their input, meaning that redstone directly connected to the
computer is read (as you would expect).
It's worth noting that this is a shift from previous behaviour.
Therefore, it runs the (small) risk of breaking existing builds.
However, I believe it is more consistent with the expected behaviour.
Originally introduced in 173ea72001, but
the underlying cause has been happening for much longer.
- Fix order of method name parameters. Looks like this has been broken
since 1.11. Woops.
- Catch RuntimeExceptions too, as Forge converts checked into unchecked
ones.
Fixes#179
I promise! The joys of using -SNAPSHOT I guess...
This will now correctly cause orphaned threads to be cleaned up,
reducing the risk of thread saturation.
If mod loading fails, we'll continue to load colour handlers. As
blocks/items have not been registered, then we'll throw an NPE.
See MinecraftForge/MinecraftForge#5682. Somewhat fixes#168.
Forge's config system will read the default values as integers, meaning
it fails to validate against the config spec. Ideally this'd be fixed in
forge, but this is a suitable work around.
Previously we just relied on magic int values, which was confusing and
potentially error-prone. We could use EnumFacing, but that's a)
dependent on MC and b) incorrect, as we're referring to local
coordinates.
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
- Languages are converted to JSON
- Rename most *(_advanced) blocks to *_{advanced,normal}. It's more
verbose, but means they're sorted together.
- A couple of changes to the ROM to work with some Java changes.
- Update recipes and advancements to not use damage values.
Are most of these changes small and petty? Yes. However, IMO they do
make the code more readable. Anyway, a summary of some of the more
interesting changes:
- Expose Abstract*Upgrade classes in the API
- Fix the spelling of Jonathan in the API docs (*shakes fist*)
- Fix bug with printout not working in the offhand.
- Rename any argments/variables accidentally named "m_*", and add an
inspection to prevent it happening again.
- Remove most of the Block*.Properties classes - just inline them in
the parent class.
- Return super.writeToNBT instead of reassigning at the top.
This makes use of the "sent" variable, which would otherwise go unused. It also makes rednet.send compliant to the behaviour specified in the Wiki: http://www.computercraft.info/wiki/Rednet.send
This is largely invisible (it's marked as a child of the main
"computercraft" mod), but allows other mods (such as Plethora) to add
hard/soft dependencies on CC:T in a user-friendly manner.
- Fire all the appropriate Forge hooks
- Crafting will now attempt to craft one item at a time in a loop,
instead of multiplying the resulting stack by the number of crafts.
This means we function as expected on recipes which consume
durability instead.
- Cache the recipe between crafting and getting the remainder (and each
craft loop). This should reduce any performance hit we would
otherwise get.
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.
- Move container opening (and gui handling) into a separate class
- Move turtle/computer placement code onto the block
- GUIs now use gui{Left,Top} instead of calculating it manually.
- IPeripheralTile is now exposed in the API.
This uses a similar approach to ComputerThread: executors store how long
they've spent executing tasks. We then use that time to prioritise
executors.
One should note that we use the current runtime at the point of adding
to the queue - external tasks will not contribute towards it until a
later execution.
This effectively acts as a public interface to canExecuteExternal() and
consumeTime(). It's hopefully sufficiently general that we can mess
around with the backend as much as we like in the future.
One thing to note here is that this is based on a polling API, as it's
largely intended for people running work every tick. It would be
possible to adapt this with callbacks for when work is available,
etc..., but that was not needed immediately.
This also removes IComputerOwned, as Plethora no longer needs it.
Unlike ComputerThread, we do not have a single source of tasks, and so
need a smarter way to handle scheduling and rate limiting. This
introduces a cooldown system, which works on both a global and
per-computer level:
Each computer is allowed to do some work for 5ms. If they go over that
budget, then they are marked as "hot", and will not execute work on the
next tick, until they have cooled down. This ensures that _on average_
computers perform at most 5ms of work per tick.
Obviously this is a rather large time span, so we also apply a global
10ms to all computers. This uses the same cooldown principle, meaning we
keep to an average of 10ms, even if we go over budget.
We were not updating the property instances, so we never actually used
the new values. This changes the syncing method to just copy values from
the new config file, meaning comments and structure are preserved from
the old one.
Note, we cannot just call Config.load(File) again, as the defaults are
no longer accurate.
- We send special packets for key and mouse events, which are then
processed by the container's InputState.
- InputState keeps track of currently held keys and mouse buttons.
- When closing the container, we queue key_up/mouse_up events for any
pending buttons.
We attempted to simplify this 0bfb7049b0,
but that change now means that minimumVirtualRuntime is not updated. As
a result, new tasks will have a runtime of 0 when the queue is empty.
- Some performance improvements to JEI recipe resolver
- Use a shared map for upgrade items, meaning we only need one map
lookup.
- Cache the basic upgrade recipes.
- Use the MC version within project rather than version name.
Before IPocketAccess.getEntity would return the entity which last held
fthis computer, even if not holding it any more. As
ba823bae13 describes, this caused
pocket.equip/pocket.unequip to dupe items.
We move the validation from the PocketAPI into the main IPocketAccess
implementation, to ensure this issue does not occur elsewhere. Note, we
require a separate method, as this is no longer thread-safe.
We also now return ok, err instead of throwing an exception, in order to
be consistent with the turtle functions. See dan200/ComputerCraft#328.
This makes Pocket API not equip/unequip upgrades when the pocket
computer is outside of the player inventory (e.g. dragging,
dropped, placed in a chest).
Oh goodness, this is going to painful to update to 1.13.
We now translate:
- Computer/Disk ID tooltips
- /computercraft descriptions, synopsises and usages. The last of these
may not always be translated when in SMP, as it is sometimes done on
the server, but the alternative would be more complex than I'm happy
with.
- Tracking field names. Might be worth adding descriptions too in the
future.
Also cleanup a couple of other translation keys, so they're more
consistent with Minecraft.
Closes#141
- Turtle and pocket computers provide a "creator mod id" based on their
upgrade(s).
We track which mod was active when the upgrade was registered, and
use that to determine the owner. Technically we could use the
RegistryLocation ID, but this is not always correct (such as
Plethora's vanilla modules).
- We show all upgraded turtles/pocket computers in JEI now, rather than
just CC ones.
- We provide a custom IRecipeRegistryPlugin for upgrades, which
provides custom usage/recipes for any upgrade or upgraded item. We
also hide our generated turtle/pocket computer recipes in order to
prevent duplicates.
Previously we would register the recipes within our code, but the
advancements were written manually. This now generates JSON files for
both the advancement and recipe.
While this does mean we're shipping even more JSON, we'll need to do
this for 1.13 anyway, and means our advancements are guaranteed to be
consistent.
On a side note, a couple of other changes:
- Turtle upgrades are now mounted on the right in the creative
menu/fake recipes. This means the upgrade is now clearly visible in
the inventory.
- We no longer generate legacy turtle items at all: we'll always
construct turtle_expanded.
- Several peripheral items are no longer registered as having sub-types
(namely advanced and full-block modems).
- We only have one disk advancement now, which unlocks all 16 recipes.
- We have removed the disk conversion recipes - these can be
exposed through JEI if needed.
This allows wireless modems (advanced and normal) to be used in
multiparts. There's a very limited set of uses for this (mostly allows
using Chisel and Bits with them), but it's very simple to do.
I'd like to look into MCMP support for wired modems/cables in the
future, but this will be somewhat harder due to their pre-existing
multiblock structure.
Similarly, might be fun to look into CBMP compatibility.
- Share the ILuaContext across all method calls, as well as shifting it
into an anonymous class.
- Move the load/loadstring prefixing into bios.lua
- Be less militant in prefixing chunk names:
- load will no longer do any auto-prefixing.
- loadstring will not prefix when there no chunk name is supplied.
Before we would do `"=" .. supplied_program`, which made no sense.
For instance, `pastebin run https://pastebin.com/LYAxmSby` will now
extract the code and download appropriately. Also add an error message
when we received something which is not a valid pastebin code.
See #134.
This runs tests on CraftOS using a tiny test runner that I originally
knocked up for LuaDash. It can be run both from JUnit (so IDEA and
Gradle) and in-game in the shell, so is pretty accessible to work with.
I also add a very basic POC test for the io library. I'd like to flesh
this out soon enough to contain most of the things from the original io
test.
Before it was not actually selected until the task had yielded for the
first time. If a computer did not yield (or took a while to do so),
nothing would actually show up.
- Only update all runtimes and the minimum runtime when queuing new
exectors. We only need to update the current executor's runtime.
- Fix overflows when comparing times within TimeoutState.
System.nanotime() may (though probably won't) return negative values.
- Hopefully explain how the scheduler works a little bit.
- Runners would set their active executor before starting resetting the
time, meaning it would be judged as running and terminated.
- Similarly, the cumulative time start was reset to 0, meaning the
computer had been judged to run for an impossibly long time.
- If a computer hit the terminate threshold, but not the hard abort
one, then we'd print the stack trace of the terminated thread - we
now do it before interrupting.
There's still race conditions here when terminating a computer, but
hopefully these changes will mean they never occur under normal
operations (only when a computer has run for far too long).
- Fix the timeout error message displaying utter rot.
- Don't resize the runner array. We don't handle this correctly, so
we shouldn't handle it at all.
- Increment virtualRuntime after a task has executed.
- The computer queue is a priority queue sorted by "virtual runtime".
- Virtual runtime is based on the time this task has executed, divided
by the number of pending tasks.
- We try to execute every task within a given period. Each computer is
allocated a fair share of that period, depending how many tasks are
in the queue. Once a computer has used more than that period, the
computer is paused and the next one resumed.
TimeoutState now introduces a TIMESLICE, which is the maximum period of
time a computer can run before we will look into pausing it.
When we have executed a task for more than this period, and if there are
other computers waiting to execute work, then we will suspend the
machine.
Suspending the machine sets a flag on the ComputerExecutor, and pauses
the "cumulative" time - the time spent handling this particular event.
When resuming the machine, we restart our timer and resume the machine.
Oh goodness, when will it end?
- Computer errors are shown in red.
- Lua machine operations provide whether they succeeded, and an
optional error message (reason bios failed to load, timeout error,
another Lua error), which is then shown to the user.
- Clear the Cobalt "thrown soft abort" flag when resuming, rather than
every n instructions.
- Computers will clear their "should start" flag once the time has
expired, irrespective of whether it turned on or not. Before
computers would immediately restart after shutting down if the flag
had been set much earlier.
Errors within the Lua machine are displayed in a more friendly
When closing a BufferedWriter, we close the underlying writer. As we're
using channels, this is an instance of sun.nio.cs.StreamEncoder. This
will attempt to flush the pending character.
However, if throwing an exception within .write errors, the flush will
fail and so the underlying stream is not closed. This was causing us to
leak file descriptors.
We fix this by introducing ChannelWrappers - this holds the wrapper
object (say, a BufferedWriter) and underlying channel. When closed, we
dispose of the wrapper, and then the channel. You could think of this as
doing a nested try-with-resources, rather than a single one.
Note, this is not related to JDK-6378948 - this occurs in the underlying
stream encoder instead.
- TimeoutState uses nanoseconds rather than milliseconds. While this is
slightly less efficient on Windows, it's a) not the bottleneck of Lua
execution and b) we need a monotonic counter, otherwise we could
fail to terminate computers if the time changes.
- Add an exception handler to all threads.
- Document several classes a little better - I'm not sure how useful
all of these are, but _hopefully_ it'll make the internals a little
more accessible.
- Move state management (turnOn, shutdown, etc...) event handling and
the command queue into a ComputerExecutor
- This means the computer thread now just handles running "work" on
computer executors, rather than managing a separate command queue +
requeuing it.
- Instead of setting soft/hard timeouts on the ILuaMachine, we instead
provide it with a TimeoutState instance. This holds the current abort
flags, which can then be polled within debug hooks.
This means the Lua machine has to do less state management, but also
allows a more flexible implementation of aborts.
- Soft aborts are now handled by the TimeoutState - we track when the
task was started, and now only need to check we're more than 7s since
then.
Note, these timers work with millisecond granularity, rather than
nano, as this invokes substantially less overhead.
- Instead of having n runners being observed with n managers, we now
have n runners and 1 manager (or Monitor).
The runners are now responsible for pulling work from the queue. When
the start to execute a task, they set the time execution commenced.
The monitor then just checks each runner every 0.1s and handles hard
aborts (or killing the thread if need be).
- Rename unload -> close to be a little more consistent
- Make pollAndResetChanged be atomic, so we don't need to aquire a lock
- Get the computer queue from the task owner, rather than a separate
argument.
Ideally we'd add a couple more tests in the future, but this'll do for
now.
The bootstrap class is largely yoinked from CCTweaks-Lua, so is a tad
ugly. It works though.
We now generate a table and concatinate the elements together. This has
several benefits:
- We no longer emit emit trailing spaces, which caused issues on 1.13's
command system.
- We no longer need the error level variable, nor have the weird
recursion system - it's just easier to understand.
Prior to this change we would schedule a new task which attached
peripherals on the ComputerThread on the empty task queue. This had a
couple of issues:
- Slow running tasks on the computer thread could result in delays in
peripherals being attached (technically, though rarely seen in
practice).
- Now that the ComputerThread runs tasks at once, there was a race
condition in computers being turned on/off and peripherals being
attached/detached.
Note, while the documentation said that peripherals would only be
(at|de)tached on the computer thread, wired modems would attach on the
server thread, so this was not the case in practice.
One should be aware that peripherals are still detached on the
computer thread, most notably when turning a computer on/off.
This is almost definitely going to break some less well-behaved mods,
and possible some of the well behaved ones. I've tested this on SC, so
it definitely works fine with Computronics and Plethora.
- Restrict what items can be inserted into printers. They're now closer
to brewing stands or furnaces: nothing can go in the output slot,
only ink in the ink slot, and only paper in the paper slot.
- Fix build.gradle using the wrong version
- Trim the width of tables to fit when displaying on the client. Closes
#45. Note, our solution isn't perfect, as it will wordwrap too, but
it's adaquate for now.
When a turtle was unloaded but not actually disposed of, the
m_peripheral map hangs around. As a result, when creating a new
ServerComputer, the peripherals aren't considered changed and so they're
never attached.
Fixes#50.
Also fix that blumin' deprecated method which has been around for a wee
while now.
The Computer class currently has several resposiblities such as storing
id/label, managing redstone/peirpherals, handling management of the
computer (on/off/events) and updating the output.
In order to simplify this a little bit, we move our IAPIEnvironment
implementation into a separate file, and store all "world state"
(redstone + peripherals) in there. While we still need to have some
level of updating them within the main Computer instance, it's
substantially simpler.
- Fire close events instead of failure when open websockets error.
- Handle ping events. I thought I was doing this already, but this
requires a WebsocketProtocolHandler. Fixes#118
- Run optipng on all our images. This has very little effect on most of
them (as they're all so small anyway), but has resulted in a 50%
reduction in some cases.
- Run Proguard on our shadowed dependencies (Cobalt).
- Minify our JSON files, stripping all whitespace. This is mostly
useful for FML's annotation cache, as that's a massive file, but
still a semi-useful optimisation to make.
This has helped reduce the jar by about 110kb, which isn't much but
still feels somewhat worth it.
The latest version of Cobalt has several major changes, which I'm
looking forward to taking advantage of in the coming months:
- The Lua interpreter has been split up from the actual LuaClosure
instance. It now runs multiple functions within one loop, handling
pushing/popping and resuming method calls correctly.
This means we have a theoretically infinite call depth, as we're no
longer bounded by Java's stack size. In reality, this is limited to
32767 (Short.MAX_VALUE), as that's a mostly equivalent to the limits
PUC Lua exposes.
- The stack is no longer unwound in the event of errors. This both
simplifies error handling (not that CC:T needs to care about that)
but also means one can call debug.traceback on a now-dead coroutine
(which is more useful for debugging than using xpcall).
- Most significantly, coroutines are no longer each run on a dedicated
thread. Instead, yielding or resuming throws an exception to unwind
the Java stack and switches to a different coroutine.
In order to preserve compatability with CC's assumption about LuaJ's
threading model (namely that yielding blocks the thread), we also
provide a yieldBlock method (which CC:T consumes). This suspends the
current thread and switches execution to a new thread (see
SquidDev/Cobalt@b5ddf164f1 for more
details). While this does mean we need to use more than 1 thread,
it's still /substantially/ less than would otherwise be needed.
We've been running these changes on SwitchCraft for a few days now and
haven't seen any issues. One nice thing to observe is that the number of
CC thread has gone down from ~1.9k to ~100 (of those, ~70 are dedicated
to running coroutines). Similarly, the server has gone from generating
~15k threads over its lifetime, to ~3k. While this is still a lot, it's
a substantial improvement.
This is far more elegant than our weird method of baking things and
manually inserting them into the model map. Also means we no longer need
the whole turtle_dynamic thing.
We moved the direction call within the if block, but never actally
updated the condition! I'm on a roll of stupid bug fixes today, which
really isn't a good sign.
- Only have computers implement custom block drop logic: everything
else only drops in creative mode.
- Fix redstone inputs not being received correctly. Introduced in
8b86a954ee, yes I'm a silly billy.
- Only update the neighbour which changed.
- Convert terminals from a polling-based system to a more event-driven
one: they now accept an onChanged callback, which marks the parent as
dirty.
- Schedule ticks when monitors are marked as dirty.
- Add several missing @Overrides. This has nothing to do with the rest
of the changes, but I'm bad at good git practice.
- Merge BlockPeripheralBase and BlockPeripheral, as no other classes
extended the former.
- Make BlockPeripheral use ITilePeripheral instead of
TilePeripheralBase. This allows us to use other, non-ticking tiles
instead.
- Convert advanced and normal modems to extend from a generic
TileWirelessModemBase class, and thus neither now tick.
- Move getPeripheralType and getLabel from IPeripheralTile to
TilePeripheralBase. These were mostly constant on all other tiles, so
were rather redundant.
- Make TileAdvancedModem extend TileGeneric, and be non-ticking (using
similar logic to all other blocks).
- Move updateTick onto BlockGeneric/TileGeneric instead of the full
wired modem, as it is used by several tiles now.
- Make *Cable extend from *Generic, and schedule ticks instead of
running every tick.
We currently generate the crafting item once when the upgrade is first
created, and cache it for the duration of the game. As the item never
changes throughout the game, and constructing a stack is a little
expensive (we need to fire an event, etc...), the caching is worth
having.
However, some mods may register capabilities after we've constructed our
ItemStack. This means the capability will be present on other items but
not ours, meaning they are not considered equivalent, and thus the item
cannot be equipped.
In order to avoid this, we use compare items using their share-tag, like
Forge's IngredientNBT. This means the items must still be "mostly" the
same (same enchantements, etc...), but allow differing capabilities.
See NillerMedDild/Enigmatica2Expert#655 for the original bug report -
in this case, Astral Sourcery was registering the capability in init,
but we construct upgrades just before then.
- Move IDirectionalTile constraint from IPeripheralTile to
TilePeripheralBase.
- Make *WiredModemFull no longer inherit from *PeripheralBase. While
there is still some shared logic (namely in the syncing of "anim"),
it's largely fine as we don't store label or direction in NBT.
- Add a TickScheduler. This is a thread-safe version of
World.scheduleUpdate. We simply build a set of all TEs, and schedule
them to be updated the next tick.
- Make ModemState receive an "onChanged" listener, which is fired
whenever the modem changes.
- Make WiredModemFull no longer tick, instead scheduling updates when
it is first loaded and whenever the modem changes.
FileSystemMount was originally added to allow using ReadableByteChannels
instead of InputStreams. However, as zip files do not allow seeking,
there is no benefit of using them over the original JarMount (which we
need to preserve for backwards compatibility).
Instead of maintaining two near-identical mounts, we remove the
FileSystemMount and rewrite the JarMount implementation with several
improvements:
- Rewrite the jar scanning algorithm to be closer to 1.13+'s data pack
mount. This means we no longer require the jar file to have
directories before the file (though this was not a problem in
practice).
- Add all JarMounts to a ReferenceQueue, closing up the ZipFile when
they have been garbage collected (fixes#100).
- Cache the contents of all files for 60 seconds (with some constraints
on size). This allows us to seek on ROM files too (assuming they are
small), by reading the whole thing into memory.
The cache is shared across all mounts, and has a 64MiB limit, and
thus should not have an adverse impact on memory.
This is done in 1.13+ for items and blocks, so we might as well do it
for upgrades now. Note we can't do it for ender pocket modems, as the
upgrade ID is spelled incorrectly there.
- For those where placement is stored in the metadata (computers),
don't also set it in onBlockPlacedBy.
- Remove .getDefaultState(int, EnumFacing) override, as this means we
have more control over what is passed to us (namely, placer's
direction too).
"/computercraf" auto-completes to "/computercraft_copy" instead of
"/computercraft", which is rather annoying, as the former is not meant
to be used normally.
It's rather embarassing that it's been restructured _again_, but I think
this is a nice middle-ground. The previous implementation was written
mostly for Fabric, which doesn't always map perfectly to Forge.
- Move the message identifier into the registration phrase. It's not
really a property of the message itself, rather a property of the
registry, so better suited there.
- Move message handling into the message itself. Honestly, it was just
ending up being rather messy mixing the logic in two places.
This also means we can drop some proxy methods, as it's easier to
have conditionally loaded methods.
- Move network registry into a dedicated class, as that's what we're
doing for everything else.
This means we can avoid several rather ugly instances of getItemBlock
and a cast. We also derive the ItemBlock's registered name from the
block's name, which makes the register a little less ugly.
- Move the "world directory" getter out of the proxy - we can just use
Forge's code here.
- Remove the server proxies, as both were empty. We don't tend to
register any dedicated-server specific code, so I think we can leave
them out.
- All "named" entries (blocks, items, recipes, TEs and pocket/turtle
upgrades) are registeredin one place.
- Most client side models/textures are registered in ClientRegistry -
we can't do item colours or TEs for now, as these aren't event based.
- A little cleanup to how we handle ItemPocketComputer models.
This offers several advantages
- Less registration code: the subscribers are reigstered automatically,
and we don't need to worry about sided-proxies.
- We no longer have so many .instance() calls.
- Move SpeakerPeripheral's TileSpeaker functionality to a sub-class.
- Use Vec3d instead of BlockPos for speaker's positions.
- Use WorldUtil.dropItemStack to spawn in items.
- Remove redundant lock on ModemPeripheral.
- 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.
While Plethora has been updated to no longer require these, it's
probably worth keeping them around a little longer, as people may not
upgrade them in sync.
We've had this on SC for most of a year now (and SC 1 for most of its
lifetime) and not seen any issues. I'm fairly confident that it does not
allow breaking the sandbox.
- Move configuration loading into a separate file, just so it doesn't
clutter up ComputerCraft.java.
- Normalise property names, so they're all snake_case.
- Split properties into separate categories (http, turtle, peripheral),
so the main one is less cluttered.
- Define an explicit ordering of each category.
- Provide whether a message was binary or text in websocket_message
and handle.receive(). (Fixes#96)
- Provide an optional reason and status code within the websocket_close
event.
Off topic, but also cleanup the file handles a little.
- Remove redundant constructors and super calls
- Standardise naming of texture fields
- Always use postfix notations for loops
- Cleanup several peripheral classes
Previously we would send computer state (labels, id, on/off) through the
ClientComputer rather than as part of the TE description. While this
mostly worked fine, it did end up making things more complex than they
needed to be.
We sync most data to the tile each tick, so there's little risk of
things getting out of date.
There's several reasons for this change:
- Try to make ComputerCraft.java less monolithic by moving
functionality into separate module-specific classes.
- Hopefully make the core class less Minecraft dependent, meaning
emulators are a little less dependent on anything outside of /core.
Note we still need /some/ methods in the main ComputerCraft class in
order to maintain backwards compatibility with Plethora and
Computronics.
Many bits of IInventory (open/close, fields, etc...) are not actually
needed most implementations, so we can clean things up a little with a
common interface.
Some methods act the same on both sides, and so can be in utility
classes. Others are only needed on one side, and so do not really need
to be part of the proxy.
- Remove TurtleVisionCamera. It would be possible to add this back in
the future, but for now it is unused and so should be removed.
- Move frame info (cursor blink, current render frame) into a
FrameInfo class.
- Move record methods (name, playing a record) into a RecordUtil class.
- getPickBlock is now implemented directly on computers and turtles,
rather than on the tile.
- Bounding boxes are handled on the block rather than tile. This ends
up being a little ugly in the case of BlockPeripheral, but it's not
the end of the world.
- Explosion resistance is only implemented for turtles now.
- Replace BlockCableCableVariant with a boolean, removing any custom
logic around it.
- Replace our previous cable Forge-blockstate with a vanilla one, which
handles cable connections in the model logic.
This ends up being slightly cleaner as we can rely on Minecraft's own
model dependency system. Also reduces reliance on Forge's APIs, which
_potentially_ makes porting a little easier.
- Remove the two redstone commands. These are not used (maybe only by
CCEdu), and so are somewhat redundant.
- Inline the select command, converting it to a lambda.
- Inline the attack/dig commands, as they did little more than wrap the
tool command.
As CCEdu has not been updated, and is unlikely to be updated as Dan does
not have the rights to open source it, we're removing explicit support
for now.
If an alternative arises in the future, it would be good to support, but
in a way which requires less workarounds in CC's core.
Most upgrades provides a couple of constant getters (upgrade ID,
adjective, crafting item). We move the getters into a parent class and
pass the values in via the constructor instead.
Also do a tiny bit of cleanup to the upgrades. Mostly just reducing
nesting, renaming fields, etc...
- Only generate resource pack mounts if the desired directory exists.
- Allow mounting files, as well as directories (fixes#90).
As always, also a wee bit of cleanup to some of the surrounding code.
This allows us to block JEI processing key events such as "o", meaning
the GUI is not constantly toggled when interacting with a turtle.
Also clean up the widget code, as there's a lot of functionality here
which only is needed in CCEdu.
This is implemented in a rather ugly way: we register a client command
(/computercraft_copy) which updates the clipboard, and run that via a
click handler on the chat message.
This hopefully makes wired modems a little easier to use. We'll see.
I don't think anyone has actually ended up using this, so it's unlikely
to break anything (though do tell me if this is the case). On the flip
side, this allows us to queue events on multiple computers, and means
we can provide a little more documentation.
Using turtle.suck on an inventory filled with tools would fill the
entire chest with said item, rather than extracting a single item. In
order to avoid that, we clamp the extract limit to the max stack size
when first extracting an item.
This also inlines the makeSlotList logic, which means we can avoid
creating an array for each inventory operation. This probably won't
have any meaninful performance impact (even on large inventories), but
is a nice optimisation to make.
- Remove a redundant logger
- Provide a getter for the ComputerCraft thread group. This allows us
to monitor child threads within prometheus.
- Replace a deprecated call with a fastutils alternative.
Some mods (*cough* Computronics *cough*) directly access this class,
rather than using the API. We add this back to ensure they still behave
as expected.
Truth be told, I can't really complain, as Plethora also does dodgy
thing with CC internals.
- Keep track of the number of created and destroyed coroutines for each
computer.
- Run coroutines with a thread pool executor, which will keep stale
threads around for 60 seconds. This substantially reduces the
pressure from short-lived coroutines.
- Update to the latest Cobalt version.
- Introduce a ModemState, which shares the open channels across all
modem instances of a wired modem.
- Keep a set of computers for all modem peripherals.
- Keep a map of computers -> (string, peripheral) for wired modem
peripherals. We shouldn't need this one, as you cannot attach one
modem to another, but it's good to be consistent.
One major change here is that modems will continue to be "on", even if
no computers are attached. This would substantially increase
implementation complexity, so I think this is an acceptable compromise
for now.
Should fix#74
Java configured the charset decoders/encoders for streams to REPLACE
malformed characters rather than the default REPORT. It does not do the
same for channels, and so we were catching an IO exception and returning
null.
We'd somehow added spaces, which means they weren't registered under the
computercraft domain (rather, the "computercraft " one). We also create
a datafixer to ensure old worlds are handled correctly.
- Rename openStreamFor* methods to more accurate openChannelFor*
- Fix ArrayByteChannel having an incorrect .position() implementation
Cherry-picked from the PR against dan200/ComputerCraft
- Add an argument to send which controls whether it's a binary message
or not. This is a little ugly, but it's probably more effective than
anything else.
- Fix binary frames not correctly queueing the correct data in the
message event.
Closes#69
The method to register new SoundEvents is private, which means that few
(if any) mods actually register them. Consequently, one could not use
the speaker to play any modded sound, as they weren't registered on the
server side.
Using SPacketCustomSound does mean we can no longer determine if a sound
exists or not, but I think a price I'm willing to pay in order to allow
playing modded sounds.
This replaces the existing IMount openFor* method with openChannelFor*
ones, which return an appropriate byte channel instead.
As channels are not correctly closed when GCed, we introduce a
FileSystemWrapper. We store a weak reference to this, and when it is
GCed or the file closed, we will remove it from our "open file" set and
ensure any underlying buffers are closed.
While this change may seem a little odd, it does introduce some
benefits:
- We can replace JarMount with a more general FileSystemMount. This
does assume a read-only file system, but could technically be used
for other sources.
- Add support for seekable (binary) handles. We can now look for
instances of SeekableByteChannel and dynamically add it. This works
for all binary filesystem and HTTP streams.
- Rewrite the io library to more accurately emulate PUC Lua's
implementation. We do not correctly implement some elements (most
noticably "*n", but it's a definite improvement.
This crash can be triggered remotely by specially constructed rednet messages, making this a bit of a problem, as any repeaters can be remotely crashed.
A lot of these don't actually have any effect as they'll only be called
on the main thread or they are getters where the state is guaranteed to
be consistent whenever it is accessed.
Hopefully this'll reduce the chance of world updates being blocked by
waiting for peripheral locks to be released.
- Make window.reposition's argument validation a little more strict.
Previously it would accept `window.reposition(x, y, width)` (no
height argument), just not act upon it.
- Use select instead of table.unpack within `pastebin run`.
- Use `parallel.waitForAny` instead of `waitForAll` within the dance
program.
- Pipe the entire help file into `textutils.pagedPrint`, rather than
doing it line by line.
- Remove bytecode loading disabling from bios.lua. This never worked
correctly, and serves little purpose as LuaJ is not vulnerable to
such exploits.
- Bump MinecraftForge version so we don't crash on load. Oh boy, all
the deprecation warnings.
- Inject IBundledEmitter and IBundledReceiver capabilities onto all
TileGenerics.
- Register a IBundledRedstoneProvider instance for IBundledEmitter.
This is a preliminary for updating to 1.13, as many of the name changes
apply to both. This will make it harder to remain consistent with
actual CC, though that will be less of a consideration when 1.13 hits.
When placing a sign against a tile entity (such as a turtle or chest),
we would consider that block the "placed" one instead, meaning the text
was never set. This solution isn't entirely ideal either, but short of
capturing block snapshots I'm not sure of a better solution.
Fixes#552