- Bump Cobalt to 0.6.0. We now track both line and column numbers of
each bytecode instruction, allowing us to map an error to a concrete
position.
- `loadfile` (and similar functions) now use the full path, rather than
the file name. Cobalt truncates this to 30 characters (rather than
the previous 60) so this should be less noisy.
- The shell, edit and Lua REPL now display the corresponding source
code alongside an error.
Note this is incredibly limited right now - it won't cope with errors
which cross coroutine boundaries. Supporting this is on the roadmap,
but requires some careful API design.
While it's a nice immersive interaction, it's far too easy to trigger by
accident. Dying/undying can now only be done via crafting and the
cauldron.
Closes#1321
It's much less aggressive than dunking it in a cauldron, so won't damage
any of your precious electronics.
I had this idea back in 2017 (dan200/ComputerCraft#230). Can't believe
it took me almost 6 years to implement.
In older versions we just used a hard-coded list of items and
superclasses. This was somewhat ugly, and so in 1.19.3 I tried to make
this code more generic.
However, this has a lot of unintended consequences - for instance
turtles can now throw ender pearls, which is definitely not intended!
By using a tag, we can emulate the old behaviour, while still allowing
modders and pack devs to add additional items if needed.
- Encode the DFA as a virtual machine (identical to lrgrep) rather than
compiling it to a series of Lua functions. While this is a little
slower and uglier, it's much more space efficient, shaving off 16Kb.
- Minimise the DFA properly. This only shaves off a few states, but
every little helps.
- Run the error handling code from a non-reduced parser stack. This was
incredibly nasty to get right (and positions are still not correctly
handled), but it fixes several broken error messages.
- Move modem recipes out of the usage section.
- Add missing argument names to BinaryWriableHandle.write. Illuaminate
really should catch this, but for now I did a grep and couldn't find
any more instances of this.
- Add several (internal) modules for lexing and parsing Lua code. These
allow us to provide (hopefully) higher quality error messages than
Lua's built-in messages.
- `shell.run`, `edit` and `lua` now use this parser when fed invalid
code. This allows us to provide better syntax errors, while not
having any impact on the happy path.
Note this does not affect any other mechanism for loading code
(`load`, `require`, `dofile`).
There's still a lot of work to do here in improving error message
quality, but hopefully this provides a good starting point.
- Document the thread safety of DetailRegistry a little better.
- Turtles now duplicate their inventory to the "previous
inventory" (now called inventorySnapshot) immediately, rather than
when the block is ticked.
This is slightly more resource intensive, but I don't think it's so
bad we need to worry.
- As this snapshot is now always up-to-date, we can read it from the
computer thread. Given the item is immutable, it's safe to read NBT
from it.
_Technically_ this is not safe under the Java memory model, but in
practice I don't think we'll observe the wrong value.
Closes#1306
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/
When the peripheral is attached, we add the computer to the map and
queue the actual disk to be mounted next tick. This avoids the
thread-safety issues with mutating the item (and creating disk ids) that
might be caused by doing it on the computer thread.
The mount is now also managed separately to the MediaStack, as that was
meant to be an immutable snapshot of the item!
Fixes#1282
This gives us slightly better guarantees that the config has actually
been loaded. This, along with a FCAP bump, fixes this config option
not doing anything on Fabric.
I originally put cc.import in a separate directory from the main
modules. This means that programs must extend the package path in order
to import these modules.
However, this ends up being a mixed blessing: while it makes it much
harder for users to accidentally require user code, it also means we
can't expose a public interface which wraps a private module.
Instead, cc.import now lives on the main package path, but lives under
the cc.internal namespace and is not documented anywhere. Hopefully this
should be enough of a clue that one shouldn't use it :p.
I was having issues where dropped items would clip into blocks when
dropped, and then phase upwards through the turtle instead. This makes
things a little more consistent with dispenser behaviour.
Instead of taking control of the breaking logic in all cases, we now
only do so when we have both a cable and modem. This allows us to fall
back to default vanilla behaviour and so correctly drop the modem/cable
item.
We now call getLevel() when attaching the peripheral, so need the
position to be available immediately. Fixes#1274.
I /think/ the entity should always be present, as peripherals are
only created on startup or when calling pocket.equipBack, both of which
require a player.[^1]
I suspect this was a little broken before (the level wouldn't be
available if a modem received a message before the position had
been set), but that would be much rarer.
I'm not 100% convinced about the thread-safety of this code (the writes
to level may not be immediately visible on other threads), so may need
to think about that.
[^1]: Note that when peripherals come to be /attached/ they may no
longer have a player (as there's a gap between turning a computer on and
it actually starting). However, the level/position will have been
initialised by then, so this isn't a problem.
Use `InteractionResult.sidedSuccess` / `.CONSUME` where applicable instead of `.SUCCESS`. This prevents the server from sending an additional swing animation packet to the client. Normally this isn't a problem, since the client will de-duplicate swing packets if they are within the animation duration of the currently playing swing; however, when connected to a server with a high ping the packet is sent after the animation is already finished on the client, resulting in a duplicate animation.
We now perform movement translations before rendering the label, rather
than afterwards. This means the label moves smoothly(ish), rather than
jumping from block to block.
I've been meaning to fix this for over 6 years, and just kept
forgetting.
Previously ILuaContext.executeMainThreadTask worked by running
ILuaContext.issueMainThreadTask, pulling task_complete events, and then
returning the results.
While this makes the implementation simple, it means that the task's
results were converted into Lua values (in order to queue the event) and
then back into Java ones (when the event was pulled), before eventually
being converted into Lua once more.
Not only is this inefficient, as roundtripping isn't lossless, you
couldn't return functions or rich objects from main thread functions
(see https://github.com/dan200/ComputerCraft/issues/125).
We now store the return value on the Java side and then return that when
the receiving the task_complete event - the event no longer carries the
result. Note this does not affect methods using issueMainThreadTask!
- Fix client classes not being included in Forge.
- Only remap Nettty's HTTP classes, not all of them. This feels a
little more error prone - maybe we should jar-in-jar this in the
future.
- Use the correct refmaps on Forge.
- Prevent the Fabric jar pulling in some other mods.
Closes#1247
- Correctly handle FileOperationExceptions for the root mount.
- Remove some checks from MountWrapper: Mount/WritableMount should do
these already!
- Normalise file paths, always using a '/'.
- Separate FileMount into separate FileMount and WritableFileMount
classes. This separates the (relatively simple) read-only code from
the (soon to be even more complex) read/write code.
It also allows you to create read-only mounts which don't bother with
filesystem accounting, which is nice.
- Make openForWrite/openForAppend always return a SeekableFileHandle.
Appendable files still cannot be seeked within, but that check is now
done on the FS side.
- Refactor the various mount tests to live in test contract interfaces,
allowing us to reuse them between mounts.
- Clean up our error handling a little better. (Most) file-specific code
has been moved to FileMount, and ArchiveMount-derived classes now
throw correct path-localised exceptions.
Currently published under 1.102.0-SNAPSHOT if anybody wants/needs to
poke. I'm going to break Mount/WritableMount, but everything else should
be stable!
Lots of minor changes, but nothing too nasty - just tedious.
Known bugs/issues:
- REI and JEI haven't been updated at the time of writing, so our usage
of their APIs may be incompatible.
- Crash when opening the config UI in Fabric, as forgeconfigapi-port
hasn't been updated yet.
Will hold off on doing a release until those mods have updated.
- Flip http.websocket and http.websocketAsync docs (fixes#1244)
- Fix http.request queuing a http_failure event with no URL when
passing a malformed URL
- Fix http.websocketAsync not queuing websocket_failure events on
immediate failure.
In classic squid tradition: 20% code, and 80% test logic.
Closes#962. Alas, whoever reported this has deleted their account, so
they can't even be happy about it :(.
- Update ForgeConfigAPI to the latest version, to fix the race
condition.
- Move WirelessNetwork lifecycle management to ServerContext.
- Some doc fixes.
- Remove deprecated API members in prep for 1.19.3. This allows us to
remove the mc-stubs and forge-stubs projects.
- Make several methods take a MinecraftServer instead of a Level (or
nothing at all).
- Remove I prefixes from a whole bunch of interfaces, making things a
little more consistent with Java conventions.
This avoids touching the "main" interfaces people consume for now. I
want to do that another Minecraft version, to avoid making the update
too painful.
- Remove IFileSystem and associated getters. This has never worked very
well and I don't think has got much (any?) usage.
I kinda hate this, but not sure what else to do. It might be worth
rewriting sanitizePath in the future to loop through the string once,
but I think this is good enough for now.
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.
- Ensure they're correctly synced to the client. This definitely isn't
comprehensive, but doing anything further probably involves multiple
players, which is tricky.
- Quick rendering test for in-hand computers.
Forge requires the file to be in the root of the jar, hence doing it
this way round. The icon is read using ModContainer.findPath, so this
shouldn't conflict with other mods.
Love being on the bleedin' edge. More importantly, this fixes a couple
of issues:
- Translations are loaded on the server, meaning .getItemDetail
correctly translates modded items.
- Shulker boxes cannot be moved inside other shulker boxes using the
transfer API.
- Start using Fab API's ItemStack.getRecipeRemainder().
I was originally pretty sceptical about this, but it actually ends up
being useful for the same reason any other form of datagen is: we can
ensure that names are well formed, and that every string is actually
translated.
There's some future work here to go through all the custom translation
keys and move them into constants (maybe also do something with the
/computercraft command?), but that's a separate chunk of work.
The main motivation for this is to add translation keys to our config:
the Fabric version of Forge Config API provides a config UI, so it's
useful to provide user-friendly strings. Our generator also
automatically copies comments over, turning them into tooltips.
This also updates all of the other language files to match en_us.json
again: it's a very noisy diff as the file is now sorted alphabetically.
Hopefully this won't affect weblate though
[^1]: Amusing really that the Fabric port actually is more useful than
the original.
- Add a new ClientJavaExec Gradle task, which is used for client-side
tests. This:
- Copies the exec spec from another JavaExec task.
- Sets some additional system properties to configure on gametest framework.
- Runs Java inside an X framebuffer (when available), meaning we
don't need to spin up a new window.
We also configure this task so that only one instance can run at
once, meaning we don't spawn multiple MC windows at once!
- Port our 1.16 client test framework to 1.19. This is mostly the same
as before, but screenshots no longer do a golden test: they /just/
write to a folder. Screenshots are compared manually afterwards.
This is still pretty brittle, and there's a lot of sleeps scattered
around in the code. It's not clear how well this will play on CI.
- Roll our own game test loader, rather than relying on the mod loader
to do it for us. This ensures that loading is consistent between
platforms (we already had to do some hacks for Forge) and makes it
easier to provide custom logic for loading client-only tests.
- Run several client tests (namely those involving monitor rendering)
against Sodium and Iris too. There's some nastiness here to set up
new Loom run configurations and automatically configure Iris to use
Complementary Shaders, but it's not too bad. These tests /don't/ run
on CI, so it doesn't need to be as reliable.
- Bundle the core API inside the Fabric API jar for now, to ensure
that ResourceLocation is remapped.
- Add a dummy fabric.mod.json file to the API. We'll remove this once
https://github.com/FabricMC/fabric-loom/pull/749 is released.
This fixes several issues I had with consuming multi-loader CC:T in
various upstream mods.
- Include /all/ sources in the Forge/Fabric jar. Before it was just the
common classes, and not the core or API.
- Use some Gradle magic to remove superfluous dependencies from the POM
file. Also make sure Cobalt and Netty are present as dependencies.
- Start using minimize() in our shadow jar config again.
- Add support for Fabric. This is mostly pretty simple, though does
require a lot more mixins than Forge.
Half this diff is due to data generators: we run them separately as
some aspects (recipes mostly) are different between the loaders.
- Add integration with Iris (same as our Oculus support) and REI
(mostly the same as our JEI support).
- Generic peripherals only support inventories (or rather
InventoryStorage) right now. Supporting more of the Fabric storage
API is going to be tricky due to the slotted nature of the API: maybe
something to revisit after Transfer API V3 (V4?, I've lost track).
Note, this does /not/ mean I will be publishing a Fabric version of
CC:T. My plan is to rebase CC:R on top of this, hopefully simplifying
the maintenance work on their end and making the two mods a little more
consistent.
My working tree is a mess, so this is not a good commit. I'm making a
bit of a habit of this.
- Fix UserLevel.OWNER check failing on single player servers.
- Correctly handle the "open folder" fake command.
- Some reshuffling of Forge-specific methods to make Fabric slightly
easier.
This commit got away from me, okay? No, I'm not proud of it either.
- Remove our overrides of handleUpdate tag: we now try to detect
whether we're on the client or server inside BlockEntity.load. Alas,
this is needed for Fabric.
- Remove BlockGeneric/TileGeneric entirely: we've slowly whittled this
down over the years, and nowadays we can get away with putting most
of its functionality into subclasses.
This allows us to do some nice things with overriding HorizontalBlock
(or our new HorizontalContainerBlock class), rather than
reimplementing functionality in each class. Though it would be nice
if Java had some sort of trait system :D:
- Simplify a lot of our container class so it's just defined in terms
of a NonNullList<ItemStack>. This also includes a total rewrite of
the disk drive which I'm not ... thrilled about. It ended up being
easier to copy the code from the mc-next branch :D:.
- Try to test some of the gnarly bits of this. Still a /lot/ more to be
done with testing this.
Closes#658
After several weeks of carefully arranging ribbons, we pull the string
and end up with, ... a bit of a messy bow. There were still some things
I'd missed.
- Split the mod into a common (vanilla-only) project and Forge-specific
project. This gives us room to add Fabric support later on.
- Split the project into main/client source sets. This is not currently
statically checked: we'll do that soon.
- Rename block/item/tile entities to use suffixes rather than prefixes.
- TurtlePlayer now returns a fake player, rather than extending from
Forge's implementation.
- Remove "turtle obeys block protection" config option.
- Put some of the more complex turtle actions behind the
PlatformHelper.
Another ugly commit, not thrilled about it:
- Move all config values to a separate Config class.
- Replace ComputerCraft.log with class-specific loggers.
- Replace ComputerCraft.MOD_ID with ComputerCraftAPI.MOD_ID
It's kinda funny looking at all the pre-CC:T proxy code, how much this
has come full circle. I think this design is nicer than what 1.12 did,
but it's still slighly embarassing.
- Add a new ContainerTransfer class to handle moving items between
containers. This is now used for turtle.drop/turtle.suck as well as
inventory methods.
- Any other usages of IItemHandler (which are mostly on turtle
inventories) now use Container and a couple of helper methods.
- Publish javadoc again: for now this is just the common-api
- Remove all dependencies from the published Forge jar. This is
technically not needed (fg.deobf does this anyway), but seems
sensible.
While this does now involve a little more indirection, by having a
single location for all hooks it's much easier to keep event listeners
consistent between loaders.
The diff is pretty noisy (I've inlined some classes, and ClientRegistry
got a big restructure), but functionality should be the same.
Previously we overrode getCapability on our BlockEntity implementations.
While this is the Proper way to do things, it's obviously impossible to
do in a multi-loader environment.
We now subscribe to the AttachCapabilitiesEvent and add our caps that
way. This does require[^1] some nasty invalidation of caps in a couple
of places, which I'm not wild about.
[^1]: I'm not actually sure it does: we invalidate peripherals and wired
elements when neighbours change, so the explicit invalidation probably
isn't useful.
NetworkMessage follows vanilla's Packet much more closely now: the
handler takes a context argument, which varies between the client and
server.
- The server handler just returns the ServerPlayer who sent the
message.
- The client context provides handleXyz(...) methods for each
clientbound packet. Our packet subclasses call the appropriate
method - the implementation of which contains the actual
implementation.
Doing this allows us to move a whole bunch of client-specific code into
the main client package, dropping several @OnlyIn annotations and
generally reducing the risk of accidentally loading client classes on
the server.
We also abstract out some packet sending and general networking code to
make it easier to use in a multi-loader context.
- Replace our usages of DeferredRegistry with a custom
RegistrationHelper. This effectively behaves the same, just without
any references to Forge code!
- Replace any references to ForgeRegistries with a home-grown
Registries class. This just fetches the underlying registry and
proxies the method calls.
- Change recipe serialisers and loot item conditions to be registered
the same way as other entries.
- Move any Forge specific registration code off to the main
ComputerCraft class.
This adds two new modules: common-api and forge-api, which contain the
common and Forge-specific interfaces for CC's Minecraft-specific API.
We add a new PlatformHelper interface, which abstracts over some of the
loader-specific functionality, such as reading registries[^1] or calling
Forge-specific methods. This interface is then implemented in the main
mod, and loaded via ServiceLoaders.
Some other notes on this:
- We now split shared and client-specific source code into separate
modules. This is to make it harder to reference client code on the
server, thus crashing the game.
Eventually we'll split the main mod up too into separate source sets
- this is, of course, a much bigger problem!
- There's currently some nastiness here due to wanting to preserve
binary compatibility of the API. We'll hopefully be able to remove
this when 1.19.3 releases.
- In order to build a separate Forge-specific API jar, we compile the
common sources twice: once for the common jar and once for the Forge
jar.
Getting this to play nicely with IDEs is a little tricky and so we
provide a cct.inlineProject(...) helper to handle everything.
[^1]: We /can/ do this with vanilla's APIs, but it gives a lot of
deprecation warnings. It just ends up being nicer to abstract over it.
We'll do this everywhere eventually, but much easier to do it
incrementally:
- Use checker framework to default all field/methods/parameters to
@Nonnull.
- Start using ErrorProne[1] and NullAway[2] to check for possible null
pointer issues. I did look into using CheckerFramework, but it's much
stricter (i.e. it's actually Correct). This is technically good, but
is a much steeper migration path, which I'm not sure we're prepared
for yet!
[1]: https://github.com/google/error-prone
[2]: https://github.com/uber/NullAway
It should be possible to consume the ComputerCraft's core (i.e.
non-Minecraft code) in other projects, such as emulators. While this
has been possible for years, it's somewhat tricky from a maintenance
perspective - it's very easy to accidentally add an MC dependency
somewhere!
By publishing a separate "core" jar, we can better distinguish the
boundaries between our Lua runtime and the Minecraft-specific code.
Ideally we could have one core project (rather than separate core and
core-api modules), and publish a separate "api" jar, like we do for the
main mod. However, this isn't really possible to express using Maven
dependencies, and so we must resort to this system.
Of course, this is kinda what the Java module system is meant to solve,
but unfortunately getting that working with Minecraft is infeasible.
- Move core-specific config options to a separate CoreConfig class.
- Use class-specific loggers, instead of a global one.
- Use log markers instead of a logComputerErrors option.
- Switch to a fairly standard code format. This is largely based on
IntelliJ defaults, with some minor tweaks applied via editor config.
Should mean people don't need to import a config!
- Use "var" everywhere instead of explicit types. Type inference is a
joy, and I intend to use it to its fullest.
- Start using switch expressions: we couldn't use them before because
IntelliJ does silly things with our previous brace style, but now we
have the luxury of them!
- Switch to using OptionalInt/OptionalLong instead of @Nullable
Long/Integers. I know IntelliJ complains, but it avoids the risk of
implicit unboxing.
- Instead of mutating PartialOptions, we now define a merge() function
which returns the new options. This simplifies the logic in
AddressRule a whole bunch.
This is a noisier diff than I'd like as this is just a direct copy from
the multi-loader branch.
- Rename "ingame" package to "gametest"
- Don't chain GameTestSequence methods - it's actually much cleaner if
we just use Kotlin's implicit this syntax.
- Use our work in 71f81e1201 to write
computer tests using Kotlin instead of Lua. This means all the logic
is in one place, which is nice!
- Add a couple more tests for some of the more error-prone bits of
functionality.
This is an initial step before refactoring this into a separate module.
It's definitely not complete - there's a lot of work needed to remove
referneces to the main ComputerCraft class for instance - but is a
useful first step.
I still don't really understand why the ROOT locale is wrong here, but
there we go. We'll need to remember to uncomment the tests on the 1.18
branch!
Also add some code to map tests back to their definition side. Alas,
this only links to the file right now, not the correct line :/.
This offers very few advantages now, but helps support the following in
the future:
- Reuse test support code across multiple projects (useful for
multi-loader).
- Allow using test fixture code in testMod. We've got a version of our
gametest which use Kotlin instead of Lua for asserting computer
behaviour.
We can't use java-test-fixtures here for Forge reasons, so have to roll
our own version. Alas.
- Add an ILuaMachine implementation which runs Kotlin coroutines
instead. We can use this for testing asynchronous APIs. This also
replaces the FakeComputerManager.
- Move most things in the .support module to .test.core. We need to use
a separate package in order to cope with Java 9 modules (again,
thanks Forge).
This allows other mods to create wired-modem alike blocks, which expose
peripherals on the wired network, without having to reimplement the main
modem interface.
This is not currently documented, but a peripheral_hub should provide
the following methods:
- isPresentRemote
- getTypeRemote
- hasTypeRemote
- getMethodsRemote
- callRemote
- 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.
- Use <p> everywhere. This is uglier, but also technically more
correct. This requires a version bump to cct-javadoc, and will give
me a massive headache when merging.
- Link against the existing OpenJDK docs.
We now wait for workers to terminate when closing the computer thread.
I'll be honest, I'm not happy with this code. Multi-threading is really
hard to get right, and I can't say I'm convinced this is especially well
behaved. I did look at trying to model this in TLA+, but in the end
decided it wasn't worth it.
In the future we probably want to split ComputerExecutor into two
objects, where one is our entry in the ComputerThread queue (and so
holds timing information) while the other is responsible for actual
execution.
- Correctly handle Git commands failing. We need an actual default
value, not just null!
- Use run/ and build/tmp/ for temporary test locations, not
/test-files.
- Switch over to the Gradle GH action. Not expecting massive changes,
but might provide some better caching.
- Bump some GH action versions.
- Fix a Java 8 compatability issue in our build scripts.
- 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.
Look, I don't enjoy having 600 LOC long build.gradle files, it's just
very easy to do! This at least moves some of the complexity elsewhere,
so the build script is a little more declarative.
It's more verbose as the default license plugin doesn't support multiple
license headers. However, it also gives us some other goodies (namely
formatting Kotlin and removing unused imports), so worth doing.
This converts ComputerThread from a singleton into a proper object,
which is setup when starting a computer, and tore down when the
ComputerContext is closed.
While this is mostly for conceptual elegance, it does offer some
concrete benefits:
- You can now adjust the thread count without restarting the whole
game (just leaving and rentering the world). Though, alas, no effect
on servers.
- We can run multiple ComputerThreads in parallel, which makes it much
easier to run tests in parallel. This allows us to remove our rather
silly IsolatedRunner test helper.
Computers now use a MainThreadScheduler to construct a
MainThreadScheduler.Executor, which is used to submit tasks. Our
previous (singleton) MainThread and MainThreadExecutor now implement
these interfaces.
The main purpose of this is to better manage the lifetime of the server
thread tasks. We've had at least one bug caused by us failing to reset
its state, so good to avoid those! This also allows us to use a fake
implementation in tests where we don't expect main thread tasks to run.
As we're now passing a bunch of arguments into our Computer, we bundle
the "global" ones into ComputerContext (which now also includes the Lua
machine factory!). This definitely isn't the nicest API, so we might
want to rethink this one day.
In some ways this isn't as nice as the Forge version (requires ATs,
doesn't check texture/model existence). However, it's more multi-loader
friendly and in some cases has much less boilerplate.
Blockstate JSON files are incredibly verbose, so we add a custom JSON
pretty printer which writes things in a slightly more compact manner.
This also changes how turtle upgrades are loaded - we now support
standard ResourceLocations (so computercraft:blocks/some_turtle_upgrade)
as well as ModelResourceLocations (computercraft:items/some_turtle_upgrade#inventory).
I don't think any resource packs need to touch our upgrades, but
apologies if this breaks anything.
- Convert remaining recipes over to datagen.
- Switch loot tables to use vanilla's loot table generator. It's
honestly not too different, just the earlier system confused me too
much :).
Alas, a positive diff because the JSON is so verbose. I've got a really
nice patch which makes the JSON more compact, but alas the Mixin doesn't
apply on 1.16 :(.
- Remove TrackingField and replace it with a Metric abstract class.
This has two concrete subclasses - Counter and Event. Events carry an
additional piece of data each time it is observed, such as HTTP
response size.
- Computers now accept a MetricsObserver, which tracks metrics for this
particular computer. This allows us to decouple Computer classes and
metrics information. The concrete MetricsObserver class we use within
Minecraft exposes the ServerComputer directly, so we no longer need to
do the awkward mapping and lookups!
- The /computercraft command can now do aggregates (count, avg, max)
over all Event metrics. This removes the need for special handling of
computer and server time.
There's also a small number of changes in removing the coupling between
Computer and some of its dependencies (ILuaMachine, MainThreadExecutor).
This makes some future refactorings easier, I promise!
This is a little odd (it's more complex for one!), but means we can
reuse the internal API interface in other classes, which is useful for
the data provider refactor I'm about to do.
This is much nicer in Java 17 :D (records, ServiceLoader.stream()),
but such is the perils of still targetting 1.16.
We now fuzz UploadFileMessage, generating random files and checking they
round-trip correctly.
The joy of having a long-lasting refactor branch with an absolutely
massive diff, is that you end up spotting bugs, and then it's a massive
pain to merge the fix back into trunk!
The last 4 or 5 commits have simplified things. I can now have some
unnecessary complexity as a treat!
This is some initial work on better tying the lifecycle of
computers (and ComputerCraft) related state to the lifecycle of the
current Minecraft server.
- Move server-wide methods in IComputerEnvironment (such as creating
resource mounts) into a separate interface.
- Add a new ServerContext class, which now holds the ID Assigner,
server computer registry, and some other tiny bits and bobs. This can
only be accessed by ServerContect.get(MinecraftServer), forcing
slightly better discipline for how we use these globals.
This does allow us to nuke some of the ugliest bits in IDAssigner. Even
if it makes things much longer!
Moves ID assigning out of the Computer class and into wherever we
construct the ServerComputer (so in computer blocks and pocket computer
items).
This is definitely not perfect - it'd be nice to make ServerComputers
more responsible for managing the lifecycle of computers (so assigning
ids, handling auto-starting, etc...), but I've not found a good way to
handle this yet!
They bring very little to the table now that computers do their own
thing! This also helps simplify the code in ServerMonitor a bit - turns
out we had two "dirty" flags in the implementation!
Previously we stored it alongside the terminal. While this makes sense -
it's not a property of the terminal itself, it ends up duplicating code
in a bunch of places.
We now track the colour flag on the terminal itself. This allows us to
simplify a couple of things:
- The palette now also knows whether it supports colours or not, and so
performs greyscale conversion. This means we no longer need to thread
a "greyscale" flag throughout terminal rendering.
- Remove isColour() getters from a whole load of
places (TerminalMethods, ServerTerminal, IComputerEnvironment).
Historically CC has maintained two computer registries; one on the
server (which runs the actual computer) and one on the client (which
stores the terminal and some small bits of additional data).
This means when a user opens the computer UI, we send the terminal
contents and store it in the client computer registry. We then send the
instance id alongside the "open container" packet, which is used to look
up the client computer (and thus terminal) in our client-side registry.
This patch makes the computer menu syncing behaviour more consistent
with vanilla. The initial terminal contents is sent alongside the "open
container" packet, and subsequent terminal changes apply /just/ to the
open container. Computer on/off state is synced via a vanilla
ContainerData/IIntArray.
Likewise, sending user input to the server now targets the open
container, rather than an arbitrary instance id.
The one remaining usage of ClientComputer is for pocket computers. For
these, we still need to sync the current on/off/blinking state and the
pocket computer light.
We don't need the full ClientComputer interface for this case (after
all, you can't send input to a pocket computer someone else is
holding!). This means we can tear out ClientComputer and
ClientComputerRegistry, replacing it with a much simpler
ClientPocketComputers store.
This in turn allows the following changes:
- Remove IComputer, as we no longer need to abstract over client and
server computers.
- Likewise, we can merge ComputerRegistry into the server
registry. This commit also cleans up the handling of instance IDs a
little bit: ServerComputers are now responsible for generating their
ID and adding/removing themselves from the registry.
- As the client-side terminal will never be null, we can remove a whole
bunch of null checks throughout the codebase.
- As the terminal is available immediately, we don't need to explicitly
pass in terminal sizes to the computer GUIs. This means we're no
longer reliant on those config values on the client side!
- Remove the "request computer state" packet. Pocket computers now
store which players need to know the computer state, automatically
sending data when a new player starts tracking the computer.
Caused by 4228011b84. While correct on
1.18, this isn't correct on 1.19 - I clearly messed up the merge here.
Fixes#1183, possibly #1184 - haven't been able to reproduce.
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.
Closes#1133. I'm not super happy about any of the versions proposed
there, but I think this is better than nothing.
Co-authored-by: JackMacWindows <jackmacwindowslinux@gmail.com>
We clamped various values to the height of the screen, rather than the
height of the content box (height-1). We didn't notice this most of the
time as the last line of a file is empty - it only really mattered when
a file was the same height as the computer's screen.
We now do the following:
- Strip the trailing new line from a file when reading.
- Replace most usages of height with height-1.
Previously illumainate required manual users to manually download it and
place it in ./bin/. This is both inconvenient for the user, and makes it
hard to ensure people are running the "right" version.
We now provide a small Gradle plugin which registers illuaminate as a
ependency, downloading the appropriate (now versioned!) file. This also
theoretically supports Macs, though I don't have access to one to test
this.
This enables the following changes:
- The Lua lint script has been converted to a Gradle task (./gradle
lintLua).
- illuaminateDocs now uses a task definition with an explicit output
directory. We can now consume this output as an input to another
task, and get a task dependency implicitly.
- Move the pre-commit config into the root of the tree. We can now use
the default GitHub action to run our hooks.
- Simplify CONTRIBUTING.md a little bit. Hopefully it's less
intimidating now.
This is mostly copied from the work Toad and I did for CC:R.
Instead of not writing to the depth buffer when rendering terminals, we
now render terminal forgrounds with a small glPolygonOffset (or an
emulation of it where not possible). This removes the need for custom
render types, while still avoiding z-fighting between the terminal
foreground and background.
The VBO monitors backend now uses Iris's TextVertexSink API when
available: Iris overwrites the vertex format for RenderType.text, and so
we need to use this API to avoid rendering garbage.
Performance is maybe a little worse than before (<3ms) and definitely
worse than CC:R. Unfortunately we can't do our upload batching as that
conflicts with Optifine's patches - instead we need to maintain two
separate VBOs. This is a bit slower, but not so bad it's unworkable.
ITurtleUpgrade.getModel has always been rather error-prone to use, due
to its client-only nature. As ModelResourceLocation is now client-only
again in Forge 1.19.1, no seems a good time to fix this.
The getter for models is now a separate interface inside a new
dan200.computercraft.api.client package. These are registered
per-TurtleUpgradeSerialiser (as those should correspond to class
anyway). It's a little ugly, and we may rename the XxxSerialiser classes
to something more general in a future update.
I'm not wild about the interface here either - happy to change it in
future versions too.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Also clean up the generic arguments to IUpgradeBase/UpgradeSerialiser a
little bit. It's not great (wish Java had HKTs), but it's better.
We're doing lots of weird OpenGL shenangins anyway, so it doesn't make
sense to use it. Instead just draw directly using the Tesselator
BufferBuilder.
This might improve compatiability with Sodium/Rubidium. Please don't let
me know if it doesn't though - I really don't want to have to deal with
it any more.
- Lots of refactoring/cleanup to Forge's events and client APIs.
- Render types/layers for blocks are now set on the model rather than
in code.
- Models now can work with multiple render types. As this would
massively complicate the implementation of the turtle item model, we
now implement a much simpler version, which makes use of Forge's
BakedModel.getRenderPasses to return a separate model for the core
turtle and each upgrade.
- Send monitor contents to players immediately when they start watching
the chunk. ChunkWatchEvent.Watch is now fired from a more sensible
location, so this is much easier to implement!
Rather than blanket disabling http with http.enabled. I think it's still
useful to keep the option around, but hopefully make it clearer what the
ramifications are.
- Changed page background to render as one quad, instead of two halves.
- Set page background to a z-offset that is between zeroth (potentially
bold border) and subsequent background pages. Bold borders were at the
same z-offset before.
We removed the config which ran all JavaExec tasks with the given
launcher, so need to override this again.
A little abusrd that this isn't done by Gradle, but there we go.
No bearing on MC, but allows us to drop the depenedency in other
projects (CCEmuX, eval.tweaked.cc, etc...)
I'd quite like to spin the core into a separate project which doesn't
depend on MC at all, but not worth doing right now.
Just saves us from having to worry about conflicts with other mods which
bundle Cobalt. This might make the transition to Jar-in-Jar easier too -
not sure yet!
Also produce an API jar - fixes#1060.
- Switch to plugins { ... } imports for Forge (FG finally supports it!)
- Use FG's new fg.component to clean up our Maven metadata instead. We
also mark JEI as optional (using Gradle's registerFeature), which
means we've no stray deps inside our POM any more.
No bearing on MC, but allows us to drop the depenedency in other
projects (CCEmuX, eval.tweaked.cc, etc...)
I'd quite like to spin the core into a separate project which doesn't
depend on MC at all, but not worth doing right now.
Oh my, a same day release! Well, if we use the AoE timezone.
Entirely untested (well, aside from automated tests), I haven't even
launched a client. In my defence, its just past midnight and I've been
up since 4am.
- Add a basic data exporter to the test mod, run via a /ccexport
command. This dumps all of CC's recipes, and the item icons needed to
display those recipes.
- Post-process our illuaminate HTML, applying several transforms:
- Apply syntax highlighting to code blocks. We previously did this
at runtime, so this shaves some bytes off the bundle.
- Convert a mc-recipe custom element into a recipe grid using
react/react-dom.
- Add a recipe to the speaker page. I'll probably clean this up in the
future (though someone else is free to too!), but it's a nice
start and proof-of-concept.
I tried so hard here to use next.js and MDX instead of rolling our own
solution again, but it's so hard to make it play well with "normal"
Markdown, which isn't explicitly written for MDX.
We now track whether a tile is enqueued or not via an atomic boolean on
the block entity itself, rather than using a hash set. This is
significantly faster (>10x).
This is mostly intended for monitors, as they're the only peripheral
likely to call TickScheduler.schedule lots of times (rather than modems,
which just invoke it when opening/closing a channel[^1])[^2]. This
change is enough to allow me to update 120 monitors each tick without
any major tearing.
[^1]: GPS does do this on each gps.locate call, so it will help there,
but modems are typically limited by other computers sending messages,
not peripheral calls themselves.
[^2]: Note that montitors implement their own change tracking, so still
only call this once per tick. But it's enough to introduce some latency!
This gives us slightly better compression, as backgrounds will often be
a single run of colours while the foreground won't be.
In practice, this is rarely an issue, as most terminals are small, but
worth doing anyway.
Just like vanilla locking, this isn't accessible in survival.
> "im retired! im retired!!", i continue to insist as i slowly shrink
> and transform into a corn cob.
- Make assertions a little more relaxed
- Increase timeouts of computer tests (again :D:).
- Log where we're up to in computer tests, to make tracking stalls a
little easier
- Rewrap everything at 80 columns. To make this tolerable I'm using
IDEA's language fragment support - hence the absurd line lengths.
- Add full stops to all comments.
- Clarify that HTTP rules are applied in-order.
- Parse Co-authored-by lines too. There's several contributors (mostly
via weblate, but a few GH ones too) who weren't credited otherwise.
- Add support for git mailmap, remapping some emails to a canonnical
username. This allows us to remove some duplicates - nobody needs
both SquidDev and "Jonathan Coates."
I'm not making this file public, as it contains email addresses. This
does mean that CI builds will still contain the full list with
duplicates.
- 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.
Previously we would compute the current timeout flags every 128
instructions of the Lua machine. While computing these flags is
_relatively_ cheap (just get the current time), it still all adds up.
Instead we now set the timeout flags from the computer monitor/watchdog
thread. This does mean that the monitor thread needs to wake up more
often[^1] _if the queue is full_, otherwise we can sleep for 100ms as
before.
This does mean that pausing is a little less accurate (can technically
take up 2*period instead). This isn't great, but in practice it seems
fine - I've not noticed any playability issues.
This offers a small (but measurable!) boost to computer performance.
[^1]: We currently sleep for scaledPeriod, but we could choose to do less.
- Reset state while the server is starting rather than once it has
started. Hopefully fixes a weird issue where wireless modems wouldn't
be "connected" on server startup.
- Correctly reset the MainThread metrics on server start/stop.
Geesh, this is nasty. Because ComputerThread is incredibly stateful, and
we want to run tests in isolation, we run each test inside its own
isolated ClassLoader (and thus ComputerThread instance).
Everything else is less nasty, though still a bit ... yuck. We also
define a custom ILuaMachine which just runs lambdas[^1], and some
utilities for starting those.
This is then tied together for four very basic tests. This is sufficient
for the changes I want to make, but might be nice to test some more
comprehensive stuff later on (e.g. timeouts after pausing).
[^1]: Which also means the ILuaMachine implementation can be changed by
other mods[^2], if someone wants to have another stab at LuaJIT :p.
[^2]: In theory. I doubt its possible in practice because so much is
package private.
This is about 5-6x faster than using a String as we don't need to
allocate and copy multiple times. In the grand scheme of things, still
vastly overshadowed by the Lua interpreter, but worth doing.
- 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.
This allows us to sync the position to the entity immediately, rather
than the sound jumping about.
Someone has set up rick-rolling pocket computers (<3 to whoever did
this), and the lag on them irritates me enough to fix this.
Fixes#1074
- Bump Forge version to latest RB.
- Generate an 8-bit audio stream again, as we no longer need to be
compatible with MC's existing streams.
No functionality changes, just mildly less hacky.
GlStateManager.glDeleteBuffers clears a buffer before deleting it on
Linux - I assume otherwise there's memory leaks on some drivers? - which
clobbers BufferUploader's cache. Roll our own version which resets the
cache when needed.
Also always reset the cache when deleting/creating a DirectVertexBuffer.
This /significantly/ improves performance of the VBO renderer (3fps to
80fps with 120 constantly changing monitors) and offers some minor FPS
improvements to the TBO renderer.
This also makes the 1.16 rendering code a little more consistent with
the 1.18 code, cleaning it up a little in the process.
Closes#1065 - this is a backport of those changes for 1.16. I will
merge these changes into 1.18, as with everything else (oh boy, that'll
be fun).
Please note this is only tested on my machine right now - any help
testing on other CPU/GPU configurations is much appreciated.
Historically I've been reluctant to do this as people might be running
Optifine for performance rather than shaders, and the VBO renderer was
significantly slower when monitors were changing.
With the recent performance optimisations, the difference isn't as bad.
Given how many people ask/complain about the TBO renderer and shaders, I
think it's worth doing this, even if it's not as granular as I'd like.
Also changes how we do the monitor backend check. We now only check for
compatibility if BEST is selected - if there's an override, we assume
the user knows what they're doing (a bold assumption, if I may say so
myself).
- For TBOs, we now pass cursor position, colour and blink state as
variables to the shader, and use them to overlay the cursor texture
in the right place.
As we no longer need to render the cursor, we can skip the depth
buffer, meaning we have to do one fewer upload+draw cycle.
- For VBOs, we bake the cursor into the main VBO, and switch between
rendering n and n+1 quads. We still need the depth blocker, but can
save one upload+draw cycle when the cursor is visible.
This saves significant time on the TBO renderer - somewhere between 4
and 7ms/frame, which bumps us up from 35 to 47fps on my test world (480
full-sized monitors, changing every tick). [Taken on 1.18, but should be
similar on 1.16]
Like #455, this sets our uniforms via a UBO rather than having separate
ones for each value. There are a couple of small differences:
- Have a UBO for each monitor, rather than sharing one and rewriting it
every monitor. This means we only need to update the buffer when the
monitor changes.
- Use std140 rather than the default layout. This means we don't have
to care about location/stride in the buffer.
Also like #455, this doesn't actually seem to result in any performance
improvements for me. However, it does make it a bit easier to handle a
large number of uniforms.
Also cleans up the generation of the main monitor texture buffer:
- Move buffer generation into a separate method - just ensures that it
shows up separately in profilers.
- Explicitly pass the position when setting bytes, rather than
incrementing the internal one. This saves some memory reads/writes (I
thought Java optimised them out, evidently not!). Saves a few fps
when updating.
- Use DSA when possible. Unclear if it helps at all, but nice to do :).
This takes a non-trivial amount of time on the render thread[^1], so
worth doing.
I don't actually think the allocation is the heavy thing here -
VisualVM says it's toWorldPos being slow. I'm not sure why - possibly
just all the block property lookups? [^2]
[^1]: To be clear, this is with 120 monitors and no other block entities
with custom renderers. so not really representative.
[^2]: I wish I could provide a narrower range, but it varies so much
between me restarting the game. Makes it impossible to benchmark
anything!
The VBO renderer needs to generate a buffer with two quads for each
cell, and then transfer it to the GPU. For large monitors, generating
this buffer can get quite slow. Most of the issues come from
IVertexBuilder (VertexConsumer under MojMap) having a lot of overhead.
By emitting a ByteBuffer directly (and doing so with Unsafe to avoid
bounds checks), we can improve performance 10 fold, going from
3fps/300ms for 120 monitors to 111fps/9ms.
See 41fa95bce4 and #1065 for some more
context and other exploratory work. The key thing to note is we _need_ a
separate version of FWFR for emitting to a ByteBuffer, as introducing
polymorphism to it comes with a significant performance hit.
- Move all RenderType instances into a common class.
Cherry-picked from 41fa95bce4:
- Render GL_QUADS instead of GL_TRIANGLES.
- Remove any "immediate mode" methods from FWFR. Most use-cases can be
replaced with the global MultiBufferSource and a proper RenderType
(which we weren't using correctly before!).
Only the GUI code (WidgetTerminal) needs to use the immediate mode.
- Pre-convert palette colours to bytes, storing both the coloured and
greyscale versions as a byte array.
Cherry-picked from 3eb601e554:
- Pass lightmap variables around the various renderers. Fixes#919 for
1.16!
"Instead, it is a standard program, which its API into the programs that it launches."
becomes
"Instead, it is a standard program, which injects its API into the programs that it launches."
A little shorter and more explicit than constructing the Vector3d
manually. Fixes an issue where sounds were centered on the bottom left
of speakers, not the middle (see cc-tweaked/cc-restitched#85).
See #1061, closes#1064.
Nobody ever seems to implement this correctly (though it's better than
1.12, at least we've not seen any crashes), and this isn't a fight I
care enough about fighting any more.
- Remove the POSITION_COLOR render type. Instead we just render a
background terminal quad as the pocket computer light - it's a little
(lot?) more cheaty, but saves having to create a render type.
- Use the existing position_color_tex shader instead of our copy. I
looked at using RenderType.text, but had a bunch of problems with GUI
terminals. Its possible we can fix it, but didn't want to spend too
much time on it.
- Remove some methods from FixedWidthFontRenderer, inlining them into
the call site.
- Switch back to using GL_QUADS rather than GL_TRIANGLES. I know Lig
will shout at me for this, but the rest of MC uses QUADS, so I don't
think best practice really matters here.
- Fix the TBO backend monitor not rendering monitors with fog.
Unfortunately we can't easily do this to the VBO one without writing
a custom shader (which defeats the whole point of the VBO backend!),
as the distance calculation of most render types expect an
already-transformed position (camera-relative I think!) while we pass
a world-relative one.
- When rendering to a VBO we push vertices to a ByteBuffer directly,
rather than going through MC's VertexConsumer system. This removes
the overhead which comes with VertexConsumer, significantly improving
performance.
- Pre-convert palette colours to bytes, storing both the coloured and
greyscale versions as a byte array. This allows us to remove the
multiple casts and conversions (double -> float -> (greyscale) ->
byte), offering noticeable performance improvements (multiple ms per
frame).
We're using a byte[] here rather than a record of three bytes as
notionally it provides better performance when writing to a
ByteBuffer directly compared to calling .put() four times. [^1]
- Memorize getRenderBoundingBox. This was taking about 5% of the total
time on the render thread[^2], so worth doing.
I don't actually think the allocation is the heavy thing here -
VisualVM says it's toWorldPos being slow. I'm not sure why - possibly
just all the block property lookups? [^2]
Note that none of these changes improve compatibility with Optifine.
Right now there's some serious issues where monitors are writing _over_
blocks in front of them. To fix this, we probably need to remove the
depth blocker and just render characters with a z offset. Will do that
in a separate commit, as I need to evaluate how well that change will
work first.
The main advantage of this commit is the improved performance. In my
stress test with 120 monitors updating every tick, I'm getting 10-20fps
[^3] (still much worse than TBOs, which manages a solid 60-100).
In practice, we'll actually be much better than this. Our network
bandwidth limits means only 40 change in a single tick - and so FPS is
much more reasonable (+60fps).
[^1]: In general, put(byte[]) is faster than put(byte) multiple times.
Just not clear if this is true when dealing with a small (and loop
unrolled) number of bytes.
[^2]: To be clear, this is with 120 monitors and no other block entities
with custom renderers. so not really representative.
[^3]: I wish I could provide a narrower range, but it varies so much
between me restarting the game. Makes it impossible to benchmark
anything!
Forge 4.0.18 deprecated a lot of methods and moved where
RegistryEvent.NewRegistry lives, so we needed to update. This does break
the CC API a little bit (sorry!) though given Forge 1.18.2 is still in
flux, that's probably inevitable.
There's a couple of alternative ways to solve this. Ideally we'd send
our network messages at the same time as MC does
(ChunkManager.playerLoadedChunk), but this'd require a mixin.
Instead we just rely on the fact that if the chunk isn't loaded,
monitors won't have done anything and so we don't need to send their
contents!
Fixes#1047, probably doesn't cause any regressions. I've not seen any
issues on 1.16, but I also hadn't before so ¯\_(ツ)_/¯.
It's now impossible to run the client tests (tests are still there, but
none of the other infrastructure is). We've not run these for months now
due to their severe flakiness :(.
This was added in the 1.13 update and I'm still not sure why. Other mods
seem to get away without it, so I think it's fine to remove.
Also remove the fake net manager, as that's part of Forge nowadays.
Fixes#1044.
- Fixes#1026
- The remaining bytes counter wasn't being decremented, so the code that
splits off smaller packets was unreachable. Thus all file slices were
being put into a single UploadFileMessage packet.
- Fix UpgradeSpeakerPeripheral not calling super.detach (so old
computers were never cleaned up)
- Correctly lock computer accesses inside SpeakerPeripheral
Fixes#1003.
Fingers crossed this is the last bug. Then I can bump the year and push
a new release tomorrow.
We're still a few days away from release, but don't think anything else
is going to change. And I /really/ don't want to have to write this
changelog (and then merge into later versions) on the 25th.
While Minecraft will automatically push a new buffer when one is
exhausted, this doesn't help if there's only a single buffer in the
queue, and you end up with stutter.
By enquing a buffer when receiving sound we ensure there's always
something queued. I'm not 100% happy with this solution, but it does
alleviate some of the concerns in #993.
Also reduce the size of the client buffer to 0.5s from 1.5s. This is
still enough to ensure seamless audio when the server is running slow (I
tested at 13 tps, but should be able to go much worse).
When the game is paused in SSP world, speakers are not ticked. However,
System.nanoTime() continues to increase, which means the next tick
speakers believe there has been a big jump and so schedule a bunch of
extra audio.
To avoid this, we keep track of how long the game has been paused offset
nanoTime by that amount.
Fixes#994
It's just more confusing having to keep track of where the ByteBuffer is
at. In this case, I think we were forgetting to rewind after computing
the digest.
Hopefully we'll be able to drop some of these in 1.17 as Java 16 has
a few more ByteBuffer methods
Fixes#992
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!
- Remove all the hungrarian notation in variables. Currently leaving
the format of rednet messages for now, while I work out whether this
counts as part of the public API or not.
- Fix the "repeat" program failing with broadcast packets. This was
introduced in #900, but I don't think anybody noticed. Will be more
relevant when #955 is implemented though.
This means that if the current player is breaking a cable/wired modem,
only the part they're looking at has breaking progress. Closes#355.
A mixin is definitely not the cleanest way to do this. There's a couple
of alternatives:
- CodeChickenLib's approach of overriding the BlockRendererDispatcher
instance with a delegating subclasss. One mod doing this is fine,
several is Not Great.o
- Adding a PR to Forge: I started this, and it's definitely the ideal
solution, but any event for this would have a ton of fields and just
ended up looking super ugly.
I assume people have broken coroutine dispatchers - I didn't think it
was possible to queue an actual event with no type.
See cc-tweaked/cc-restitched#31. Will fix it too once merged downstream!
testModExtra must /strictly/ be the set of dependencies which are not
present in implementation - there can't be any duplicates.
Yes, it's stupid, but the whole lazyToken("minecraft_classpath") thing
wasn't really built with this in mind, so not much we can do :)
Opening a screen KeyBinding.releaseAll(), which forces all inputs to be
considered released. However, our init() function then calls
grabMouse(), which calls Keybinding.setAll(), undoing this work.
The fix we're going for here is to call releaseAll() one more time[^1]
after grabbing the mouse. I think if this becomes any more of a problem,
we should roll our own grabMouse which _doesn't_ implement any specific
behaviour.
Fixes#975
[^1]: Obvious problem here is that we do minecraft.screen=xyz rather
than setScreen. We need to - otherwise we'd just hit a stack
overflow - but it's not great.
- Build fails right now due to module issues, so this won't be pushed
to GitHub.
- Monitors render transparently when loaded into the world. I don't
think this is a 1.17 bug, so not sure what's going on here!
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.
- Capability invalidation and tile/block entity changes set a dirty bit
instead of refetching the peripheral immediately.
- Then on the block's tick we recompute the peripheral if the dirty bit
is set.
Fixes#696 and probably fixes#882. Some way towards #893, but not
everything yet.
This is probably going to break things horribly. Let's find out!
- Bump copy-cat version to have support for initial files in
directories and the blit fixes.
- Add an example nft image and move example nfp into a data/ directory.
- Fix nft parser not resetting colours on the start of each line.
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
- Subscribe to the "on add reload listener" event, otherwise we don't
get reloads beyond the first one! This means we no longer need to
cast the resource manager to a reloadable one.
- Change the mount cache so it's keyed on path, rather than "path ✕
manager".
- Update the reload listener just to use the mount cache, rather than
having its own separate list. I really don't understand what I was
thinking before.
- Some improvements to validation of monitors. This rejects monitors
with invalid dimensions, specifically those with a width or height
of 0. Should fix#922.
- Simplify monitor collapsing a little. This now just attempts to
resize the four "corner" monitors (where present) and then expands
them if needed. Fixes#913.
- Rewrite monitor expansion so that it's no longer recursive. Instead
we track the "origin" monitor and replace it whenever we resize to
the left or upwards.
Also add a upper bound on the loop count, which should prevent things
like #922 happening again. Though as mentioned above, validation
should prevent this anyway.
- Some small bits of cleanup to general monitor code.
I have absolutely no confidence that this code is any better behaved
than the previous version. Let's find out I guess!
- Add a new GenericPeripheral interface. We don't strictly speaking
need this - could put this on GenericSource - but the separation
seems cleaner.
- GenericPeripheral.getType() returns a new PeripheralType class, which
can either be untyped() or specify a type name. This is a little
over-engineered (could just be a nullable string), but I'm planning
to allow multiple types in the future, so want some level of
future-proofing.
- Thread this PeripheralType through the method gathering code and
expose it to the GenericPeripheralProvider, which then chooses an
appropriate name.
This is a little ugly (we're leaking information about peripherals
everywhere), but I think is fine for now. It's all private internals
after all!
Closes#830
- Move TaskCallback into the API and make it package private. This
effectively means it's not an API class, just exists there for
convenience reasons.
- Replace any usage of TaskCallback.make with
ILuaContext.executeMainThreadTask.
- Some minor formatting/checkstyle changes to bring us inline with
IntelliJ config.
- Allow any tool to break an "instabreak" block (saplings, plants,
TNT). Oddly this doesn't include bamboo or bamboo sapings (they're
marked as instabreak, only to have their strength overridden again!),
so we also provide a tag for additional blocks to allow.
- Hoes and shovels now allow breaking any block for which this tool is
effective.
- Use block tags to drive any other block breaking capabilities. For
instance, hoes can break pumpkins and cactuses despite not being
effective.
This should get a little nicer in 1.17, as we can just use block tags
for everything.
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.
Yes, I know this is a terrible feature. But it's been a long week and
I'm so tired.
Also fix the ordering in motd_spec. Who thought putting the month first
was reasonable?
This means wired peripherals now correctly track their current mounts
and attached state, rather than inheriting from the origin wired modem.
Closes#890
Allows us to run multiple "computers" in parallel and send messages
betwene them. I don't think this counts as another test framework, but
it's sure silly.
- Fix broken /cctest marker
- Correctly wait for the screenshot to be taken before continuing.
- Filter out client tests in a different place, meaning we can remove
the /cctest runall command
- Bump kotlin version
- Add lightmap parameters to the text, computer and printout renderers.
- Printouts are always rendered using the current lightmap. When
interacting with the GUI, we use the fullbright lightmap coordinate.
- Pocket computers render their border using the lightmap. Terminal and
light do not use the lightmap at all.
There's some funkiness going on here with render types - it appears the
"correct" position_color_tex_lightmap render type is actually one used
for text.
Fixes#919. This bug does occur on 1.16 too, but given how complex the
rendering changes are between 1.16 and 1.17 I do /not/ want to have to
implement this twice. Sorry.
This ensures inventory slots are synced while the container is open,
meaning the hotbar (which is visible underneath the GUI) correctly
updates.
Fixes#915
When placed in the off hand, pocket computers now render a different
screen when opened in the off-hand, just rendering text at the top of
the screen rather than "opening" the whole computer.
This means you can view the world and computer in your hand at the
same time, effectively allowing you to emulate the
Plethora/MoarPeripherals keyboard (and much more).
This currently requires you to move the pocket computer to the other
hand to open it normally. I did look into allowing for shift+right click
to open normally, but this is awkward when you're looking at a something
like a monitor - you need to shift as otherwise you'd click the block!
Plethora hooks into onItemUseFirst instead, and this might be an option
in the future - meaning that right click would always open some computer
GUI and never the blocks. This may be something we change in the future
- let's get some feedback first!
Closes#861. Apologies for this essay, but if you got this far you were
probably interested!
As always, a massive diff which is largely just moving files between
projects. This does fix a couple of issues with advancements, but
otherwise should behave the same.
Speaking of which, should probably go and test some of these recipes...
Instead of using ids for each computer each computer is spawned with id
0 but has a label which matches up to its test name. This has several
advantages:
- No more confusing IDs: the test code now just does thenComputerOk()
and that's it - the computer to track is inferred from the test name.
- All files are stored on one computer, which means we can write code
which is shared between tests.
This spins up a Minecraft instance (much like we do for the server) and
instructs the client to take screenshots at particular times. We then
compare those screenshots and assert they match (modulo some small
delta).
Basically mimic the actual API that Minecraft would expose if the
methods hadn't been stripped. Lots of ATs and unsafe hacks to get this
working, but thankfully the API we can expose to the user is pretty
nice. Yay for Kotlin?
Anyway, will cause some immediate pain (yay merge conflicts) but should
make keeping the two in sync much easier.
These are still equivalent to the official mappings but also include
method names and javadoc. Yay!
A bit weird to be on versioned mappings after 8 months of MojMap :).!
- Fix missing shader for printout render type
- Use current buffer provider for pocket computers rather than the
tesselator. This requires us to use a non-depth-writing terminal +
depth blocker, as otherwise one gets z-fighting.
- Thus refactor some of the shaders to be terminal wide, not just for
monitors.
Fixes#894
- Use linear attenuation.
- Fix speakers being 16 times as loud as they should be. They correctly
cut off at the right distance, but didn't fade out as one might
expect.
- Clamp volume at 0, not 1. Fixes#892
I don't think anybody actually used these, and I'm not convinced they
had much value anyway.
It might be worth switching the refueling code to work as a registry
instead, though events are kinda nice.
- Remap everything to use MojMap class names too. This is what Forge
uses, so \o/.
This does NOT currently rename any classes to use suffix notation or
BlockEntity. That will come in a later change. We do however rename
references of "World" to "Level".
- Move the test mod into a separate "cctest" source set. As Forge now
works using Jigsaw we cannot have multiple mods defining the same
package, which causes problems with our JUnit test classes.
- Remove our custom test framework and replace it with vanilla's (this
is no longer stripped from the jar). RIP kotlin coroutines.
It's still worth using Kotlin here though, just for extension
methods.
- Other 1.17-related changes:
- Use separate tile/block entity tick methods for server and client
side, often avoiding ticking at all on the client.
- Switch much of the monitor rendering code to use vanilla's
built-in shader system. It's still an incredibly ugly hack, so not
really expecting this to work with any rendering mods, but we'll
cross that bridge when we come to it.
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.
Plan here is to release 1.98 for 1.16.x and 1.17.x and 1.97.1 for
1.15.x. However, will let this sit for a few days while I sort out 1.98
and the 1.17 port just in case any more bugs pop up.
This uses Netty's global traffic shaping handlers to limit the rate at
which packets can be sent and received. If the bandwidth limit is hit,
we'll start dropping packets, which will mean remote servers send
traffic to us at a much slower pace.
This isn't perfect, as there is only a global limit, and not a
per-computer one. As a result, its possible for one computer to use
all/most bandwidth, and thus slow down other computers.
This would be something to improve on in the future. However, I've spent
a lot of time reading the netty source code and docs, and the
implementation for that is significantly more complex, and one I'm not
comfortable working on right now.
For the time being, this satisfies the issues in #33 and hopefully
alleviates server owner's concerns about the http API. Remaining
problems can either be solved by moderation (with help of the
//computercraft track` command) or future updates.
Closes#33
Also add a test for rednet message sending. Hopefully gives some of the
modem and networking code a little bit of coverage (which is clearly the
same as being right :p).
By default CT applies them on the client and server. In a single player
world, this means we try to create two upgrades, which obviously fails!
Fixes#721
When exiting paint via the keyboard by typing "Ctrl" then "E"
separately, we consume the "key" event within paint, leaving the shell
to consume "read".
To avoid this, we run a sleep(0) to gobble any other left-over events.
Note, it's generally not enough to run a queueEvent/pullEvent here, as
the char event may not have ended up on the queue yet. Alas, as this
solution is pretty ugly.
- Move some shared Gui{Computer,Turtle} code into a new class. Using
entirely different naming conventions because of course (they are
consistent with MojMap, just not the rest of CC:T).
- Fix some mouse scaling issues in the terminal.
Speakers now play sounds using a custom set of packets.
- When playing a sound, we send the resource id, position, volume,
pitch and a UUID for the _speaker_ to all nearby clients.
- This UUID is then used when we need to update the sound. When the
speaker is moved or destroyed, we send a new packet to clients and
update accordingly.
This does have one side effect, that speakers can now only play one
sound at a time. I think this is accceptable - otherwise it's possible
to spam ward in a loop.
Notes still use the old networking code, and so will not be affected.
Closes#823
- Allow help files to use the ".md" suffix, and move changelog/whatsnew
to use them.
- When files end with ".md", the "help" program attempts to highlight
them. This involves:
- Colour code blocks with a lightGrey background.
- Replace lists to use bullet points instead of "-"/"*".
- Colours headings yellow.
The implementation of this is a bit janky because a) I wrote this and
b) we need to run this step before text wrapping, but preserve
colours and section positions over wrapping (thanks to Jack for
getting this working).
- Add section navigation to the help viewer, with left/right to move to
the next/previous section.
Closes#569
- Upgade to Gradle 7.0 and FG 5.0
- Allow running with any Java version - this now correctly compiles
Forge with the right version.
- Upload to Modrinth too. This is entirely untested, so may need some
tweaking.
Adds a sidebar to the computer and turtle GUI. This currently provides
- A power indicator, which turns on/shuts down a computer.
- Button to queue a "terminate" event
I've written three or four integrations with bundled cables now over the
various versions, and I'm still not convinced this one is right. It
appears to work though, so we'll see.
We need depend on the main jar here (rather than the API jar), as
otherwise our javadoc tools fails - the API references some internal
classes which aren't on our classpath.
It might be nice to write tests for this (and CT) in the future -
goodness knows these features are fragile - but that'll require some
more gradle work which I don't want to do right now.
Closes#772
- Move registry code into the various *Registry classes.
I'm not sure this is any more sensible, but things being registered
in different places kinda irked me.
- Everything else (i.e. event listeners) goes in a {Client,Common}Hooks
class right now. It's not ideal, but I don't think we can split it up
much.
- Fix double updateOutput() call in TileComputerBase - I guess a
merge/rebase gone wrong in the past.
- Don't call updateBlock() when creating a server computer. This used
to be needed when we sent the computer to the client, but this is no
longer the case.
- Don't call updateBlock() on TileMonitors when updating from the
client. We don't need to do a redraw here, as this is all stored in
the block state now.
- Don't update the block when reading turtle upgrades. See #643 for
some background here.
See #658
- Return a more sensible string for empty treasure disks (i.e. those
given by /give). This should help identify packs which are giving
items in non-supported ways.
- Fix NPE when the treasure mount doesn't exist.
Fixes#801
- Simplify how the turtle's inventory is processed. We now copy all
items into the player inventory, attempt to place, and then copy the
items back.
This also fixes the problem where turtle.place() wouldn't (always)
update the item which was placed.
I'm also hoping this is more "correct" in how we process drops from
entities and whatnot. Though I've not had any reports of issues, so
it's probably fine.
- Replace the "error message" string array with an actual object. It'd
be nicer all these functions returned a TurtleCommandResult, but
merging error messages from that is a little harder.
Fun facts: the test suite was actually helpful here, and caught the fact
that hoeing was broken!
Implementation is a little awkward, as we can't send OPEN_FILE links
from the server, so we ensure the client runs a
/computercraft open-computer ID command instead. We then intercept this
on the client side and use that to open the folder.
- Add a basic problem matcher for illuaminate errors.
- Add a script (tools/parse-reports.py) which parses the XML reports
generated by checkstyle and junit, extracts source locations, and
emits them in a manner which can be consumed by another set of
matchers.
This should make it a little easier to see problems for folks who just
rely on CI to test things (though also, please don't do this if you can
help it).
using "optipng -o7 -strip all". I ran this a few years ago and had some
issues, but aren't seeing any problems now. I don't know if this is a
graphics card change, or just optipng fixed some bugs.
These are fairly minimal changes, but hopefully save a few bytes!
- Remove the service provider code and require people to explicitly
register these. This is definitely more ugly, but easier than people
pulling in AutoService or similar!
- Add an API for registering capabilities.
- Expand the doc comments a little. Not sure how useful they'll be, but
let's see!
There's still so much work to be done on this, but it's a "good enough"
first step.
This way we still get some differences between files and folders on
normal computers. I did try with just green, but I think the contrast is
too low.
Closes#656
Unlike short handles, we don't read these immediately, and so we can't
close it right away. Otherwise the file is considered empty!
FixesSquidDev-CC/treasure-programs#1
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/
These are largely copied across from Cobalt's test suite, with some
minor tweaks. It actually exposed one bug in Cobalt, which is pretty
nice.
One interesting thing from the coroutine tests, is that Lua 5.4 (and
one assumes 5.2/5.3) doesn't allow yielding from within the error
handler of xpcall - I rather thought it might.
This doesn't add any of the PUC Lua tests yet - I got a little
distracted.
Also:
- Allow skipping "keyword" tests, in the style of busted. This is
implemented on the Java side for now.
- Fix a bug with os.date("%I", _) not being 2 characters wide.
- Don't treat turtles/pocket computers with no upgrades as an "any"
turtle. Otherwise getting the recipe of a crafty turtle shows the
recipe of a normal turtle too.
- Fix "get usage" of upgrade items not returning their recipes.
- Fix NPEs inside JEI (closes#719)
- Add remaining docs for the turtle API
- Add documentation for the fluid storage peripheral.
- Enforce undocumented warning for most modules (only io and window
remaining).
"Finish" in quotes, because these are clearly a long way from perfect.
I'm bad at writing docs, OK!
Fixes#701 (well, hopefully). Our BlockModelProvider is created when
running other mods' data generators (thought not run), which causes
issues as none of the models are considered as "existing files".
This is definitely going to break the build (it shouldn't, but these
things always do). Anyway...
- Use the new Java toolchain support, rather than requiring the user to
install multiple Java versions.
- Bump versions of several plugins.
We're sadly stuck on Gradle <7 for now, as they drop the old
maven-publish plugin, which drops SCP support.
We send monitor updates when a player starts watching a chunk. However,
the block/tile data has not been sent when this event is fired, and so
the packet is entirely ignored.
Instead, we now queue a "send this" task, which is then dispatched on
the next tick end.
I have memories of this working on 1.12, so either something changed in
an update or I'm a complete idiot. Both are possible.
Fixes#687
The replacement is objectively worse. However, it supports Git
worktrees, which sadly jgit does not.
We really need to rewrite the build script to make it lazy so we're not
executing these commands every time.
2021-01-16 15:41:19 +00:00
3272 changed files with 111814 additions and 76915 deletions
- Search for the bug on the issue tracker. Make sure to look at closed issues too!
-->
## Useful information to include:
- Minecraft version
- CC: Tweaked version
- Logs: These will be located in the `logs/` directory of your Minecraft instance. Please upload them as a gist or directly into this editor.
- Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
changelog="Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
The @{modem_message} event is fired when a message is received on an open channel on any @{modem}.
## Return Values
1. @{string}: The event name.
2. @{string}: The side of the modem that received the message.
3. @{number}: The channel that the message was sent on.
4. @{number}: The reply channel set by the sender.
5. @{any}: The message as sent by the sender.
6. <spanclass="type">@{number}|@{nil}</span>: The distance between the sender and the receiver in blocks, or @{nil} if the message was sent between dimensions.
## Example
Wraps a @{modem} peripheral, opens channel 0 for listening, and prints all received messages.
```lua
local modem = peripheral.find("modem") or error("No modem attached", 0)
modem.open(0)
while true do
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
print(("Message received on side %s on channel %d (reply to %d) from %f blocks away with message %s"):format(
see: modem_message For raw modem messages sent outside of Rednet.
see: rednet.receive To wait for a Rednet message with an optional timeout and protocol filter.
---
The @{rednet_message} event is fired when a message is sent over Rednet.
This event is usually handled by @{rednet.receive}, but it can also be pulled manually.
@{rednet_message} events are sent by @{rednet.run} in the top-level coroutine in response to @{modem_message} events. A @{rednet_message} event is always preceded by a @{modem_message} event. They are generated inside CraftOS rather than being sent by the ComputerCraft machine.
## Return Values
1. @{string}: The event name.
2. @{number}: The ID of the sending computer.
3. @{any}: The message sent.
4. <spanclass="type">@{string}|@{nil}</span>: The protocol of the message, if provided.
## Example
Prints a message when one is sent:
```lua
while true do
local event, sender, message, protocol = os.pullEvent("rednet_message")
if protocol ~= nil then
print("Received message from " .. sender .. " with protocol " .. protocol .. " and message " .. tostring(message))
else
print("Received message from " .. sender .. " with message " .. tostring(message))
see: commands.execAsync To run a command which fires a task_complete event.
---
The @{task_complete} event is fired when an asynchronous task completes. This is usually handled inside the function call that queued the task; however, functions such as @{commands.execAsync} return immediately so the user can wait for completion.
## Return Values
1. @{string}: The event name.
2. @{number}: The ID of the task that completed.
3. @{boolean}: Whether the command succeeded.
4. @{string}: If the command failed, an error message explaining the failure. (This is not present if the command succeeded.)
5. <abbrtitle="Variable number of arguments">…</abbr>: Any parameters returned from the command.
The @{terminate} event is fired when <kbd>Ctrl-T</kbd> is held down.
This event is normally handled by @{os.pullEvent}, and will not be returned. However, @{os.pullEventRaw} will return this event when fired.
@{terminate} will be sent even when a filter is provided to @{os.pullEventRaw}. When using @{os.pullEventRaw} with a filter, make sure to check that the event is not @{terminate}.
## Return values
1. @{string}: The event name.
## Example
Prints a message when Ctrl-T is held:
```lua
while true do
local event = os.pullEventRaw("terminate")
if event == "terminate" then print("Terminate requested!") end
By default, ComputerCraft blocks access to local IP addresses for security. This means you can't normally access any
HTTP server running on your computer. However, this may be useful for testing programs without having a remote
server. You can unblock these IPs in the ComputerCraft config.
- [Minecraft 1.13 and later, CC:T 1.87.0 and later](#cc-1.87.0)
- [Minecraft 1.13 and later, CC:T 1.86.2 and earlier](#cc-1.86.2)
- [Minecraft 1.12.2 and earlier](#mc-1.12)
## Minecraft 1.13 and later, CC:T 1.87.0 and later {#cc-1.87.0}
The configuration file can be located at `serverconfig/computercraft-server.toml` inside the world folder on either
single-player or multiplayer. Look for lines that look like this:
```toml
#A list of rules which control behaviour of the "http" API for specific domains or IPs.
#Each rule is an item with a 'host' to match against, and a series of properties. The host may be a domain name ("pastebin.com"),
#wildcard ("*.pastebin.com") or CIDR notation ("127.0.0.0/8"). If no rules, the domain is blocked.
[[http.rules]]
host = "$private"
action = "deny"
```
On 1.95.0 and later, this will be a single entry with `host = "$private"`. On earlier versions, this will be a number of
`[[http.rules]]` with various IP addresses. You will want to remove all of the `[[http.rules]]` entries that have
`action = "deny"`. Then save the file and relaunch Minecraft (Server).
Here's what it should look like after removing:
```toml
#A list of rules which control behaviour of the "http" API for specific domains or IPs.
#Each rule is an item with a 'host' to match against, and a series of properties. The host may be a domain name ("pastebin.com"),
#wildcard ("*.pastebin.com") or CIDR notation ("127.0.0.0/8"). If no rules, the domain is blocked.
[[http.rules]]
#The maximum size (in bytes) that a computer can send or receive in one websocket packet.
max_websocket_message = 131072
host = "*"
#The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text.
max_upload = 4194304
action = "allow"
#The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client.
max_download = 16777216
#The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited.
timeout = 30000
```
## Minecraft 1.13 and later, CC:T 1.86.2 and earlier {#cc-1.86.2}
The configuration file for singleplayer is at `.minecraft/config/computercraft-common.toml`. Look for lines that look
like this:
```toml
#A list of wildcards for domains or IP ranges that cannot be accessed through the "http" API on Computers.
#If this is empty then all whitelisted domains will be accessible. Example: "*.github.com" will block access to all subdomains of github.com.
#You can use domain names ("pastebin.com"), wildcards ("*.pastebin.com") or CIDR notation ("127.0.0.0/8").
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the much-beloved [ComputerCraft], it continues its legacy with better performance, stability, and a wealth of new features.
**Fabric support is added by the [CC: Restitched][ccrestitched] project**
## Testimonials
> I'm not sure what that is [...] I don't know where that came from.
>
> \- [direwolf20, December 2020](https://youtu.be/D8Ue9I-SKeM?t=980)
> It is basically ComputerCraft. It has the turtles, and the computers, and writing Lua programs and all that stuff.
>
> \- [direwolf20, May 2022](https://youtu.be/7Ruq33XmQIQ?t=537)
## Features
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
writing code and automating your Minecraft world.

While computers are incredibly powerful, they're rather limited by their inability to move about. *Turtles* are the
solution here. They can move about the world, placing and breaking blocks, swinging a sword to protect you from zombies,
or whatever else you program them to!

Not all problems can be solved with a pickaxe though, and so CC: Tweaked also provides a bunch of additional peripherals
for your computers. You can play a tune with speakers, display text or images on a monitor, connect all your
computers together with modems, and much more.
Computers can now also interact with inventories such as chests, allowing you to build complex inventory and item
management systems.

## Getting Started
While ComputerCraft is lovely for both experienced programmers and for people who have never coded before, it can be a
little daunting getting started. Thankfully, there's several fantastic tutorials out there:
CC: Tweaked is based off of the Cobalt Lua runtime, which uses Lua 5.1. However, Cobalt and CC:T implement additional features from Lua 5.2 and 5.3 (as well as some deprecated 5.0 features) that are not available in base 5.1. This page lists all of the compatibility for these newer versions.
# Minecraft properties (update mods.toml when changing)
mc_version=1.16.4
forge_version=35.1.16
kotlin.stdlib.default.dependency=false
kotlin.jvm.target.validation.mode=error
# Mod properties
isUnstable=false
modVersion=1.103.0
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
mcVersion=1.19.3
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.