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!