1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-15 14:07:38 +00:00

Compare commits

...

77 Commits

Author SHA1 Message Date
Jonathan Coates
1963e0160f Bump CC:T to 1.114.2
Ahhhh, I hate graphics code.
2024-11-23 09:34:03 +00:00
Jonathan Coates
9a06904634 Only skip cursor if it exists
If the cursor is not visible then we'd end up blinking the last
character on the screen. And if the screen was empty we'd spew the logs
with GL errors.
2024-11-23 09:31:04 +00:00
Jonathan Coates
5e24ad17d7 Bump CC:T to 1.114.1 2024-11-23 09:14:53 +00:00
Jonathan Coates
8b1cb09ddf Update translations 2024-11-23 09:10:50 +00:00
Jonathan Coates
d1a6b043c2 Clean up monitor cursor rendering
- Use the correct index count for the cursor quad. Monitors are now
   rendered as quads, rather than triangles.
 - *Skip* rendering the cursor vertex, rather than additionally
   rendering it.

I confess, I'm baffled how this code was ever written. From what I can
tell, this has been broken since it was first introduced in
4228011b84, and I'm sure I tested it then.

Fixes #2013. Probably.
2024-11-23 08:24:11 +00:00
Jonathan Coates
cddb8fec11 Fix crash when lectern has no item
This should never happen in practice, but might happen when using
/setblock or after world corruption, so let's be careful here.

Closes #2014
2024-11-19 21:35:00 +00:00
Jonathan Coates
1d7d8006d4 Stop publishing to CurseForge
Been dragging my feet over this for a while now, but increasingly
uncomfortable with Overwolf. I'm not going to delete the project (or any
existing versions), just not publish any new versions there.
2024-11-16 15:19:00 +00:00
Jonathan Coates
63bdc2537c Fix monitor events using the wrong computer set
Fixes #2010
2024-11-15 18:43:28 +00:00
Jonathan Coates
f776b17150 Fix argument order of math.atan in changelog 2024-11-15 15:32:40 +00:00
Jonathan Coates
31da2555cb Bump CC:T to 1.114.0 2024-11-15 08:22:05 +00:00
Jonathan Coates
9b19a93ab9 Sync translations from Crowdin
Ended up writing my own janky script to do this, rather than use the GH
integration. I'm not proud of this, but it works.
2024-11-15 08:14:06 +00:00
Jonathan Coates
ad52117f0f Syntax highlight more docstrings
This is going to conflict horribly with MC 1.21 (where we started using
@snippet), but hopefully this still helps.
2024-11-13 11:00:46 +00:00
Jonathan Coates
bdffabc08e Clarify docs around registering peripherals 2024-11-13 10:19:10 +00:00
Jonathan Coates
87ce41f251 Update Cobalt to 0.9.5
- Fix several issues with large doubles
 - Fix metatable cache not being cleared
2024-11-12 21:11:22 +00:00
Jonathan Coates
e7c7919cad Add test for turtle crafting with remainders
See #2007. This isn't an issue on 1.20.1, so it doesn't fix the issue,
but good to have the test everywhere.
2024-11-12 09:17:03 +00:00
Jonathan Coates
4f66ac79d3 Add redstone relay block (#2002)
- Move redstone methods out of the IAPIEnvironment, and into a new
   RedstoneAccess. We similarly move the implementation from Environment
   into a new RedstoneState class.

   The interface is possibly a little redundant (interfaces with a
   single implementation are always a little suspect), but it's nice to
   keep the consumer/producer interfaces separate.

 - Abstract most redstone API methods into a separate shared class, that
   can be used by both the rs API and the new redstone relay.

 - Add the new redstone relay block.

The docs are probably a little lacking here, but I really struggled to
write anything which wasn't just "look, it's the same as the redstone
API".
2024-11-12 09:05:27 +00:00
Jonathan Coates
ba6da3bc6c Update item image exporter to work on 1.20.x 2024-11-12 08:11:09 +00:00
Jonathan Coates
b742745854 Cancel no-longer-needed timers
Several functions accept a "timeout" argument, which is implemented by
starting a timer, and then racing the desired output against the timer
event.

However, if the timer never wins, we weren't cancelling the timer, and
so it was still queued. This is especially problematic if dozens or
hundreds of rednet (or websocket) messages are received in quick
succession, as we could fill the entire event queue, and stall the
computer.

See #1995
2024-11-10 21:08:05 +00:00
Jonathan Coates
3293639adf Normalise language files 2024-11-05 10:00:08 +00:00
Jonathan Coates
064ff31830 Don't reset client pocket state when changing level
As part of the multi-loader work, we unified some of our event listening
code (0908acbe9b). This incorrectly caused
client pocket computer state to be reset when the player changes
dimension, rather than when the player (dis)connects.

The server code isn't aware of this behaviour, and so does not resend
pocket computer state when the player moves level. We could change this,
but just fixing when we clear the pocket computer state is a much nicer
fix!

Fixes #2004
2024-10-31 09:33:22 +00:00
Jonathan Coates
5d473725d5 Don't word-wrap in the bug report template
Oh, I wish GHFM handled soft-breaks as soft-breaks, rather than turning
them into hard ones :/.
2024-10-31 08:32:44 +00:00
Jonathan Coates
97a2f2dbdd A desperate plea to get people to include logs 2024-10-31 08:31:35 +00:00
Jonathan Coates
37c4789fa4 Fix Czech language mapping 2024-10-31 08:31:21 +00:00
Jonathan Coates
0aaeeeee24 Don't log HTTP errors
We don't do this for websockets, so maybe we can get away without this
for HTTP ones too? Closes #1975.
2024-10-27 16:07:17 +00:00
Jonathan Coates
2155ec3d63 Give up on codecov
v4 of the action seems to be much more restrictive in what can upload
coveage. I'll miss this (the historic view of coverage was nice!), but
not worth trying to get working again.

We also stop running client tests. These break so often, we only really
ran them for code coverage reasons.
2024-10-27 11:01:42 +00:00
NotSquidDev
0da906fc93 New Crowdin updates (#1954) 2024-10-27 10:18:26 +00:00
Jonathan Coates
9e5e6a1b60 Update npm packages and illuaminate 2024-10-27 10:01:29 +00:00
Jonathan Coates
dcc74e15c7 Fix pocket upgrades not applying after crafting
The most annoying thing about pocket computers is handling computer
state (label, upgrades, etc...). Unlike other computers, which are tied
to a specific block entity, pocket computers float untethered. We can't
hold a reference to a specific item stack (as the computer might be
moved between inventories, crafted, etc...), so instead we explicitly
sync data between the computer and *current* stack, whenever the holding
player/entity is ticked.

In ed0b156e05 I rewrote this syncing code
to always treat the computer as the source of truth. Upgrades would be
copied to the computer, but never the other way round. However, this
meant that upgrades obtained by crafting would never be detected,
requiring the computer to be destroyed and recreated.

A more long-term fix here is probably to rewrite IPocketAccess to only
allow updating upgrade data on the main thread, and when we have a valid
PocketHolder. This is a breaking API change though, and so will have to
wait for 1.21.3.

For now, we just add a hook that refreshes the upgrade after crafting.

Fixes #1957
2024-10-27 09:49:01 +00:00
Jonathan Coates
c271ed7c7f Fix wrong link in os.date docs
Should be os.time, not os.date! Fixes #1999
2024-10-24 14:03:06 +01:00
Karotte128
d6a246c122 Small german translation update (#1992) 2024-10-11 20:36:28 +02:00
Jonathan Coates
0bef3ee0d8 Install/run pre-commit directly
The update to Python 3.12 has broken the pre-commit action (as it
installs via pip rather than pipx). The maintainer seems unwilling to
fix it (to put it diplomatically), so let's just stop using the action
and imlement it ourselves.
2024-10-11 20:27:15 +02:00
Jonathan Coates
bb04df7086 Remove command translation keys
- <no pos> is no longer used, as positions cannot be nullable.
 - We don't really need the position one — we can just concatenate in
   Java.
2024-10-11 12:12:02 +02:00
RuyaSavascisi
a70baf0d74 Add Turkish translation 2024-09-28 15:03:33 +01:00
Jonathan Coates
86e2f92493 Add Turkish language mapping 2024-09-28 10:15:07 +01:00
Jonathan Coates
e9aceca1de Add a helper class for working with attached computers
One of the easiest things to mess up with writing a custom peripheral is
handling attached peripherals. IPeripheral.{attach,detach} are called
from multiple threads, so naive implementations that just store
computers in a set/list will at some point throw a CME.

Historically I've suggested using a concurrent collection (i.e.
ConcurrentHashMap). While this solves the problems of CMEs, it still has
some flaws. If a computer is detached while iterating over the
collection, the iterator will still yield the now-detached peripheral,
causing usages of that computer (e.g. queueEvent) to throw an exception.

The only fix here is to use a lock when updating and iterating over the
collection. This does come with some risks, but I think they are not too
serious:

 - Lock contention: Contention is relatively rare in general (as
   peripheral attach/detach is not especially frequent). If we do see
   contention, both iteration and update actions are cheap, so I would
   not expect the other thread to be blocked for a significant time.

 - Deadlocks: One could imagine an implementation if IComputerAccess
   that holds a lock both when detaching a peripheral and inside
   queueEvent.

   If we queue an event on one thread, and try to detach on the other,
   we could see a deadlock:

     Thread 1                         | Thread 2
    ----------------------------------------------------------
     AttachedComputerSet.queueEvent   | MyModem.detach
      (take lock #1)                  |  (take lock #2)

     -> MyModem.queueEvent            | AttachedComputerSet.remove
      (wait on lock #2)               |  (wait on lock #1)

   Such code would have been broken already (some peripherals already
   use locks), so I'm fairly sure we've fixed this in CC. But definitely
   something to watch out for.

Anyway, the long and short of it:
 - Add a new AttachedComputerSet that can be used to track the computers
   attached to a peripheral. We also mention this in the attach/detach
   docs, to hopefully make it a little more obvoius.

 - Update speakers and monitors to use this new class.
2024-09-22 13:51:11 +01:00
Jonathan Coates
3042950507 Update Cobalt to add math.atan(y, x) support 2024-09-22 13:13:07 +01:00
Jonathan Coates
f7a6aac657 Bump CC:T to 1.113.1 2024-09-11 18:27:13 +01:00
Jonathan Coates
782564e6ab Write colour channel as a single int
Should be a little more efficient than writing four bytes separately.
2024-09-11 18:27:13 +01:00
Jonathan Coates
6b8ba8b80b Shadow netty rather than jar-in-jaring
Under Forge, netty-codec lives on the BOOT layer. However, this means it
does not have access to our jzlib (which lives on the GAME layer). To
fix this, we now shadow netty-codec (and its dependents, like netty-http
and netty-proxy) rather than jar-in-jaring them.

This involves some horrible build logic, but means websocket compression
works on Forge.

Fixes #1958.
2024-09-11 18:00:12 +01:00
Jonathan Coates
52b76d8886 Some stability fixes to client tests
- Place the player above the test region before running tests. This
   guarantees the client has the chunks loaded (and rendered) before we
   start running tests.

 - Reset the time after running the monitor/printout tests.

 - Fix rotation of turtle item models.

This still isn't perfect - the first test still fails with Iris and
Sodium - but is an improvement. Probably will still fail in CI though
:D:.
2024-09-11 10:13:39 +01:00
Jonathan Coates
ba36c69583 Use ARGB32 to store palette colours
Previously we used an RGBA byte array. However, this comes with some
overhead (extra memory reads, bounds checks).

Minecraft 1.21+ uses ARGB32 colours for rendering (well, in the public
code — internaly it converts to ABGR), so it makes sense to match that
here.

We also add some helper functions for dealing with ARGB32 colours. These
can be removed in 1.21, as Minecraft will have these builtin.
2024-09-11 10:13:39 +01:00
Jonathan Coates
370e5f92a0 Wait until the turtle has gone in explosion tests
Rather than a fixed delay. This should help when turtle tasks are
running a little slow.
2024-09-11 08:52:42 +01:00
Jonathan Coates
36d05e4774 Some small optimisations to textutils.urlEncode
This probably isn't useful in practice — nobody is escaping 1MB of data.
Right. Right???? But no harm in doing it.

 - Cache globals as locals.
 - Remove redundant pattern capture.
 - Merge string.format calls into one.

Also remove the "if str then" check. I assume we accepted nil values a
long time ago, but that was broken when we added arg checks. Woops!
2024-08-30 10:15:24 +01:00
Jonathan Coates
89d1be17c9 Make common's CC:T dependencies api, not impl
While mods shouldn't be depending on common, sometimes it's unavoidable
(e.g. for cc-prometheus). In those cases, you want all the CC classes
available, not just the common ones.
2024-08-30 09:35:48 +01:00
Jonathan Coates
0069591af9 Fix overflow when converting recursive objects to Lua
In cdcd82679c, we rewrote the Lua
conversion function to update the "Java -> Lua" mapping after
conversion, rather than part way through.

This made the code a little cleaner (as we only updated the mapping in
one place), but is entirely incorrect — we need to store the object
first, in order to correctly handle recursive objects — otherwise we'll
just recurse infinitely (or until we overflow).

This partially reverts the above commit, while preserving the new
behaviour for singleton collections.

Fixes #1955.
2024-08-25 09:24:10 +01:00
Jonathan Coates
c36c8605bf Mention Crowdin in our documentation 2024-08-24 22:55:14 +01:00
Jonathan Coates
3c72a00d46 Write translations to the root 2024-08-24 18:46:22 +01:00
Jonathan Coates
58aefc8df8 Add Crowdin config
We may end up reverting this, but let's give it a go at least.
2024-08-24 18:29:17 +01:00
Konuma Takaki
97ddfc2794 Japanese translation update (#1950) 2024-08-22 09:43:55 +00:00
Jonathan Coates
6e4ec86586 Fix repeated words in DFPWM docs
Even more of these! I really need to stop getting bored half way through
writing sentences and then continue writing at the wrong place. Or,
y'know, get better at proof reading.
2024-08-20 09:22:04 +01:00
Jonathan Coates
d24984c1d5 Bump CC:T to 1.113.0 2024-08-19 18:28:22 +01:00
Jonathan Coates
8080dcdd9e Fix pocket computers not being active in the off-hand
While Item.inventoryTick is passed a slot number, apparently that slot
corresponds to the offset within a particular inventory compartment
(such as the main inventory or armour)[^1], rather than the inventory as
a whole.

In the case of the off-hand, this means the pocket computer is set to be
in slot 0. When we next tick the computer (to send terminal updates), we
then assume the item has gone missing, and so skip sending updates.

Fixes #1945.

[^1]: A fun side effect of this is that the "selected" flag is true for
  the off-hand iff the player has slot 0 active. This whole thing feels
  like a vanilla bug, but who knows!
2024-08-19 17:34:39 +01:00
Jonathan Coates
d7cea55e2a Add recipes for pocket computers too
This is a little daft (recipes feel a little clumsy and tacked on), but
it's better than them being nowhere.
2024-08-19 08:10:50 +01:00
Jonathan Coates
9b2f974a81 Some tweaks to the turtle docs
- Mention only diamond tools can be used as upgrades, and be clearer
   that only the pickaxe and sword are actually useful. We probably
   could be more explicit here, but struggled to find a way to do that.

 - Expliitly list which peripherals can be equipped.

 - Add turtle recipes.
2024-08-19 08:06:00 +01:00
Jonathan Coates
43770fa9bd Remove usage of deprecated legacy Java Date API
I've been staring at this warning for years, and ignored it thinking it
would be a pain to fix. I'm a fool!
2024-08-18 12:56:36 +01:00
Jonathan Coates
80c7a54ad4 Test path manipulation methods sanitise correctly
There's some nuance here with pattern vs non-pattern characters, so
useful to test for that.
2024-08-18 12:49:33 +01:00
Jonathan Coates
e57b6fede2 Test behaviour of fs.getName/getDir with relative paths
It's not entirely clear what the correct behaviour of fs.getDir("..")
should be, and there's not much consensus between various languages.

I think the intended behaviour of this function is to move "up" one
directory level in the path, meaning it should return "../..".
2024-08-18 11:38:10 +01:00
Jonathan Coates
34a2fd039f Clarify behaviour of readAll at the end of a file
This should return an empty string, to match PUC Lua.
2024-08-18 11:03:17 +01:00
Jonathan Coates
3299d0e72a Search for items in the whole gametest structure
This fixes some flakiness where items get thrown outside a 1 block
radius.
2024-08-18 10:53:40 +01:00
Jonathan Coates
b89e2615db Don't add lore to item details when empty 2024-08-18 10:28:16 +01:00
Jonathan Coates
cdcd82679c Don't share singleton collections
CC tries to preserve sharing of objects when crossing the Lua/Java
boundary. For instance, if you queue (or send over a modem)
`{ tbl, tbl }`, then the returned table will have `x[1] == x[2]`.

However, this sharing causes issues with Java singletons. If some code
uses a singleton collection (such as List.of()) in multiple places, then
the same Lua table will be used in all those locations. It's incredibly
easy to accidentally, especially when using using Stream.toList.

For now, we special case these collections and don't de-duplicate them.
I'm not wild about this (it's a bit of a hack!), but I think it's
probably the easiest solution for now.

Fixes #1940
2024-08-18 10:20:54 +01:00
Jonathan Coates
cdfa866760 Fix several repeated words
Depressing how many of these there are. Some come from Dan though
(including one in the LICENSE!), so at least it's not just me!
2024-08-17 11:39:14 +01:00
Jonathan Coates
aa8078ddeb Allow placing printouts in lecterns
- Add a new custom lectern block, that is used to hold the printed
   pages. We have to roll quite a lot of custom logic, so this is much
   cleaner than trying to mixin to the existing lectern code.

 - Add a new (entity) model for printed pages and books placed on a
   lectern. I did originally think about just rendering the item (or the
   in-hand/map version), but I think this is a bit more consistent with
   vanilla.

   However, we do still need to sync the item to the client (mostly to
   get the current page count!). There is a risk of chunkbanning here,
   but I think it's much harder than vanilla, due to the significantly
   reduced page limit.
2024-08-15 21:19:13 +01:00
Jonathan Coates
7e53c19d74 Add a specialised menu for printouts
Rather than having a general "held-item" container, we now have a
specialised one for printouts. This now is a little more general,
supporting any container (not just the player inventory), and syncs the
current page via a data slot.

Currently this isn't especially useful, but should make it a little
easier to add lectern support in the future.
2024-08-15 20:58:09 +01:00
Jonathan Coates
b7a8432cfb Fix turtles capturing their own drops when broken
There's a whole load of gnarly issues that occur when a turtle is broken
mid-dig/attack (normally due to an explosion). We fixed most of these in
24af36743d, but not perfectly.

Part of the fix here was to not capture drops if the turtle BE has been
removed. However, on removal, turtles drop their items *before* removing
the BE. This meant that the drop consumer still triggered, and attempted
to insert items back into the turtle.

This bug only triggers if the turtle contains a stack larger than 10
(ish, I think) items, which is possibly why I'd never reproduced before.

We now drop items after removing the BE, which resolves the issue.

Fixes #1936.
2024-08-15 10:32:54 +01:00
Jonathan Coates
356c8e8aeb Fix disk drives not setting/clearing removed flag
This was originally noticed on 1.21, as it causes disk drives to not be
detected as peripherals. However, things will still be broken (albeit
more subtly) on 1.20, so worth fixing here.
2024-08-15 09:03:33 +01:00
Jonathan Coates
ed283155f7 Update to Gradle 8.10 2024-08-15 08:49:46 +01:00
Jonathan Coates
87dfad026e Add a test for exploding turtles
There's been a couple of bug reports in the past where the game would
crash if a turtle is destroyed while breaking a block (typically due to
the block exploding). This commit adds a test, to ensure that this is
handled gracefully.

I'm not entirely sure this is testing the right thing. Looking at the
issues in question, it doesn't look like I ever managed to reproduce the
bug. However, it's hopefully at least a quick sanity test to check we
never break this case.
2024-08-14 22:41:31 +01:00
Jonathan Coates
bb97c465d9 Fix computers/turtles not being dropped on explosion
Computer drops are currently[^1] implemented via a dynamic drop. To
support this, we need to inject the dynamic drop into the loot
parameters.

We currently do this by implementing our own drop logic in
playerWillDestroy[^2], manually creating the loot params and adding our
additional drop. However, if the item is dropped via some other method
(such as via explosions), we'll go through vanilla's drop logic and so
never add the dynamic drop!

The correct way to do this is to override getDrops to add the dynamic
drop instead. I don't know why we didn't always do this -- the code in
question was first written for MC 1.14[^3], when things were very
different.

[^1]: This is no longer the case on 1.21, where we can just copy
      capabilities.

[^2]: We need to override vanilla's drop behaviour to ensure items are
      dropped in creative mode.

[^3]: See 594bc4203c. Which probably means
      the bug has been around for 5 years :/.
2024-08-14 21:12:30 +01:00
Jonathan Coates
9484315d37 Fix return type of Vector.dot
Closes #1932
2024-08-11 14:11:14 +01:00
Jonathan Coates
be59f1a875 Clarify some quicks of JSON serialisation
There's a mismatch between how Lua and JSON's values are defined, which
means that serialisation is a little confusing at times. This commit
attempts to document them a little better.

Closes #1885, closes #1920
2024-08-11 12:25:28 +01:00
Jonathan Coates
bfb28b4710 Log current block entity in TickScheduler
This check should be impossible (the BE has not been removed, but is no
longer present in the world), but we've had one instance where it has
happened (#1925). I don't have a good solution here, so at least let's
print both BEs for now.
2024-08-11 12:03:48 +01:00
JackMacWindows
216f0adb3c Fix a couple of typos in fluid method docs
Also mention ffmpeg can now encode/decode DFPWM.
2024-08-11 11:55:11 +01:00
Jonathan Coates
77af4bc213 Fix a couple of typos in fluid method docs 2024-08-11 11:51:40 +01:00
Jonathan Coates
5abab982c7 Allow registering more generic detail providers
Allow registering details providers matching any super type, not just
the exact type. This is mostly useful for 1.21, where we can have
providers for any DataComponentHolder, not just item stacks.
2024-08-11 11:51:40 +01:00
Jonathan Coates
764e1aa332 Merge pull request #1924 from viluon/fix/get-next-version
Fix getNextVersion
2024-08-04 14:50:19 +01:00
Andrew Kvapil
c47718b09d Fix getNextVersion 2024-08-04 14:57:09 +02:00
201 changed files with 5778 additions and 1610 deletions

View File

@@ -6,7 +6,8 @@ body:
id: mc-version
attributes:
label: Minecraft Version
description: What version of Minecraft are you using?
description: |
What version of Minecraft are you using? If your version is not listed, please try to reproduce on one of the supported versions.
options:
- 1.20.1
- 1.21.x
@@ -26,8 +27,5 @@ body:
label: Details
description: |
Description of the bug. Please include the following:
- 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.
- Logs: These will be located in the `logs/` directory of your Minecraft instance. This is always useful, even if it doesn't include errors, so please upload this!
- 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.

View File

@@ -30,8 +30,16 @@ jobs:
- name: ⚒️ Build
run: ./gradlew assemble || ./gradlew assemble
- name: Cache pre-commit
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: 💡 Lint
uses: pre-commit/action@v3.0.0
run: |
pipx install pre-commit
pre-commit run --show-diff-on-failure --color=always
- name: 🧪 Run tests
run: ./gradlew test validateMixinNames checkChangelog
@@ -42,11 +50,6 @@ jobs:
- name: 🧪 Run integration tests
run: ./gradlew runGametest
- name: 🧪 Run client tests
run: ./gradlew runGametestClient # Not checkClient, as no point running rendering tests.
# These are a little flaky on GH actions: its useful to run them, but don't break the build.
continue-on-error: true
- name: 🧪 Parse test reports
run: ./tools/parse-reports.py
if: ${{ failure() }}
@@ -63,9 +66,6 @@ jobs:
name: CC-Tweaked
path: ./jars
- name: 📤 Upload coverage
uses: codecov/codecov-action@v4
build-core:
strategy:
fail-fast: false

View File

@@ -12,6 +12,7 @@ If you've any other questions, [just ask the community][community] or [open an i
## Table of Contents
- [Reporting issues](#reporting-issues)
- [Translations](#translations)
- [Setting up a development environment](#setting-up-a-development-environment)
- [Developing CC: Tweaked](#developing-cc-tweaked)
- [Writing documentation](#writing-documentation)
@@ -20,6 +21,10 @@ If you've any other questions, [just ask the community][community] or [open an i
If you have a bug, suggestion, or other feedback, the best thing to do is [file an issue][new-issue]. When doing so, do
use the issue templates - they provide a useful hint on what information to provide.
## Translations
Translations are managed through [CrowdIn], an online interface for managing language strings. Translations may either
be contributed there, or directly via a pull request.
## Setting up a development environment
In order to develop CC: Tweaked, you'll need to download the source code and then run it.
@@ -102,3 +107,4 @@ about how you can build on that until you've covered everything!
[busted]: https://github.com/Olivine-Labs/busted "busted: Elegant Lua unit testing."
[node]: https://nodejs.org/en/ "Node.js"
[architecture]: projects/ARCHITECTURE.md
[Crowdin]: https://crowdin.com/project/cc-tweaked/

View File

@@ -11,14 +11,13 @@ SPDX-License-Identifier: MPL-2.0
</picture>
[![Current build status](https://github.com/cc-tweaked/CC-Tweaked/workflows/Build/badge.svg)](https://github.com/cc-tweaked/CC-Tweaked/actions "Current build status")
[![Download CC: Tweaked on CurseForge](https://img.shields.io/static/v1?label=Download&message=CC:%20Tweaked&color=E04E14&logoColor=E04E14&logo=CurseForge)][CurseForge]
[![Download CC: Tweaked on Modrinth](https://img.shields.io/static/v1?label=Download&color=00AF5C&logoColor=00AF5C&logo=Modrinth&message=CC:%20Tweaked)][Modrinth]
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 improved performance and stability, along with a wealth of
new features.
CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
CC: Tweaked can be installed from [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
## Contributing
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you want to get started
@@ -83,7 +82,6 @@ We bundle the API sources with the jar, so documentation should be easily viewab
the generated documentation [can be browsed online](https://tweaked.cc/javadoc/).
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
[curseforge]: https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked from CurseForge"
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
[Fabric]: https://fabricmc.net/use/installer/ "Download Fabric."

View File

@@ -100,7 +100,7 @@ SPDX-License-Identifier = "CC0-1.0"
path = ".github/**"
[[annotations]]
path = ["gradle/wrapper/**", "gradlew", "gradlew.bat"]
path = ["gradle/wrapper/**"]
SPDX-FileCopyrightText = "Gradle Inc"
SPDX-License-Identifier = "Apache-2.0"

View File

@@ -49,7 +49,6 @@ dependencies {
implementation(libs.kotlin.plugin)
implementation(libs.spotless)
implementation(libs.curseForgeGradle)
implementation(libs.fabric.loom)
implementation(libs.forgeGradle)
implementation(libs.ideaExt)

View File

@@ -2,11 +2,9 @@
//
// SPDX-License-Identifier: MPL-2.0
import net.darkhax.curseforgegradle.TaskPublishCurseForge
import cc.tweaked.gradle.setProvider
plugins {
id("net.darkhax.curseforgegradle")
id("com.modrinth.minotaur")
id("cc-tweaked.publishing")
}
@@ -25,23 +23,6 @@ val isUnstable = project.properties["isUnstable"] == "true"
val modVersion: String by extra
val mcVersion: String by extra
val publishCurseForge by tasks.registering(TaskPublishCurseForge::class) {
group = PublishingPlugin.PUBLISH_TASK_GROUP
description = "Upload artifacts to CurseForge"
apiToken = findProperty("curseForgeApiKey") ?: ""
enabled = apiToken != ""
val mainFile = upload("282001", modPublishing.output)
mainFile.changelog =
"Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
mainFile.changelogType = "markdown"
mainFile.releaseType = if (isUnstable) "alpha" else "release"
mainFile.gameVersions.add(mcVersion)
}
tasks.publish { dependsOn(publishCurseForge) }
modrinth {
token.set(findProperty("modrinthApiKey") as String? ?: "")
projectId.set("gu7yAYhd")

View File

@@ -269,7 +269,7 @@ abstract class CCTweakedExtension(
companion object {
private val COMMIT_COUNTS = Pattern.compile("""^\s*[0-9]+\s+(.*)$""")
private val IGNORED_USERS = setOf(
"GitHub", "Daniel Ratcliffe", "Weblate",
"GitHub", "Daniel Ratcliffe", "NotSquidDev", "Weblate",
)
private fun <T> gitProvider(project: Project, default: T, supplier: () -> T): Provider<T> {

View File

@@ -143,7 +143,7 @@ fun getNextVersion(version: String): String {
val lastIndex = mainVersion.lastIndexOf('.')
if (lastIndex < 0) throw IllegalArgumentException("Cannot parse version format \"$version\"")
val lastVersion = try {
version.substring(lastIndex + 1).toInt()
mainVersion.substring(lastIndex + 1).toInt()
} catch (e: NumberFormatException) {
throw IllegalArgumentException("Cannot parse version format \"$version\"", e)
}

28
crowdin.yml Normal file
View File

@@ -0,0 +1,28 @@
# SPDX-FileCopyrightText: 2017 The CC: Tweaked Developers
#
# SPDX-License-Identifier: MPL-2.0
files:
- source: projects/common/src/generated/resources/assets/computercraft/lang/en_us.json
translation: /projects/common/src/main/resources/assets/computercraft/lang/%locale_with_underscore%.json
languages_mapping:
locale_with_underscore:
cs: cs_cz # Czech
da: da_dk # Danish
de: de_de # German
es-ES: es_es # Spanish
fr: fr_fr # French
it: it_it # Italian
ja: ja_jp # Japanese
ko: ko_kr # Korean
nb: nb_no # Norwegian Bokmal
nl: nl_nl # Dutch
pl: pl_pl # Polish
pt-BR: pt_br # Portuguese, Brazilian
ru: ru_ru # Russian
sv-SE: sv_se # Sweedish
tok: tok # Toki Pona
tr: tr_tr # Turkish
uk: uk_ua # Ukraine
vi: vi_vn # Vietnamese
zh-CN: zh_cn # Chinese Simplified

View File

@@ -8,7 +8,7 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
SPDX-License-Identifier: MPL-2.0
-->
The [`event!redstone`] event is fired whenever any redstone inputs on the computer change.
The [`event!redstone`] event is fired whenever any redstone inputs on the computer or [relay][`redstone_relay`] change.
## Return values
1. [`string`]: The event name.
@@ -21,3 +21,7 @@ while true do
print("A redstone input has changed!")
end
```
## See also
- [The `redstone` API on computers][`module!redstone`]
- [The `redstone_relay` peripheral][`redstone_relay`]

View File

@@ -16,7 +16,7 @@ CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles an
much-beloved [ComputerCraft], it continues its legacy with improved performance and stability, along with a wealth of
new features.
CC: Tweaked can be installed from [CurseForge] or [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
CC: Tweaked can be installed from [Modrinth]. It runs on both [Minecraft Forge] and [Fabric].
## Features
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
@@ -62,7 +62,6 @@ CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
[curseforge]: https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked from CurseForge"
[modrinth]: https://modrinth.com/mod/gu7yAYhd "Download CC: Tweaked from Modrinth"
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
[Minecraft Forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."

View File

@@ -81,7 +81,7 @@ compatibility for these newer versions.
| `string.dump` strip argument | ✔ | |
| `string.pack`/`string.unpack`/`string.packsize` | ✔ | |
| `table.move` | ✔ | |
| `math.atan2` -> `math.atan` | | |
| `math.atan2` -> `math.atan` | 🔶 | `math.atan` supports its two argument form. |
| Removed `math.frexp`, `math.ldexp`, `math.pow`, `math.cosh`, `math.sinh`, `math.tanh` | ❌ | |
| `math.maxinteger`/`math.mininteger` | ❌ | |
| `math.tointeger` | ❌ | |

View File

@@ -10,7 +10,7 @@ kotlin.jvm.target.validation.mode=error
# Mod properties
isUnstable=false
modVersion=1.112.0
modVersion=1.114.2
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
mcVersion=1.20.1

View File

@@ -26,7 +26,7 @@ slf4j = "2.0.1"
asm = "9.6"
autoService = "1.1.1"
checkerFramework = "3.42.0"
cobalt = "0.9.3"
cobalt = { strictly = "0.9.5" }
commonsCli = "1.6.0"
jetbrainsAnnotations = "24.1.0"
jsr305 = "3.0.2"
@@ -56,9 +56,8 @@ junit = "5.10.1"
jmh = "1.37"
# Build tools
cctJavadoc = "1.8.2"
cctJavadoc = "1.8.3"
checkstyle = "10.14.1"
curseForgeGradle = "1.0.14"
errorProne-core = "2.27.0"
errorProne-plugin = "3.1.0"
fabric-loom = "1.7.1"
@@ -66,11 +65,12 @@ forgeGradle = "6.0.21"
githubRelease = "2.5.2"
gradleVersions = "0.50.0"
ideaExt = "1.1.7"
illuaminate = "0.1.0-73-g43ee16c"
illuaminate = "0.1.0-74-gf1551d5"
librarian = "1.+"
lwjgl = "3.3.3"
minotaur = "2.+"
nullAway = "0.10.25"
shadow = "8.3.1"
spotless = "6.23.3"
taskTree = "2.1.1"
teavm = "0.11.0-SQUID.1"
@@ -94,9 +94,10 @@ jzlib = { module = "com.jcraft:jzlib", version.ref = "jzlib" }
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
kotlin-platform = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
netty-codec = { module = "io.netty:netty-codec", version.ref = "netty" }
netty-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
netty-socks = { module = "io.netty:netty-codec-socks", version.ref = "netty" }
netty-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
netty-socks = { module = "io.netty:netty-codec-socks", version.ref = "netty" }
nightConfig-core = { module = "com.electronwill.night-config:core", version.ref = "nightConfig" }
nightConfig-toml = { module = "com.electronwill.night-config:toml", version.ref = "nightConfig" }
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
@@ -143,7 +144,6 @@ lwjgl-glfw = { module = "org.lwjgl:lwjgl-glfw" }
# Build tools
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
curseForgeGradle = { module = "net.darkhax.curseforgegradle:CurseForgeGradle", version.ref = "curseForgeGradle" }
errorProne-annotations = { module = "com.google.errorprone:error_prone_annotations", version.ref = "errorProne-core" }
errorProne-api = { module = "com.google.errorprone:error_prone_check_api", version.ref = "errorProne-core" }
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
@@ -175,6 +175,7 @@ githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "g
gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersions" }
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
versionCatalogUpdate = { id = "nl.littlerobots.version-catalog-update", version.ref = "versionCatalogUpdate" }

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

5
gradlew vendored
View File

@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum

2
gradlew.bat vendored
View File

@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################

1277
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,10 +13,10 @@
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^15.2.1",
"@rollup/plugin-typescript": "^11.0.0",
"@rollup/plugin-typescript": "^12.0.0",
"@rollup/plugin-url": "^8.0.1",
"@swc/core": "^1.3.92",
"@types/node": "^20.8.3",
"@types/node": "^22.0.0",
"lightningcss": "^1.22.0",
"preact-render-to-string": "^6.2.1",
"rehype": "^13.0.0",

View File

@@ -8,6 +8,8 @@ plugins {
id("cc-tweaked.vanilla")
}
val mcVersion: String by extra
java {
withJavadocJar()
}
@@ -17,8 +19,36 @@ dependencies {
}
tasks.javadoc {
title = "CC: Tweaked $version Minecraft $mcVersion"
include("dan200/computercraft/api/**/*.java")
options {
(this as StandardJavadocDocletOptions)
groups = mapOf(
"Common" to listOf(
"dan200.computercraft.api",
"dan200.computercraft.api.lua",
"dan200.computercraft.api.peripheral",
),
"Upgrades" to listOf(
"dan200.computercraft.api.client.turtle",
"dan200.computercraft.api.pocket",
"dan200.computercraft.api.turtle",
"dan200.computercraft.api.upgrades",
),
)
addBooleanOption("-allow-script-in-comments", true)
bottom(
"""
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/components/prism-core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
<link href=" https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css " rel="stylesheet">
""".trimIndent(),
)
}
// Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump.
source(project(":core-api").sourceSets.main.map { it.allJava })
}

View File

@@ -173,7 +173,7 @@ public final class ComputerCraftAPI {
* This may be used with {@link IComputerSystem#getComponent(ComputerComponent)} to only attach APIs to specific
* computers. For example, one can add an additional API just to turtles with the following code:
*
* <pre>{@code
* <pre class="language language-java">{@code
* ComputerCraftAPI.registerAPIFactory(computer -> {
* // Read the turtle component.
* var turtle = computer.getComponent(ComputerComponents.TURTLE);

View File

@@ -13,7 +13,7 @@ import java.util.Map;
import java.util.Objects;
/**
* An item detail provider for {@link ItemStack}'s whose {@link Item} has a specific type.
* An item detail provider for {@link ItemStack}s whose {@link Item} has a specific type.
*
* @param <T> The type the stack's item must have.
*/
@@ -22,7 +22,7 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
private final @Nullable String namespace;
/**
* Create a new item detail provider. Meta will be inserted into a new sub-map named as per {@code namespace}.
* Create a new item detail provider. Details will be inserted into a new sub-map named as per {@code namespace}.
*
* @param itemType The type the stack's item must have.
* @param namespace The namespace to use for this provider.
@@ -34,7 +34,7 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
}
/**
* Create a new item detail provider. Meta will be inserted directly into the results.
* Create a new item detail provider. Details will be inserted directly into the results.
*
* @param itemType The type the stack's item must have.
*/
@@ -53,21 +53,18 @@ public abstract class BasicItemDetailProvider<T> implements DetailProvider<ItemS
* @param stack The item stack to provide details for.
* @param item The item to provide details for.
*/
public abstract void provideDetails(
Map<? super String, Object> data, ItemStack stack, T item
);
public abstract void provideDetails(Map<? super String, Object> data, ItemStack stack, T item);
@Override
public void provideDetails(Map<? super String, Object> data, ItemStack stack) {
public final void provideDetails(Map<? super String, Object> data, ItemStack stack) {
var item = stack.getItem();
if (!itemType.isInstance(item)) return;
// If `namespace` is specified, insert into a new data map instead of the existing one.
Map<? super String, Object> child = namespace == null ? data : new HashMap<>();
provideDetails(child, stack, itemType.cast(item));
if (namespace != null) {
if (namespace == null) {
provideDetails(data, stack, itemType.cast(item));
} else {
Map<? super String, Object> child = new HashMap<>();
provideDetails(child, stack, itemType.cast(item));
data.put(namespace, child);
}
}

View File

@@ -26,7 +26,7 @@ public interface DetailRegistry<T> {
* @param provider The detail provider to register.
* @see DetailProvider
*/
void addProvider(DetailProvider<T> provider);
void addProvider(DetailProvider<? super T> provider);
/**
* Compute basic details about an object. This is cheaper than computing all details operation, and so is suitable

View File

@@ -14,7 +14,7 @@ import dan200.computercraft.api.ComputerCraftAPI;
* as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant
* for its lifespan.
* <p>
* Elements are generally tied to a block or tile entity in world. In such as case, one should provide the
* Elements are generally tied to a block or block entity in world. In such as case, one should provide the
* {@link WiredElement} capability for the appropriate sides.
*/
public interface WiredElement extends WiredSender {

View File

@@ -5,7 +5,7 @@
package dan200.computercraft.api.turtle;
/**
* An enum representing the two sides of the turtle that a turtle turtle might reside.
* An enum representing the two sides of the turtle that a turtle upgrade might reside.
*/
public enum TurtleSide {
/**

View File

@@ -28,7 +28,7 @@ import java.util.function.Function;
* {@link #simple(Function)} or {@link #simpleWithCustomItem(BiFunction)} to create a basic upgrade serialiser.
*
* <h2>Example (Forge)</h2>
* <pre>{@code
* <pre class="language language-java">{@code
* static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
*
* // Register a new upgrade serialiser called "my_upgrade".
@@ -42,9 +42,9 @@ import java.util.function.Function;
* We can then define a new upgrade using JSON by placing the following in
* {@literal data/<my_mod>/computercraft/turtle_upgrades/<my_upgrade_id>.json}}.
*
* <pre>{@code
* <pre class="language language-json">{@code
* {
* "type": my_mod:my_upgrade",
* "type": "my_mod:my_upgrade",
* }
* }</pre>
* <p>

View File

@@ -86,7 +86,7 @@ public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends Upgra
* Add all turtle or pocket computer upgrades.
* <p>
* <strong>Example usage:</strong>
* <pre>{@code
* <pre class="language language-java">{@code
* protected void addUpgrades(Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) {
* simple(new ResourceLocation("mymod", "speaker"), SPEAKER_SERIALISER.get()).add(addUpgrade);
* }

View File

@@ -38,9 +38,9 @@ repositories {
dependencies {
// Pull in our other projects. See comments in MinecraftConfigurations on this nastiness.
implementation(project(":core"))
implementation(commonClasses(project(":common-api")))
clientImplementation(clientClasses(project(":common-api")))
api(project(":core"))
api(commonClasses(project(":common-api")))
clientApi(clientClasses(project(":common-api")))
compileOnly(libs.bundles.externalMods.common)
compileOnly(variantOf(libs.create.forge) { classifier("slim") }) { isTransitive = false }

View File

@@ -64,6 +64,9 @@ public final class ClientHooks {
public static void onWorldUnload() {
MonitorRenderState.destroyAll();
SpeakerManager.reset();
}
public static void onDisconnect() {
ClientPocketComputers.reset();
}

View File

@@ -13,6 +13,7 @@ import dan200.computercraft.api.client.turtle.RegisterTurtleUpgradeModeller;
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
import dan200.computercraft.client.gui.*;
import dan200.computercraft.client.pocket.ClientPocketComputers;
import dan200.computercraft.client.render.CustomLecternRenderer;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.TurtleBlockEntityRenderer;
import dan200.computercraft.client.render.monitor.MonitorBlockEntityRenderer;
@@ -73,6 +74,7 @@ public final class ClientRegistry {
BlockEntityRenderers.register(ModRegistry.BlockEntities.MONITOR_ADVANCED.get(), MonitorBlockEntityRenderer::new);
BlockEntityRenderers.register(ModRegistry.BlockEntities.TURTLE_NORMAL.get(), TurtleBlockEntityRenderer::new);
BlockEntityRenderers.register(ModRegistry.BlockEntities.TURTLE_ADVANCED.get(), TurtleBlockEntityRenderer::new);
BlockEntityRenderers.register(ModRegistry.BlockEntities.LECTERN.get(), CustomLecternRenderer::new);
}
/**

View File

@@ -6,15 +6,22 @@ package dan200.computercraft.client.gui;
import com.mojang.blaze3d.vertex.Tesselator;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.common.HeldItemMenu;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.media.PrintoutMenu;
import dan200.computercraft.shared.media.items.PrintoutItem;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerListener;
import net.minecraft.world.item.ItemStack;
import org.lwjgl.glfw.GLFW;
import java.util.Arrays;
import java.util.Objects;
import static dan200.computercraft.client.render.PrintoutRenderer.*;
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
@@ -23,40 +30,75 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA
*
* @see dan200.computercraft.client.render.PrintoutRenderer
*/
public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
private final boolean book;
private final int pages;
private final TextBuffer[] text;
private final TextBuffer[] colours;
private int page;
public final class PrintoutScreen extends AbstractContainerScreen<PrintoutMenu> implements ContainerListener {
private PrintoutInfo printout = PrintoutInfo.DEFAULT;
private int page = 0;
public PrintoutScreen(HeldItemMenu container, Inventory player, Component title) {
public PrintoutScreen(PrintoutMenu container, Inventory player, Component title) {
super(container, player, title);
imageHeight = Y_SIZE;
}
var text = PrintoutItem.getText(container.getStack());
this.text = new TextBuffer[text.length];
for (var i = 0; i < this.text.length; i++) this.text[i] = new TextBuffer(text[i]);
private void setPrintout(ItemStack stack) {
var text = PrintoutItem.getText(stack);
var textBuffers = new TextBuffer[text.length];
for (var i = 0; i < textBuffers.length; i++) textBuffers[i] = new TextBuffer(text[i]);
var colours = PrintoutItem.getColours(container.getStack());
this.colours = new TextBuffer[colours.length];
for (var i = 0; i < this.colours.length; i++) this.colours[i] = new TextBuffer(colours[i]);
var colours = PrintoutItem.getColours(stack);
var colourBuffers = new TextBuffer[colours.length];
for (var i = 0; i < colours.length; i++) colourBuffers[i] = new TextBuffer(colours[i]);
page = 0;
pages = Math.max(this.text.length / PrintoutItem.LINES_PER_PAGE, 1);
book = ((PrintoutItem) container.getStack().getItem()).getType() == PrintoutItem.Type.BOOK;
var pages = Math.max(text.length / PrintoutItem.LINES_PER_PAGE, 1);
var book = stack.is(ModRegistry.Items.PRINTED_BOOK.get());
printout = new PrintoutInfo(pages, book, textBuffers, colourBuffers);
}
@Override
protected void init() {
super.init();
menu.addSlotListener(this);
}
@Override
public void removed() {
menu.removeSlotListener(this);
}
@Override
public void slotChanged(AbstractContainerMenu menu, int slot, ItemStack stack) {
if (slot == 0) setPrintout(stack);
}
@Override
public void dataChanged(AbstractContainerMenu menu, int slot, int data) {
if (slot == PrintoutMenu.DATA_CURRENT_PAGE) page = data;
}
private void setPage(int page) {
this.page = page;
var gameMode = Objects.requireNonNull(Objects.requireNonNull(minecraft).gameMode);
gameMode.handleInventoryButtonClick(menu.containerId, PrintoutMenu.PAGE_BUTTON_OFFSET + page);
}
private void previousPage() {
if (page > 0) setPage(page - 1);
}
private void nextPage() {
if (page < printout.pages() - 1) setPage(page + 1);
}
@Override
public boolean keyPressed(int key, int scancode, int modifiers) {
if (key == GLFW.GLFW_KEY_RIGHT) {
if (page < pages - 1) page++;
nextPage();
return true;
}
if (key == GLFW.GLFW_KEY_LEFT) {
if (page > 0) page--;
previousPage();
return true;
}
@@ -68,13 +110,13 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
if (super.mouseScrolled(x, y, delta)) return true;
if (delta < 0) {
// Scroll up goes to the next page
if (page < pages - 1) page++;
nextPage();
return true;
}
if (delta > 0) {
// Scroll down goes to the previous page
if (page > 0) page--;
previousPage();
return true;
}
@@ -85,8 +127,9 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
// Draw the printout
var renderer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
drawBorder(graphics.pose(), renderer, leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP);
drawText(graphics.pose(), renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutItem.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours);
drawBorder(graphics.pose(), renderer, leftPos, topPos, 0, page, printout.pages(), printout.book(), FULL_BRIGHT_LIGHTMAP);
drawText(graphics.pose(), renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutItem.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, printout.text(), printout.colour());
renderer.endBatch();
}
@@ -105,4 +148,18 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
// Skip rendering labels.
}
record PrintoutInfo(int pages, boolean book, TextBuffer[] text, TextBuffer[] colour) {
public static final PrintoutInfo DEFAULT;
static {
var textLines = new TextBuffer[PrintoutItem.LINES_PER_PAGE];
Arrays.fill(textLines, new TextBuffer(" ".repeat(PrintoutItem.LINE_MAX_LENGTH)));
var colourLines = new TextBuffer[PrintoutItem.LINES_PER_PAGE];
Arrays.fill(colourLines, new TextBuffer("f".repeat(PrintoutItem.LINE_MAX_LENGTH)));
DEFAULT = new PrintoutInfo(1, false, textLines, colourLines);
}
}
}

View File

@@ -0,0 +1,117 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.client.model;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.client.render.CustomLecternRenderer;
import dan200.computercraft.shared.media.items.PrintoutItem;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeListBuilder;
import net.minecraft.client.model.geom.builders.MeshDefinition;
import net.minecraft.client.resources.model.Material;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
import java.util.List;
/**
* A model for {@linkplain PrintoutItem printouts} placed on a lectern.
* <p>
* This provides two models, {@linkplain #renderPages(PoseStack, VertexConsumer, int, int, int) one for a variable
* number of pages}, and {@linkplain #renderBook(PoseStack, VertexConsumer, int, int) one for books}.
*
* @see CustomLecternRenderer
*/
public class LecternPrintoutModel {
public static final ResourceLocation TEXTURE = new ResourceLocation(ComputerCraftAPI.MOD_ID, "entity/printout");
public static final Material MATERIAL = new Material(InventoryMenu.BLOCK_ATLAS, TEXTURE);
private static final int TEXTURE_WIDTH = 32;
private static final int TEXTURE_HEIGHT = 32;
private static final String PAGE_1 = "page_1";
private static final String PAGE_2 = "page_2";
private static final String PAGE_3 = "page_3";
private static final List<String> PAGES = List.of(PAGE_1, PAGE_2, PAGE_3);
private final ModelPart pagesRoot;
private final ModelPart bookRoot;
private final ModelPart[] pages;
public LecternPrintoutModel() {
pagesRoot = buildPages();
bookRoot = buildBook();
pages = PAGES.stream().map(pagesRoot::getChild).toArray(ModelPart[]::new);
}
private static ModelPart buildPages() {
var mesh = new MeshDefinition();
var parts = mesh.getRoot();
parts.addOrReplaceChild(
PAGE_1,
CubeListBuilder.create().texOffs(0, 0).addBox(-0.005f, -4.0f, -2.5f, 1f, 8.0f, 5.0f),
PartPose.ZERO
);
parts.addOrReplaceChild(
PAGE_2,
CubeListBuilder.create().texOffs(12, 0).addBox(-0.005f, -4.0f, -2.5f, 1f, 8.0f, 5.0f),
PartPose.offsetAndRotation(-0.125f, 0, 1.5f, (float) Math.PI * (1f / 16), 0, 0)
);
parts.addOrReplaceChild(
PAGE_3,
CubeListBuilder.create().texOffs(12, 0).addBox(-0.005f, -4.0f, -2.5f, 1f, 8.0f, 5.0f),
PartPose.offsetAndRotation(-0.25f, 0, -1.5f, (float) -Math.PI * (2f / 16), 0, 0)
);
return mesh.getRoot().bake(TEXTURE_WIDTH, TEXTURE_HEIGHT);
}
private static ModelPart buildBook() {
var mesh = new MeshDefinition();
var parts = mesh.getRoot();
parts.addOrReplaceChild(
"spine",
CubeListBuilder.create().texOffs(12, 15).addBox(-0.005f, -5.0f, -0.5f, 0, 10, 1.0f),
PartPose.ZERO
);
var angle = (float) Math.toRadians(5);
parts.addOrReplaceChild(
"left",
CubeListBuilder.create()
.texOffs(0, 10).addBox(0, -5.0f, -6.0f, 0, 10, 6.0f)
.texOffs(0, 0).addBox(0.005f, -4.0f, -5.0f, 1.0f, 8.0f, 5.0f),
PartPose.offsetAndRotation(-0.005f, 0, -0.5f, 0, -angle, 0)
);
parts.addOrReplaceChild(
"right",
CubeListBuilder.create()
.texOffs(14, 10).addBox(0, -5.0f, 0, 0, 10, 6.0f)
.texOffs(0, 0).addBox(0.005f, -4.0f, 0, 1.0f, 8.0f, 5.0f),
PartPose.offsetAndRotation(-0.005f, 0, 0.5f, 0, angle, 0)
);
return mesh.getRoot().bake(TEXTURE_WIDTH, TEXTURE_HEIGHT);
}
public void renderBook(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay) {
bookRoot.render(poseStack, buffer, packedLight, packedOverlay, 1, 1, 1, 1);
}
public void renderPages(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, int pageCount) {
if (pageCount > pages.length) pageCount = pages.length;
var i = 0;
for (; i < pageCount; i++) pages[i].visible = true;
for (; i < pages.length; i++) pages[i].visible = false;
pagesRoot.render(poseStack, buffer, packedLight, packedOverlay, 1, 1, 1, 1);
}
}

View File

@@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.client.render;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import dan200.computercraft.client.model.LecternPrintoutModel;
import dan200.computercraft.shared.lectern.CustomLecternBlockEntity;
import dan200.computercraft.shared.media.items.PrintoutItem;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.blockentity.LecternRenderer;
import net.minecraft.world.level.block.LecternBlock;
/**
* A block entity renderer for our {@linkplain CustomLecternBlockEntity lectern}.
* <p>
* This largely follows {@link LecternRenderer}, but with support for multiple types of item.
*/
public class CustomLecternRenderer implements BlockEntityRenderer<CustomLecternBlockEntity> {
private final LecternPrintoutModel printoutModel;
public CustomLecternRenderer(BlockEntityRendererProvider.Context context) {
printoutModel = new LecternPrintoutModel();
}
@Override
public void render(CustomLecternBlockEntity lectern, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {
poseStack.pushPose();
poseStack.translate(0.5f, 1.0625f, 0.5f);
poseStack.mulPose(Axis.YP.rotationDegrees(-lectern.getBlockState().getValue(LecternBlock.FACING).getClockWise().toYRot()));
poseStack.mulPose(Axis.ZP.rotationDegrees(67.5f));
poseStack.translate(0, -0.125f, 0);
var item = lectern.getItem();
if (item.getItem() instanceof PrintoutItem printout) {
var vertexConsumer = LecternPrintoutModel.MATERIAL.buffer(buffer, RenderType::entitySolid);
if (printout.getType() == PrintoutItem.Type.BOOK) {
printoutModel.renderBook(poseStack, vertexConsumer, packedLight, packedOverlay);
} else {
printoutModel.renderPages(poseStack, vertexConsumer, packedLight, packedOverlay, PrintoutItem.getPageCount(item));
}
}
poseStack.popPose();
}
}

View File

@@ -13,6 +13,7 @@ import dan200.computercraft.core.util.Colour;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.config.Config;
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
import dan200.computercraft.shared.util.ARGB32;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.item.ItemStack;
import org.joml.Matrix4f;
@@ -92,16 +93,11 @@ public final class PocketItemRenderer extends ItemMapLikeRenderer {
}
private static void renderLight(PoseStack transform, MultiBufferSource render, int colour, int width, int height) {
var r = (byte) ((colour >>> 16) & 0xFF);
var g = (byte) ((colour >>> 8) & 0xFF);
var b = (byte) (colour & 0xFF);
var c = new byte[]{ r, g, b, (byte) 255 };
var buffer = render.getBuffer(RenderTypes.TERMINAL);
FixedWidthFontRenderer.drawQuad(
FixedWidthFontRenderer.toVertexConsumer(transform, buffer),
width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0.001f, LIGHT_HEIGHT * 2, LIGHT_HEIGHT,
c, RenderTypes.FULL_BRIGHT_LIGHTMAP
ARGB32.opaque(colour), RenderTypes.FULL_BRIGHT_LIGHTMAP
);
}
}

View File

@@ -176,7 +176,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
var size = DirectFixedWidthFontRenderer.getVertexCount(terminal);
// In an ideal world we could upload these both into one buffer. However, we can't render VBOs with
// and starting and ending offset, and so need to use two buffers instead.
// a starting and ending offset, and so need to use two buffers instead.
renderToBuffer(backgroundBuffer, size, sink ->
DirectFixedWidthFontRenderer.drawTerminalBackground(sink, 0, 0, terminal, yMargin, yMargin, xMargin, xMargin));
@@ -208,10 +208,10 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
foregroundBuffer.bind();
foregroundBuffer.drawWithShader(
matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader(),
// As mentioned in the above comment, render the extra cursor quad if it is visible this frame. Each
// // quad has an index count of 6.
FixedWidthFontRenderer.isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink()
? foregroundBuffer.getIndexCount() + 6 : foregroundBuffer.getIndexCount()
// Skip the cursor quad if it is not visible this frame.
FixedWidthFontRenderer.isCursorVisible(terminal) && !FrameInfo.getGlobalCursorBlink()
? foregroundBuffer.getIndexCount() - RenderTypes.TERMINAL.mode().indexCount(4)
: foregroundBuffer.getIndexCount()
);
// Clear state

View File

@@ -13,9 +13,11 @@ import dan200.computercraft.core.terminal.Palette;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.core.util.Colour;
import dan200.computercraft.shared.util.ARGB32;
import org.lwjgl.system.MemoryUtil;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.*;
import static org.lwjgl.system.MemoryUtil.*;
@@ -38,10 +40,12 @@ import static org.lwjgl.system.MemoryUtil.*;
* {@link FixedWidthFontRenderer}.
*/
public final class DirectFixedWidthFontRenderer {
private static final boolean IS_LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
private DirectFixedWidthFontRenderer() {
}
private static void drawChar(QuadEmitter emitter, float x, float y, int index, byte[] colour) {
private static void drawChar(QuadEmitter emitter, float x, float y, int index, int colour) {
// Short circuit to avoid the common case - the texture should be blank here after all.
if (index == '\0' || index == ' ') return;
@@ -158,8 +162,8 @@ public final class DirectFixedWidthFontRenderer {
return (terminal.getHeight() + 2) * (terminal.getWidth() + 2) * 2;
}
private static void quad(QuadEmitter buffer, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2) {
buffer.quad(x1, y1, x2, y2, z, rgba, u1, v1, u2, v2);
private static void quad(QuadEmitter buffer, float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) {
buffer.quad(x1, y1, x2, y2, z, colour, u1, v1, u2, v2);
}
public interface QuadEmitter {
@@ -167,7 +171,7 @@ public final class DirectFixedWidthFontRenderer {
ByteBuffer buffer();
void quad(float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2);
void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2);
}
public record ByteBufferEmitter(ByteBuffer buffer) implements QuadEmitter {
@@ -177,12 +181,12 @@ public final class DirectFixedWidthFontRenderer {
}
@Override
public void quad(float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2) {
DirectFixedWidthFontRenderer.quad(buffer, x1, y1, x2, y2, z, rgba, u1, v1, u2, v2);
public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) {
DirectFixedWidthFontRenderer.quad(buffer, x1, y1, x2, y2, z, colour, u1, v1, u2, v2);
}
}
static void quad(ByteBuffer buffer, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2) {
static void quad(ByteBuffer buffer, float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) {
// Emit a single quad to our buffer. This uses Unsafe (well, LWJGL's MemoryUtil) to directly blit bytes to the
// underlying buffer. This allows us to have a single bounds check up-front, rather than one for every write.
// This provides significant performance gains, at the cost of well, using Unsafe.
@@ -196,16 +200,15 @@ public final class DirectFixedWidthFontRenderer {
if (position < 0 || 112 > buffer.limit() - position) throw new IndexOutOfBoundsException();
// Require the pointer to be aligned to a 32-bit boundary.
if ((addr & 3) != 0) throw new IllegalStateException("Memory is not aligned");
// Also assert the length of the array. This appears to help elide bounds checks on the array in some circumstances.
if (rgba.length != 4) throw new IllegalStateException();
// Pack colour so it is equivalent to rgba:BBBB.
var colourAbgr = ARGB32.toABGR32(colour);
var nativeColour = IS_LITTLE_ENDIAN ? colourAbgr : Integer.reverseBytes(colourAbgr);
memPutFloat(addr + 0, x1);
memPutFloat(addr + 4, y1);
memPutFloat(addr + 8, z);
memPutByte(addr + 12, rgba[0]);
memPutByte(addr + 13, rgba[1]);
memPutByte(addr + 14, rgba[2]);
memPutByte(addr + 15, (byte) 255);
memPutInt(addr + 12, nativeColour);
memPutFloat(addr + 16, u1);
memPutFloat(addr + 20, v1);
memPutShort(addr + 24, (short) 0xF0);
@@ -214,10 +217,7 @@ public final class DirectFixedWidthFontRenderer {
memPutFloat(addr + 28, x1);
memPutFloat(addr + 32, y2);
memPutFloat(addr + 36, z);
memPutByte(addr + 40, rgba[0]);
memPutByte(addr + 41, rgba[1]);
memPutByte(addr + 42, rgba[2]);
memPutByte(addr + 43, (byte) 255);
memPutInt(addr + 40, nativeColour);
memPutFloat(addr + 44, u1);
memPutFloat(addr + 48, v2);
memPutShort(addr + 52, (short) 0xF0);
@@ -226,10 +226,7 @@ public final class DirectFixedWidthFontRenderer {
memPutFloat(addr + 56, x2);
memPutFloat(addr + 60, y2);
memPutFloat(addr + 64, z);
memPutByte(addr + 68, rgba[0]);
memPutByte(addr + 69, rgba[1]);
memPutByte(addr + 70, rgba[2]);
memPutByte(addr + 71, (byte) 255);
memPutInt(addr + 68, nativeColour);
memPutFloat(addr + 72, u2);
memPutFloat(addr + 76, v2);
memPutShort(addr + 80, (short) 0xF0);
@@ -238,10 +235,7 @@ public final class DirectFixedWidthFontRenderer {
memPutFloat(addr + 84, x2);
memPutFloat(addr + 88, y1);
memPutFloat(addr + 92, z);
memPutByte(addr + 96, rgba[0]);
memPutByte(addr + 97, rgba[1]);
memPutByte(addr + 98, rgba[2]);
memPutByte(addr + 99, (byte) 255);
memPutInt(addr + 96, nativeColour);
memPutFloat(addr + 100, u2);
memPutFloat(addr + 104, v1);
memPutShort(addr + 108, (short) 0xF0);

View File

@@ -12,6 +12,7 @@ import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.core.util.Colour;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FastColor;
import org.joml.Matrix4f;
import org.joml.Vector3f;
@@ -41,7 +42,7 @@ public final class FixedWidthFontRenderer {
static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH;
static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH;
private static final byte[] BLACK = new byte[]{ byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR()), (byte) 255 };
private static final int BLACK = FastColor.ARGB32.color(255, byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR()));
private static final float Z_OFFSET = 1e-3f;
private FixedWidthFontRenderer() {
@@ -59,7 +60,7 @@ public final class FixedWidthFontRenderer {
return 15 - Terminal.getColour(c, def);
}
private static void drawChar(QuadEmitter emitter, float x, float y, int index, byte[] colour, int light) {
private static void drawChar(QuadEmitter emitter, float x, float y, int index, int colour, int light) {
// Short circuit to avoid the common case - the texture should be blank here after all.
if (index == '\0' || index == ' ') return;
@@ -75,7 +76,7 @@ public final class FixedWidthFontRenderer {
);
}
public static void drawQuad(QuadEmitter emitter, float x, float y, float z, float width, float height, byte[] colour, int light) {
public static void drawQuad(QuadEmitter emitter, float x, float y, float z, float width, float height, int colour, int light) {
quad(emitter, x, y, x + width, y + height, z, colour, BACKGROUND_START, BACKGROUND_START, BACKGROUND_END, BACKGROUND_END, light);
}
@@ -216,10 +217,10 @@ public final class FixedWidthFontRenderer {
return new QuadEmitter(transform.last().pose(), consumer);
}
private static void quad(QuadEmitter c, float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2, int light) {
private static void quad(QuadEmitter c, float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2, int light) {
var poseMatrix = c.poseMatrix();
var consumer = c.consumer();
byte r = rgba[0], g = rgba[1], b = rgba[2], a = rgba[3];
int r = FastColor.ARGB32.red(colour), g = FastColor.ARGB32.green(colour), b = FastColor.ARGB32.blue(colour), a = FastColor.ARGB32.alpha(colour);
consumer.vertex(poseMatrix, x1, y1, z).color(r, g, b, a).uv(u1, v1).uv2(light).endVertex();
consumer.vertex(poseMatrix, x1, y2, z).color(r, g, b, a).uv(u1, v2).uv2(light).endVertex();

View File

@@ -5,6 +5,7 @@
package dan200.computercraft.data.client;
import dan200.computercraft.client.gui.GuiSprites;
import dan200.computercraft.client.model.LecternPrintoutModel;
import dan200.computercraft.data.DataProviders;
import dan200.computercraft.shared.turtle.inventory.UpgradeSlot;
import net.minecraft.client.renderer.texture.atlas.SpriteSource;
@@ -30,7 +31,8 @@ public final class ClientDataProviders {
generator.addFromCodec("Block atlases", PackType.CLIENT_RESOURCES, "atlases", SpriteSources.FILE_CODEC, out -> {
out.accept(new ResourceLocation("blocks"), List.of(
new SingleFile(UpgradeSlot.LEFT_UPGRADE, Optional.empty()),
new SingleFile(UpgradeSlot.RIGHT_UPGRADE, Optional.empty())
new SingleFile(UpgradeSlot.RIGHT_UPGRADE, Optional.empty()),
new SingleFile(LecternPrintoutModel.TEXTURE, Optional.empty())
));
out.accept(GuiSprites.SPRITE_SHEET, Stream.of(
// Buttons

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=east": {"model": "minecraft:block/lectern", "y": 90},
"facing=north": {"model": "minecraft:block/lectern", "y": 0},
"facing=south": {"model": "minecraft:block/lectern", "y": 180},
"facing=west": {"model": "minecraft:block/lectern", "y": 270}
}
}

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=east": {"model": "computercraft:block/redstone_relay", "y": 90},
"facing=north": {"model": "computercraft:block/redstone_relay", "y": 0},
"facing=south": {"model": "computercraft:block/redstone_relay", "y": 180},
"facing=west": {"model": "computercraft:block/redstone_relay", "y": 270}
}
}

View File

@@ -17,6 +17,7 @@
"block.computercraft.monitor_advanced": "Advanced Monitor",
"block.computercraft.monitor_normal": "Monitor",
"block.computercraft.printer": "Printer",
"block.computercraft.redstone_relay": "Redstone Relay",
"block.computercraft.speaker": "Speaker",
"block.computercraft.turtle_advanced": "Advanced Turtle",
"block.computercraft.turtle_advanced.upgraded": "Advanced %s Turtle",
@@ -38,8 +39,6 @@
"commands.computercraft.generic.additional_rows": "%d additional rows…",
"commands.computercraft.generic.exception": "Unhandled exception (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<no pos>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "Y",
"commands.computercraft.help.desc": "Displays this help message",
"commands.computercraft.help.no_children": "%s has no sub-commands",

View File

@@ -0,0 +1,9 @@
{
"parent": "minecraft:block/orientable_with_bottom",
"textures": {
"bottom": "computercraft:block/redstone_relay_bottom",
"front": "computercraft:block/redstone_relay_front",
"side": "computercraft:block/redstone_relay_side",
"top": "computercraft:block/redstone_relay_top"
}
}

View File

@@ -0,0 +1 @@
{"parent": "computercraft:block/redstone_relay"}

View File

@@ -1,6 +1,7 @@
{
"sources": [
{"type": "minecraft:single", "resource": "computercraft:gui/turtle_upgrade_left"},
{"type": "minecraft:single", "resource": "computercraft:gui/turtle_upgrade_right"}
{"type": "minecraft:single", "resource": "computercraft:gui/turtle_upgrade_right"},
{"type": "minecraft:single", "resource": "computercraft:entity/printout"}
]
}

View File

@@ -0,0 +1,16 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_cable": {
"conditions": {"items": [{"items": ["computercraft:wired_modem"]}]},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {"recipe": "computercraft:redstone_relay"},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [["has_cable", "has_the_recipe"]],
"rewards": {"recipes": ["computercraft:redstone_relay"]},
"sends_telemetry_event": false
}

View File

@@ -0,0 +1,12 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [{"condition": "minecraft:survives_explosion"}],
"entries": [{"type": "minecraft:item", "name": "minecraft:lectern"}],
"rolls": 1.0
}
],
"random_sequence": "computercraft:blocks/lectern"
}

View File

@@ -0,0 +1,12 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [{"condition": "minecraft:survives_explosion"}],
"entries": [{"type": "minecraft:item", "name": "computercraft:redstone_relay"}],
"rolls": 1.0
}
],
"random_sequence": "computercraft:blocks/redstone_relay"
}

View File

@@ -23,6 +23,7 @@ import net.minecraft.data.models.BlockModelGenerators;
import net.minecraft.data.models.blockstates.*;
import net.minecraft.data.models.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.Property;
@@ -96,10 +97,17 @@ class BlockModelProvider {
registerCable(generators);
registerRedstoneControl(generators);
registerTurtleUpgrade(generators, "block/turtle_crafting_table", "block/turtle_crafty_face");
registerTurtleUpgrade(generators, "block/turtle_speaker", "block/turtle_speaker_face");
registerTurtleModem(generators, "block/turtle_modem_normal", "block/wireless_modem_normal_face");
registerTurtleModem(generators, "block/turtle_modem_advanced", "block/wireless_modem_advanced_face");
generators.blockStateOutput.accept(MultiVariantGenerator.multiVariant(
ModRegistry.Blocks.LECTERN.get(),
Variant.variant().with(VariantProperties.MODEL, ModelLocationUtils.getModelLocation(Blocks.LECTERN))
).with(createHorizontalFacingDispatch()));
}
private static void registerDiskDrive(BlockModelGenerators generators) {
@@ -349,6 +357,18 @@ class BlockModelProvider {
generators.blockStateOutput.accept(generator);
}
private static void registerRedstoneControl(BlockModelGenerators generators) {
var redstoneControl = ModRegistry.Blocks.REDSTONE_RELAY.get();
var model = ModelTemplates.CUBE_ORIENTABLE_TOP_BOTTOM.create(
redstoneControl, TextureMapping.orientableCube(redstoneControl), generators.modelOutput
);
generators.blockStateOutput.accept(
MultiVariantGenerator.multiVariant(redstoneControl, Variant.variant().with(VariantProperties.MODEL, model))
.with(createHorizontalFacingDispatch())
);
}
private static final BooleanProperty[] CABLE_DIRECTIONS = { CableBlock.DOWN, CableBlock.UP, CableBlock.NORTH, CableBlock.SOUTH, CableBlock.WEST, CableBlock.EAST };
private static final boolean[] BOOLEANS = new boolean[]{ false, true };

View File

@@ -80,6 +80,7 @@ public final class LanguageProvider implements DataProvider {
add(ModRegistry.Items.WIRED_MODEM.get(), "Wired Modem");
add(ModRegistry.Items.CABLE.get(), "Networking Cable");
add(ModRegistry.Items.WIRED_MODEM_FULL.get(), "Wired Modem");
add(ModRegistry.Items.REDSTONE_RELAY.get(), "Redstone Relay");
add(ModRegistry.Items.TURTLE_NORMAL.get(), "Turtle");
add(ModRegistry.Blocks.TURTLE_NORMAL.get().getDescriptionId() + ".upgraded", "%s Turtle");
@@ -160,8 +161,6 @@ public final class LanguageProvider implements DataProvider {
add("commands.computercraft.queue.synopsis", "Send a computer_command event to a command computer");
add("commands.computercraft.queue.desc", "Send a computer_command event to a command computer, passing through the additional arguments. This is mostly designed for map makers, acting as a more computer-friendly version of /trigger. Any player can run the command, which would most likely be done through a text component's click event.");
add("commands.computercraft.generic.no_position", "<no pos>");
add("commands.computercraft.generic.position", "%s, %s, %s");
add("commands.computercraft.generic.yes", "Y");
add("commands.computercraft.generic.no", "N");
add("commands.computercraft.generic.exception", "Unhandled exception (%s)");
@@ -284,7 +283,9 @@ public final class LanguageProvider implements DataProvider {
return Stream.of(
RegistryWrappers.BLOCKS.stream()
.filter(x -> RegistryWrappers.BLOCKS.getKey(x).getNamespace().equals(ComputerCraftAPI.MOD_ID))
.map(Block::getDescriptionId),
.map(Block::getDescriptionId)
// Exclude blocks that just reuse vanilla translations, such as the lectern.
.filter(x -> !x.startsWith("block.minecraft.")),
RegistryWrappers.ITEMS.stream()
.filter(x -> RegistryWrappers.ITEMS.getKey(x).getNamespace().equals(ComputerCraftAPI.MOD_ID))
.map(Item::getDescriptionId),

View File

@@ -15,6 +15,7 @@ import dan200.computercraft.shared.peripheral.modem.wired.CableModemVariant;
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
import net.minecraft.data.loot.LootTableProvider.SubProviderEntry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
@@ -50,6 +51,7 @@ class LootTableProvider {
selfDrop(add, ModRegistry.Blocks.WIRED_MODEM_FULL);
selfDrop(add, ModRegistry.Blocks.WIRELESS_MODEM_NORMAL);
selfDrop(add, ModRegistry.Blocks.WIRELESS_MODEM_ADVANCED);
selfDrop(add, ModRegistry.Blocks.REDSTONE_RELAY);
computerDrop(add, ModRegistry.Blocks.COMPUTER_NORMAL);
computerDrop(add, ModRegistry.Blocks.COMPUTER_ADVANCED);
@@ -57,6 +59,8 @@ class LootTableProvider {
computerDrop(add, ModRegistry.Blocks.TURTLE_NORMAL);
computerDrop(add, ModRegistry.Blocks.TURTLE_ADVANCED);
blockDrop(add, ModRegistry.Blocks.LECTERN, LootItem.lootTableItem(Items.LECTERN), ExplosionCondition.survivesExplosion());
add.accept(ModRegistry.Blocks.CABLE.get().getLootTable(), LootTable
.lootTable()
.withPool(LootPool.lootPool()

View File

@@ -461,6 +461,17 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.requires(ingredients.string())
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
.save(RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPELESS.get(), add));
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.REDSTONE_RELAY.get())
.pattern("SRS")
.pattern("RCR")
.pattern("SRS")
.define('S', Items.STONE)
.define('R', ingredients.redstone())
.define('C', ModRegistry.Blocks.CABLE.get())
.unlockedBy("has_cable", inventoryChange(ModRegistry.Blocks.CABLE.get()))
.save(add);
}
private static DyeColor ofColour(Colour colour) {

View File

@@ -78,9 +78,12 @@ class TagProvider {
ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get(),
ModRegistry.Blocks.WIRELESS_MODEM_ADVANCED.get(),
ModRegistry.Blocks.WIRED_MODEM_FULL.get(),
ModRegistry.Blocks.CABLE.get()
ModRegistry.Blocks.CABLE.get(),
ModRegistry.Blocks.REDSTONE_RELAY.get()
);
tags.tag(BlockTags.MINEABLE_WITH_AXE).add(ModRegistry.Blocks.LECTERN.get());
tags.tag(BlockTags.WITHER_IMMUNE).add(ModRegistry.Blocks.COMPUTER_COMMAND.get());
tags.tag(ExternalModTags.Blocks.CREATE_BRITTLE).add(
@@ -102,8 +105,14 @@ class TagProvider {
ModRegistry.Items.MONITOR_ADVANCED.get()
);
// Allow printed books to be placed in bookshelves.
tags.tag(ItemTags.BOOKSHELF_BOOKS).add(ModRegistry.Items.PRINTED_BOOK.get());
// Allow any printout to be placed on lecterns. See also PrintoutItem and CustomLecternBlock.
tags.tag(ItemTags.LECTERN_BOOKS).add(
ModRegistry.Items.PRINTED_PAGE.get(), ModRegistry.Items.PRINTED_PAGES.get(), ModRegistry.Items.PRINTED_BOOK.get()
);
tags.tag(ComputerCraftTags.Items.TURTLE_CAN_PLACE)
.add(Items.GLASS_BOTTLE)
.addTag(ItemTags.BOATS);

View File

@@ -15,7 +15,7 @@ import java.util.*;
* @param <T> The type of object that this registry provides details for.
*/
public class DetailRegistryImpl<T> implements DetailRegistry<T> {
private final Collection<DetailProvider<T>> providers = new ArrayList<>();
private final Collection<DetailProvider<? super T>> providers = new ArrayList<>();
private final DetailProvider<T> basic;
public DetailRegistryImpl(DetailProvider<T> basic) {
@@ -24,7 +24,7 @@ public class DetailRegistryImpl<T> implements DetailRegistry<T> {
}
@Override
public synchronized void addProvider(DetailProvider<T> provider) {
public synchronized void addProvider(DetailProvider<? super T> provider) {
Objects.requireNonNull(provider, "provider cannot be null");
if (!providers.contains(provider)) providers.add(provider);
}

View File

@@ -23,7 +23,6 @@ import dan200.computercraft.shared.command.arguments.TrackingFieldArgumentType;
import dan200.computercraft.shared.common.ClearColourRecipe;
import dan200.computercraft.shared.common.ColourableRecipe;
import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider;
import dan200.computercraft.shared.common.HeldItemMenu;
import dan200.computercraft.shared.computer.apis.CommandAPI;
import dan200.computercraft.shared.computer.blocks.CommandComputerBlock;
import dan200.computercraft.shared.computer.blocks.ComputerBlock;
@@ -41,6 +40,9 @@ import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
import dan200.computercraft.shared.details.BlockDetails;
import dan200.computercraft.shared.details.ItemDetails;
import dan200.computercraft.shared.integration.PermissionRegistry;
import dan200.computercraft.shared.lectern.CustomLecternBlock;
import dan200.computercraft.shared.lectern.CustomLecternBlockEntity;
import dan200.computercraft.shared.media.PrintoutMenu;
import dan200.computercraft.shared.media.items.DiskItem;
import dan200.computercraft.shared.media.items.PrintoutItem;
import dan200.computercraft.shared.media.items.RecordMedia;
@@ -49,7 +51,6 @@ import dan200.computercraft.shared.media.recipes.DiskRecipe;
import dan200.computercraft.shared.media.recipes.PrintoutRecipe;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.network.container.ContainerData;
import dan200.computercraft.shared.network.container.HeldItemContainerData;
import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveBlock;
import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveBlockEntity;
import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu;
@@ -61,6 +62,8 @@ import dan200.computercraft.shared.peripheral.monitor.MonitorBlockEntity;
import dan200.computercraft.shared.peripheral.printer.PrinterBlock;
import dan200.computercraft.shared.peripheral.printer.PrinterBlockEntity;
import dan200.computercraft.shared.peripheral.printer.PrinterMenu;
import dan200.computercraft.shared.peripheral.redstone.RedstoneRelayBlock;
import dan200.computercraft.shared.peripheral.redstone.RedstoneRelayBlockEntity;
import dan200.computercraft.shared.peripheral.speaker.SpeakerBlock;
import dan200.computercraft.shared.peripheral.speaker.SpeakerBlockEntity;
import dan200.computercraft.shared.platform.PlatformHelper;
@@ -101,10 +104,12 @@ import net.minecraft.world.item.crafting.CustomRecipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType;
@@ -129,7 +134,7 @@ public final class ModRegistry {
return BlockBehaviour.Properties.of().strength(2);
}
private static BlockBehaviour.Properties computerProperties() {
private static BlockBehaviour.Properties redstoneConductor() {
// Computers shouldn't conduct redstone through them, so set isRedstoneConductor to false. This still allows
// redstone to connect to computers though as it's a signal source.
return properties().isRedstoneConductor((block, level, blockPos) -> false);
@@ -144,11 +149,11 @@ public final class ModRegistry {
}
public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_NORMAL = REGISTRY.register("computer_normal",
() -> new ComputerBlock<>(computerProperties().mapColor(MapColor.STONE), BlockEntities.COMPUTER_NORMAL));
() -> new ComputerBlock<>(redstoneConductor().mapColor(MapColor.STONE), BlockEntities.COMPUTER_NORMAL));
public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_ADVANCED = REGISTRY.register("computer_advanced",
() -> new ComputerBlock<>(computerProperties().mapColor(MapColor.GOLD), BlockEntities.COMPUTER_ADVANCED));
() -> new ComputerBlock<>(redstoneConductor().mapColor(MapColor.GOLD), BlockEntities.COMPUTER_ADVANCED));
public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_COMMAND = REGISTRY.register("computer_command",
() -> new CommandComputerBlock<>(computerProperties().strength(-1, 6000000.0F), BlockEntities.COMPUTER_COMMAND));
() -> new CommandComputerBlock<>(redstoneConductor().strength(-1, 6000000.0F), BlockEntities.COMPUTER_COMMAND));
public static final RegistryEntry<TurtleBlock> TURTLE_NORMAL = REGISTRY.register("turtle_normal",
() -> new TurtleBlock(turtleProperties().mapColor(MapColor.STONE), BlockEntities.TURTLE_NORMAL));
@@ -172,6 +177,13 @@ public final class ModRegistry {
public static final RegistryEntry<WiredModemFullBlock> WIRED_MODEM_FULL = REGISTRY.register("wired_modem_full",
() -> new WiredModemFullBlock(modemProperties().mapColor(MapColor.STONE)));
public static final RegistryEntry<CableBlock> CABLE = REGISTRY.register("cable", () -> new CableBlock(modemProperties().mapColor(MapColor.STONE)));
public static final RegistryEntry<CustomLecternBlock> LECTERN = REGISTRY.register("lectern", () -> new CustomLecternBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.5F).sound(SoundType.WOOD).ignitedByLava()
));
public static final RegistryEntry<RedstoneRelayBlock> REDSTONE_RELAY = REGISTRY.register("redstone_relay",
() -> new RedstoneRelayBlock(redstoneConductor().mapColor(MapColor.STONE)));
}
public static class BlockEntities {
@@ -213,6 +225,10 @@ public final class ModRegistry {
ofBlock(Blocks.WIRELESS_MODEM_NORMAL, (p, s) -> new WirelessModemBlockEntity(BlockEntities.WIRELESS_MODEM_NORMAL.get(), p, s, false));
public static final RegistryEntry<BlockEntityType<WirelessModemBlockEntity>> WIRELESS_MODEM_ADVANCED =
ofBlock(Blocks.WIRELESS_MODEM_ADVANCED, (p, s) -> new WirelessModemBlockEntity(BlockEntities.WIRELESS_MODEM_ADVANCED.get(), p, s, true));
public static final RegistryEntry<BlockEntityType<CustomLecternBlockEntity>> LECTERN = ofBlock(Blocks.LECTERN, CustomLecternBlockEntity::new);
public static final RegistryEntry<BlockEntityType<RedstoneRelayBlockEntity>> REDSTONE_RELAY = ofBlock(Blocks.REDSTONE_RELAY, RedstoneRelayBlockEntity::new);
}
public static final class Items {
@@ -258,6 +274,7 @@ public final class ModRegistry {
public static final RegistryEntry<BlockItem> WIRELESS_MODEM_NORMAL = ofBlock(Blocks.WIRELESS_MODEM_NORMAL, BlockItem::new);
public static final RegistryEntry<BlockItem> WIRELESS_MODEM_ADVANCED = ofBlock(Blocks.WIRELESS_MODEM_ADVANCED, BlockItem::new);
public static final RegistryEntry<BlockItem> WIRED_MODEM_FULL = ofBlock(Blocks.WIRED_MODEM_FULL, BlockItem::new);
public static final RegistryEntry<BlockItem> REDSTONE_RELAY = ofBlock(Blocks.REDSTONE_RELAY, BlockItem::new);
public static final RegistryEntry<CableBlockItem.Cable> CABLE = REGISTRY.register("cable",
() -> new CableBlockItem.Cable(Blocks.CABLE.get(), properties()));
@@ -309,11 +326,8 @@ public final class ModRegistry {
public static final RegistryEntry<MenuType<PrinterMenu>> PRINTER = REGISTRY.register("printer",
() -> new MenuType<>(PrinterMenu::new, FeatureFlags.VANILLA_SET));
public static final RegistryEntry<MenuType<HeldItemMenu>> PRINTOUT = REGISTRY.register("printout",
() -> ContainerData.toType(
HeldItemContainerData::new,
(id, inventory, data) -> new HeldItemMenu(Menus.PRINTOUT.get(), id, inventory.player, data.getHand())
));
public static final RegistryEntry<MenuType<PrintoutMenu>> PRINTOUT = REGISTRY.register("printout",
() -> new MenuType<>((i, c) -> PrintoutMenu.createRemote(i), FeatureFlags.VANILLA_SET));
}
static class ArgumentTypes {
@@ -409,6 +423,7 @@ public final class ModRegistry {
out.accept(Items.CABLE.get());
out.accept(Items.WIRED_MODEM.get());
out.accept(Items.WIRED_MODEM_FULL.get());
out.accept(Items.REDSTONE_RELAY.get());
out.accept(Items.MONITOR_NORMAL.get());
out.accept(Items.MONITOR_ADVANCED.get());

View File

@@ -40,9 +40,8 @@ public final class ChatHelpers {
return component;
}
public static MutableComponent position(@Nullable BlockPos pos) {
if (pos == null) return Component.translatable("commands.computercraft.generic.no_position");
return Component.translatable("commands.computercraft.generic.position", pos.getX(), pos.getY(), pos.getZ());
public static MutableComponent position(BlockPos pos) {
return Component.literal(pos.toShortString());
}
public static MutableComponent bool(boolean value) {

View File

@@ -63,7 +63,7 @@ public class TableBuilder {
/**
* Get the number of columns for this table.
* <p>
* This will be the same as {@link #getHeaders()}'s length if it is is non-{@code null},
* This will be the same as {@link #getHeaders()}'s length if it is non-{@code null},
* otherwise the length of the first column.
*
* @return The number of columns.

View File

@@ -1,68 +0,0 @@
// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
//
// SPDX-License-Identifier: LicenseRef-CCPL
package dan200.computercraft.shared.common;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import javax.annotation.Nullable;
public class HeldItemMenu extends AbstractContainerMenu {
private final ItemStack stack;
private final InteractionHand hand;
public HeldItemMenu(MenuType<? extends HeldItemMenu> type, int id, Player player, InteractionHand hand) {
super(type, id);
this.hand = hand;
stack = player.getItemInHand(hand).copy();
}
public ItemStack getStack() {
return stack;
}
@Override
public ItemStack quickMoveStack(Player player, int slot) {
return ItemStack.EMPTY;
}
@Override
public boolean stillValid(Player player) {
if (!player.isAlive()) return false;
var stack = player.getItemInHand(hand);
return stack == this.stack || !stack.isEmpty() && !this.stack.isEmpty() && stack.getItem() == this.stack.getItem();
}
public static class Factory implements MenuProvider {
private final MenuType<HeldItemMenu> type;
private final Component name;
private final InteractionHand hand;
public Factory(MenuType<HeldItemMenu> type, ItemStack stack, InteractionHand hand) {
this.type = type;
name = stack.getHoverName();
this.hand = hand;
}
@Override
public Component getDisplayName() {
return name;
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int id, Inventory inventory, Player player) {
return new HeldItemMenu(type, id, player, hand);
}
}
}

View File

@@ -248,7 +248,7 @@ public class CommandAPI implements ILuaAPI {
* Get some basic information about a block.
* <p>
* The returned table contains the current name, metadata and block state (as
* with [`turtle.inspect`]). If there is a tile entity for that block, its NBT
* with [`turtle.inspect`]). If there is a block entity for that block, its NBT
* will also be returned.
*
* @param x The x position of the block to query.

View File

@@ -35,9 +35,9 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
import java.util.List;
public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntity> extends HorizontalDirectionalBlock implements IBundledRedstoneBlock, EntityBlock {
private static final ResourceLocation DROP = new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer");
@@ -110,9 +110,19 @@ public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntit
return super.getCloneItemStack(world, pos, state);
}
@Override
@Deprecated
public List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
if (params.getOptionalParameter(LootContextParams.BLOCK_ENTITY) instanceof AbstractComputerBlockEntity computer) {
params = params.withDynamicDrop(DROP, out -> out.accept(getItem(computer)));
}
return super.getDrops(state, params);
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity tile, ItemStack tool) {
// Don't drop blocks here - see onBlockHarvested.
// Don't drop blocks here - see playerWillDestroy.
player.awardStat(Stats.BLOCK_MINED.get(this));
player.causeFoodExhaustion(0.005F);
}
@@ -120,25 +130,11 @@ public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntit
@Override
public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
super.playerWillDestroy(world, pos, state, player);
if (!(world instanceof ServerLevel serverWorld)) return;
if (!(world instanceof ServerLevel serverLevel)) return;
// We drop the item here instead of doing it in the harvest method, as we should
// drop computers for creative players too.
var tile = world.getBlockEntity(pos);
if (tile instanceof AbstractComputerBlockEntity computer) {
var context = new LootParams.Builder(serverWorld)
.withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos))
.withParameter(LootContextParams.TOOL, player.getMainHandItem())
.withParameter(LootContextParams.THIS_ENTITY, player)
.withParameter(LootContextParams.BLOCK_ENTITY, tile)
.withDynamicDrop(DROP, out -> out.accept(getItem(computer)));
for (var item : state.getDrops(context)) {
popResource(world, pos, item);
}
state.spawnAfterBreak(serverWorld, pos, player.getMainHandItem(), true);
}
dropResources(state, serverLevel, pos, world.getBlockEntity(pos));
}
@Override

View File

@@ -110,7 +110,7 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
fresh = false;
computerID = computer.getID();
// If the on state has changed, mark as as dirty.
// If the on state has changed, mark as dirty.
var newOn = computer.isOn();
if (on != newOn) {
on = newOn;
@@ -127,7 +127,7 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
// Update the block state if needed.
updateBlockState(computer.getState());
var changes = computer.pollAndResetChanges();
var changes = computer.pollRedstoneChanges();
if (changes != 0) {
for (var direction : DirectionUtil.FACINGS) {
if ((changes & (1 << remapToLocalSide(direction).ordinal())) != 0) updateRedstoneTo(direction);
@@ -195,8 +195,10 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
var offsetSide = dir.getOpposite();
var localDir = remapToLocalSide(dir);
computer.setRedstoneInput(localDir, RedstoneUtil.getRedstoneInput(getLevel(), targetPos, dir));
computer.setBundledRedstoneInput(localDir, BundledRedstone.getOutput(getLevel(), targetPos, offsetSide));
computer.setRedstoneInput(localDir,
RedstoneUtil.getRedstoneInput(getLevel(), targetPos, dir),
BundledRedstone.getOutput(getLevel(), targetPos, offsetSide)
);
}
/**

View File

@@ -134,8 +134,8 @@ public class ServerComputer implements InputHandler, ComputerEnvironment {
*
* @return What sides on the computer have changed.
*/
public int pollAndResetChanges() {
return computer.pollAndResetChanges();
public int pollRedstoneChanges() {
return computer.pollRedstoneChanges();
}
public UUID register() {
@@ -222,19 +222,15 @@ public class ServerComputer implements InputHandler, ComputerEnvironment {
}
public int getRedstoneOutput(ComputerSide side) {
return computer.getEnvironment().getExternalRedstoneOutput(side);
return computer.isOn() ? computer.getRedstone().getExternalOutput(side) : 0;
}
public void setRedstoneInput(ComputerSide side, int level) {
computer.getEnvironment().setRedstoneInput(side, level);
public void setRedstoneInput(ComputerSide side, int level, int bundledState) {
computer.getRedstone().setInput(side, level, bundledState);
}
public int getBundledRedstoneOutput(ComputerSide side) {
return computer.getEnvironment().getExternalBundledRedstoneOutput(side);
}
public void setBundledRedstoneInput(ComputerSide side, int combination) {
computer.getEnvironment().setBundledRedstoneInput(side, combination);
return computer.isOn() ? computer.getRedstone().getExternalBundledOutput(side) : 0;
}
public void setPeripheral(ComputerSide side, @Nullable IPeripheral peripheral) {

View File

@@ -4,16 +4,17 @@
package dan200.computercraft.shared.container;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
import net.minecraft.world.ContainerHelper;
import net.minecraft.world.item.ItemStack;
import java.util.List;
/**
* A basic implementation of {@link Container} which operates on a {@linkplain #getContents() list of stacks}.
*/
public interface BasicContainer extends Container {
NonNullList<ItemStack> getContents();
List<ItemStack> getContents();
@Override
default int getContainerSize() {

View File

@@ -15,7 +15,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType;
import java.util.Set;
/**
* A loot condition which checks if the tile entity has a non-0 ID.
* A loot condition which checks if the block entity has a computer ID.
*/
public final class HasComputerIdLootCondition implements LootItemCondition {
public static final HasComputerIdLootCondition INSTANCE = new HasComputerIdLootCondition();

View File

@@ -50,12 +50,12 @@ public class ItemDetails {
if (tag != null && tag.contains("display", Tag.TAG_COMPOUND)) {
var displayTag = tag.getCompound("display");
if (displayTag.contains("Lore", Tag.TAG_LIST)) {
var loreTag = displayTag.getList("Lore", Tag.TAG_STRING);
data.put("lore", loreTag.stream()
var lore = displayTag.getList("Lore", Tag.TAG_STRING).stream()
.map(ItemDetails::parseTextComponent)
.filter(Objects::nonNull)
.map(Component::getString)
.toList());
.toList();
if (!lore.isEmpty()) data.put("lore", lore);
}
}

View File

@@ -0,0 +1,142 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.lectern;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.media.items.PrintoutItem;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.stats.Stats;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LecternBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
/**
* Extends {@link LecternBlock} with support for {@linkplain PrintoutItem printouts}.
* <p>
* Unlike the vanilla lectern, this block is never empty. If the book is removed from the lectern, it converts back to
* its vanilla version (see {@link #clearLectern(Level, BlockPos, BlockState)}).
*
* @see PrintoutItem#useOn(UseOnContext) Placing books into a lectern.
*/
public class CustomLecternBlock extends LecternBlock {
public CustomLecternBlock(Properties properties) {
super(properties);
registerDefaultState(defaultBlockState().setValue(HAS_BOOK, true));
}
/**
* Replace a vanilla lectern with a custom one.
*
* @param level The current level.
* @param pos The position of the lectern.
* @param blockState The current state of the lectern.
* @param item The item to place in the custom lectern.
*/
public static void replaceLectern(Level level, BlockPos pos, BlockState blockState, ItemStack item) {
level.setBlockAndUpdate(pos, ModRegistry.Blocks.LECTERN.get().defaultBlockState()
.setValue(HAS_BOOK, true)
.setValue(FACING, blockState.getValue(FACING))
.setValue(POWERED, blockState.getValue(POWERED)));
if (level.getBlockEntity(pos) instanceof CustomLecternBlockEntity be) be.setItem(item.split(1));
}
/**
* Remove a custom lectern and replace it with an empty vanilla one.
*
* @param level The current level.
* @param pos The position of the lectern.
* @param blockState The current state of the lectern.
*/
static void clearLectern(Level level, BlockPos pos, BlockState blockState) {
level.setBlockAndUpdate(pos, Blocks.LECTERN.defaultBlockState()
.setValue(HAS_BOOK, false)
.setValue(FACING, blockState.getValue(FACING))
.setValue(POWERED, blockState.getValue(POWERED)));
}
@Override
@Deprecated
public ItemStack getCloneItemStack(BlockGetter level, BlockPos pos, BlockState state) {
return new ItemStack(Items.LECTERN);
}
@Override
public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
// If we've no lectern, remove it.
if (level.getBlockEntity(pos) instanceof CustomLecternBlockEntity lectern && lectern.getItem().isEmpty()) {
clearLectern(level, pos, state);
return;
}
super.tick(state, level, pos, random);
}
@Override
public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
if (state.is(newState.getBlock())) return;
if (level.getBlockEntity(pos) instanceof CustomLecternBlockEntity lectern) {
dropItem(level, pos, state, lectern.getItem().copy());
}
super.onRemove(state, level, pos, newState, isMoving);
}
private static void dropItem(Level level, BlockPos pos, BlockState state, ItemStack stack) {
if (stack.isEmpty()) return;
var direction = state.getValue(FACING);
var dx = 0.25 * direction.getStepX();
var dz = 0.25 * direction.getStepZ();
var entity = new ItemEntity(level, pos.getX() + 0.5 + dx, pos.getY() + 1, pos.getZ() + 0.5 + dz, stack);
entity.setDefaultPickUpDelay();
level.addFreshEntity(entity);
}
@Override
public String getDescriptionId() {
return Blocks.LECTERN.getDescriptionId();
}
@Override
public CustomLecternBlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new CustomLecternBlockEntity(pos, state);
}
@Override
public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
return level.getBlockEntity(pos) instanceof CustomLecternBlockEntity lectern ? lectern.getRedstoneSignal() : 0;
}
@Override
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (!level.isClientSide && level.getBlockEntity(pos) instanceof CustomLecternBlockEntity lectern) {
if (player.isSecondaryUseActive()) {
// When shift+clicked with an empty hand, drop the item and replace with the normal lectern.
clearLectern(level, pos, state);
} else {
// Otherwise open the screen.
player.openMenu(lectern);
}
player.awardStat(Stats.INTERACT_WITH_LECTERN);
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
}

View File

@@ -0,0 +1,193 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.lectern;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.container.BasicContainer;
import dan200.computercraft.shared.container.SingleContainerData;
import dan200.computercraft.shared.media.PrintoutMenu;
import dan200.computercraft.shared.media.items.PrintoutItem;
import dan200.computercraft.shared.util.BlockEntityHelpers;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.LecternBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.LecternBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.AbstractList;
import java.util.List;
/**
* The block entity for our {@link CustomLecternBlock}.
*
* @see LecternBlockEntity
*/
public final class CustomLecternBlockEntity extends BlockEntity implements MenuProvider {
private static final String NBT_ITEM = "Item";
private static final String NBT_PAGE = "Page";
private ItemStack item = ItemStack.EMPTY;
private int page, pageCount;
public CustomLecternBlockEntity(BlockPos pos, BlockState blockState) {
super(ModRegistry.BlockEntities.LECTERN.get(), pos, blockState);
}
public ItemStack getItem() {
return item;
}
void setItem(ItemStack item) {
this.item = item;
itemChanged();
BlockEntityHelpers.updateBlock(this);
}
int getRedstoneSignal() {
if (item.getItem() instanceof PrintoutItem) {
var progress = pageCount > 1 ? (float) page / (pageCount - 1) : 1F;
return Mth.floor(progress * 14f) + 1;
}
return 15;
}
/**
* Called after the item has changed. This sets up the state for the new item.
*/
private void itemChanged() {
if (item.getItem() instanceof PrintoutItem) {
pageCount = PrintoutItem.getPageCount(item);
page = Mth.clamp(page, 0, pageCount - 1);
} else {
pageCount = page = 0;
}
}
/**
* Set the current page, emitting a redstone pulse if needed.
*
* @param page The new page.
*/
private void setPage(int page) {
if (this.page == page) return;
this.page = page;
setChanged();
if (getLevel() != null) LecternBlock.signalPageChange(getLevel(), getBlockPos(), getBlockState());
}
@Override
public void load(CompoundTag tag) {
super.load(tag);
item = tag.contains(NBT_ITEM, Tag.TAG_COMPOUND) ? ItemStack.of(tag.getCompound(NBT_ITEM)) : ItemStack.EMPTY;
page = tag.getInt(NBT_PAGE);
itemChanged();
}
@Override
protected void saveAdditional(CompoundTag tag) {
super.saveAdditional(tag);
if (!item.isEmpty()) tag.put(NBT_ITEM, item.save(new CompoundTag()));
if (item.getItem() instanceof PrintoutItem) tag.putInt(NBT_PAGE, page);
}
@Override
public Packet<ClientGamePacketListener> getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
}
@Override
public CompoundTag getUpdateTag() {
var tag = super.getUpdateTag();
if (!item.isEmpty()) tag.put(NBT_ITEM, item.save(new CompoundTag()));
return tag;
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
var item = getItem();
if (item.getItem() instanceof PrintoutItem) {
return new PrintoutMenu(
containerId, new LecternContainer(), 0,
p -> Container.stillValidBlockEntity(this, player, Container.DEFAULT_DISTANCE_LIMIT),
new PrintoutContainerData()
);
}
return null;
}
@Override
public Component getDisplayName() {
return getItem().getDisplayName();
}
/**
* A read-only container storing the lectern's contents.
*/
private final class LecternContainer implements BasicContainer {
private final List<ItemStack> itemView = new AbstractList<>() {
@Override
public ItemStack get(int index) {
if (index != 0) throw new IndexOutOfBoundsException("Inventory only has one slot");
return item;
}
@Override
public int size() {
return 1;
}
};
@Override
public List<ItemStack> getContents() {
return itemView;
}
@Override
public void setChanged() {
// Should never happen, so a no-op.
}
@Override
public boolean stillValid(Player player) {
return !isRemoved();
}
}
/**
* {@link ContainerData} for a {@link PrintoutMenu}. This provides a read/write view of the current page.
*/
private final class PrintoutContainerData implements SingleContainerData {
@Override
public int get() {
return page;
}
@Override
public void set(int index, int value) {
if (index == 0) setPage(value);
}
}
}

View File

@@ -0,0 +1,136 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.media;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.container.InvisibleSlot;
import dan200.computercraft.shared.media.items.PrintoutItem;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import java.util.function.Predicate;
/**
* The menus for {@linkplain PrintoutItem printouts}.
* <p>
* This is a somewhat similar design to {@link LecternMenu}, which is used to read written books.
* <p>
* This holds a single slot (containing the printout), and a single data slot ({@linkplain #DATA_CURRENT_PAGE holding
* the current page}). The page is set by the client by sending a {@linkplain #clickMenuButton(Player, int) button
* press} with an index of {@link #PAGE_BUTTON_OFFSET} plus the current page.
* <p>
* The client-side screen uses {@linkplain ContainerListener container listeners} to subscribe to item and page changes.
* However, listeners aren't fired on the client, so we copy {@link LecternMenu}'s hack and call
* {@link #broadcastChanges()} whenever an item or data value are changed.
*/
public class PrintoutMenu extends AbstractContainerMenu {
public static final int DATA_CURRENT_PAGE = 0;
private static final int DATA_SIZE = 1;
public static final int PAGE_BUTTON_OFFSET = 100;
private final Predicate<Player> valid;
private final ContainerData currentPage;
public PrintoutMenu(
int containerId, Container container, int slotIdx, Predicate<Player> valid, ContainerData currentPage
) {
super(ModRegistry.Menus.PRINTOUT.get(), containerId);
this.valid = valid;
this.currentPage = currentPage;
addSlot(new InvisibleSlot(container, slotIdx) {
@Override
public void setChanged() {
super.setChanged();
slotsChanged(container); // Trigger listeners on the client.
}
});
addDataSlots(currentPage);
}
/**
* Create {@link PrintoutMenu} for use a remote (client).
*
* @param containerId The current container id.
* @return The constructed container.
*/
public static PrintoutMenu createRemote(int containerId) {
return new PrintoutMenu(containerId, new SimpleContainer(1), 0, p -> true, new SimpleContainerData(DATA_SIZE));
}
/**
* Create a {@link PrintoutMenu} for the printout in the current player's hand.
*
* @param containerId The current container id.
* @param player The player to open the container.
* @param hand The hand containing the item.
* @return The constructed container.
*/
public static PrintoutMenu createInHand(int containerId, Player player, InteractionHand hand) {
var currentStack = player.getItemInHand(hand);
var currentItem = currentStack.getItem();
var slot = switch (hand) {
case MAIN_HAND -> player.getInventory().selected;
case OFF_HAND -> Inventory.SLOT_OFFHAND;
};
return new PrintoutMenu(
containerId, player.getInventory(), slot,
p -> player.getItemInHand(hand).getItem() == currentItem, new SimpleContainerData(DATA_SIZE)
);
}
@Override
public ItemStack quickMoveStack(Player player, int index) {
return ItemStack.EMPTY;
}
@Override
public boolean stillValid(Player player) {
return valid.test(player);
}
@Override
public boolean clickMenuButton(Player player, int id) {
if (id >= PAGE_BUTTON_OFFSET) {
var page = Mth.clamp(id - PAGE_BUTTON_OFFSET, 0, PrintoutItem.getPageCount(getPrintout()) - 1);
setData(DATA_CURRENT_PAGE, page);
return true;
}
return super.clickMenuButton(player, id);
}
/**
* Get the current printout.
*
* @return The current printout.
*/
public ItemStack getPrintout() {
return getSlot(0).getItem();
}
/**
* Get the current page.
*
* @return The current page.
*/
public int getPage() {
return currentPage.get(DATA_CURRENT_PAGE);
}
@Override
public void setData(int id, int data) {
super.setData(id, data);
broadcastChanges(); // Trigger listeners on the client.
}
}

View File

@@ -4,18 +4,23 @@
package dan200.computercraft.shared.media.items;
import com.google.common.base.Strings;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.common.HeldItemMenu;
import dan200.computercraft.shared.network.container.HeldItemContainerData;
import dan200.computercraft.shared.lectern.CustomLecternBlock;
import dan200.computercraft.shared.media.PrintoutMenu;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LecternBlock;
import javax.annotation.Nullable;
import java.util.List;
@@ -50,12 +55,30 @@ public class PrintoutItem extends Item {
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (!world.isClientSide) {
new HeldItemContainerData(hand)
.open(player, new HeldItemMenu.Factory(ModRegistry.Menus.PRINTOUT.get(), player.getItemInHand(hand), hand));
public InteractionResult useOn(UseOnContext context) {
var level = context.getLevel();
var blockPos = context.getClickedPos();
var blockState = level.getBlockState(blockPos);
if (blockState.is(Blocks.LECTERN) && !blockState.getValue(LecternBlock.HAS_BOOK)) {
// If we have an empty lectern, place our book into it.
if (!level.isClientSide) {
CustomLecternBlock.replaceLectern(level, blockPos, blockState, context.getItemInHand());
}
return InteractionResult.sidedSuccess(level.isClientSide);
} else {
return InteractionResult.PASS;
}
return new InteractionResultHolder<>(InteractionResult.sidedSuccess(world.isClientSide), player.getItemInHand(hand));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
var stack = player.getItemInHand(hand);
if (!world.isClientSide) {
var title = getTitle(stack);
var displayTitle = Strings.isNullOrEmpty(title) ? stack.getDisplayName() : Component.literal(title);
player.openMenu(new SimpleMenuProvider((id, playerInventory, p) -> PrintoutMenu.createInHand(id, p, hand), displayTitle));
}
return new InteractionResultHolder<>(InteractionResult.sidedSuccess(world.isClientSide), stack);
}
private ItemStack createFromTitleAndText(@Nullable String title, @Nullable String[] text, @Nullable String[] colours) {

View File

@@ -1,37 +0,0 @@
// SPDX-FileCopyrightText: 2019 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.network.container;
import dan200.computercraft.shared.common.HeldItemMenu;
import dan200.computercraft.shared.media.items.PrintoutItem;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.InteractionHand;
/**
* Opens a printout GUI based on the currently held item.
*
* @see HeldItemMenu
* @see PrintoutItem
*/
public class HeldItemContainerData implements ContainerData {
private final InteractionHand hand;
public HeldItemContainerData(InteractionHand hand) {
this.hand = hand;
}
public HeldItemContainerData(FriendlyByteBuf buffer) {
hand = buffer.readEnum(InteractionHand.class);
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeEnum(hand);
}
public InteractionHand getHand() {
return hand;
}
}

View File

@@ -96,11 +96,13 @@ public final class DiskDriveBlockEntity extends AbstractContainerBlockEntity {
@Override
public void clearRemoved() {
super.clearRemoved();
updateMedia();
}
@Override
public void setRemoved() {
super.setRemoved();
if (recordPlaying) stopRecord();
}

View File

@@ -70,10 +70,10 @@ public abstract class AbstractFluidMethods<T> implements GenericPeripheral {
) throws LuaException;
/**
* Move a fluid from a connected fluid container into this oneone.
* Move a fluid from a connected fluid container into this one.
* <p>
* This allows you to pull fluid in the current fluid container from another container <em>on the same wired
* network</em>. Both containers must attached to wired modems which are connected via a cable.
* network</em>. Both containers must be attached to wired modems which are connected via a cable.
*
* @param to Container to move fluid to.
* @param computer The current computer.

View File

@@ -1,6 +1,6 @@
// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers
//
// SPDX-License-Identifier: LicenseRef-CCPL
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.peripheral.generic.methods;

View File

@@ -6,6 +6,7 @@ package dan200.computercraft.shared.peripheral.monitor;
import com.google.common.annotations.VisibleForTesting;
import dan200.computercraft.annotations.ForgeOverride;
import dan200.computercraft.api.peripheral.AttachedComputerSet;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.terminal.Terminal;
@@ -25,9 +26,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
public class MonitorBlockEntity extends BlockEntity {
@@ -53,7 +51,7 @@ public class MonitorBlockEntity extends BlockEntity {
private @Nullable ClientMonitor clientMonitor;
private @Nullable MonitorPeripheral peripheral;
private final Set<IComputerAccess> computers = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final AttachedComputerSet computers = new AttachedComputerSet();
private boolean needsUpdate = false;
private boolean needsValidating = false;
@@ -487,7 +485,7 @@ public class MonitorBlockEntity extends BlockEntity {
var monitor = getLoadedMonitor(x, y).getMonitor();
if (monitor == null) continue;
for (var computer : monitor.computers) fun.accept(computer);
monitor.computers.forEach(fun);
}
}
}

View File

@@ -0,0 +1,84 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.peripheral.redstone;
import dan200.computercraft.shared.common.IBundledRedstoneBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import javax.annotation.Nonnull;
/**
* The block for redstone relays. This mostly just forwards method calls to the {@linkplain RedstoneRelayBlockEntity
* block entity}.
*/
public final class RedstoneRelayBlock extends HorizontalDirectionalBlock implements EntityBlock, IBundledRedstoneBlock {
public RedstoneRelayBlock(Properties properties) {
super(properties);
registerDefaultState(defaultBlockState().setValue(FACING, Direction.NORTH));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> properties) {
properties.add(FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext placement) {
return defaultBlockState().setValue(FACING, placement.getHorizontalDirection());
}
@Override
@Deprecated
public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
super.tick(state, level, pos, random);
if (level.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay) relay.update();
}
@Override
@Deprecated
public boolean isSignalSource(@Nonnull BlockState state) {
return true;
}
@Override
@Deprecated
public int getDirectSignal(@Nonnull BlockState state, BlockGetter level, @Nonnull BlockPos pos, @Nonnull Direction incomingSide) {
return level.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay ? relay.getRedstoneOutput(incomingSide.getOpposite()) : 0;
}
@Override
@Deprecated
public int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return getDirectSignal(state, level, pos, direction);
}
@Override
public int getBundledRedstoneOutput(Level level, BlockPos pos, Direction side) {
return level.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay ? relay.getBundledRedstoneOutput(side) : 0;
}
@Override
@Deprecated
public void neighborChanged(@Nonnull BlockState state, @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, @Nonnull BlockPos neighbourPos, boolean isMoving) {
if (world.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay) relay.neighborChanged(neighbourPos);
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new RedstoneRelayBlockEntity(pos, state);
}
}

View File

@@ -0,0 +1,92 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.peripheral.redstone;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.computer.ComputerSide;
import dan200.computercraft.core.redstone.RedstoneState;
import dan200.computercraft.impl.BundledRedstone;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.RedstoneUtil;
import dan200.computercraft.shared.util.TickScheduler;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
public final class RedstoneRelayBlockEntity extends BlockEntity {
private final TickScheduler.Token tickToken = new TickScheduler.Token(this);
private final RedstoneState redstoneState = new RedstoneState(() -> TickScheduler.schedule(tickToken));
private final RedstoneRelayPeripheral peripheral = new RedstoneRelayPeripheral(redstoneState);
public RedstoneRelayBlockEntity(BlockPos pos, BlockState blockState) {
super(ModRegistry.BlockEntities.REDSTONE_RELAY.get(), pos, blockState);
}
@Override
public void clearRemoved() {
super.clearRemoved();
TickScheduler.schedule(tickToken);
}
void update() {
var changes = redstoneState.updateOutput();
if (changes != 0) {
for (var direction : DirectionUtil.FACINGS) {
if ((changes & (1 << mapSide(direction).ordinal())) != 0) updateRedstoneTo(direction);
}
}
if (redstoneState.pollInputChanged()) peripheral.queueRedstoneEvent();
}
void neighborChanged(BlockPos neighbour) {
for (var dir : DirectionUtil.FACINGS) {
var offset = getBlockPos().relative(dir);
if (offset.equals(neighbour)) {
updateRedstoneInput(dir, offset, false);
return;
}
}
// If the position is not any adjacent one, update all inputs. This is pretty terrible, but some redstone mods
// handle this incorrectly.
for (var dir : DirectionUtil.FACINGS) updateRedstoneInput(dir, getBlockPos().relative(dir), false);
}
private void updateRedstoneTo(Direction direction) {
RedstoneUtil.propagateRedstoneOutput(getLevel(), getBlockPos(), direction);
updateRedstoneInput(direction, getBlockPos().relative(direction), true);
}
private void updateRedstoneInput(Direction dir, BlockPos targetPos, boolean ticking) {
var changed = redstoneState.setInput(mapSide(dir),
RedstoneUtil.getRedstoneInput(getLevel(), targetPos, dir),
BundledRedstone.getOutput(getLevel(), targetPos, dir.getOpposite())
);
// If the input has changed, and we're not currently in update(), then schedule a new tick so we can queue a
// redstone event.
if (changed && !ticking) TickScheduler.schedule(tickToken);
}
private ComputerSide mapSide(Direction globalSide) {
return DirectionUtil.toLocal(getBlockState().getValue(HorizontalDirectionalBlock.FACING), globalSide);
}
int getRedstoneOutput(Direction side) {
return redstoneState.getExternalOutput(mapSide(side));
}
int getBundledRedstoneOutput(Direction side) {
return redstoneState.getExternalBundledOutput(mapSide(side));
}
public IPeripheral peripheral() {
return peripheral;
}
}

View File

@@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.peripheral.redstone;
import dan200.computercraft.api.peripheral.AttachedComputerSet;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.apis.RedstoneAPI;
import dan200.computercraft.core.apis.RedstoneMethods;
import dan200.computercraft.core.redstone.RedstoneAccess;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The redstone relay is a peripheral that allows reading and outputting redstone signals. While this is not very useful
* on its own (as computers have the same functionality [built-in][`redstone`]), this can be used with [wired
* modems][`modem`] to interact with multiple redstone signals from the same computer.
* <p>
* The peripheral provides largely identical methods to a computer's built-in {@link RedstoneAPI} API, allowing setting
* signals on all six sides of the block ("top", "bottom", "left", "right", "front" and "back").
*
* <p>
* ## Recipe
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:redstone_relay"></mc-recipe>
* </div>
*
* @cc.usage Toggle the redstone signal above the computer every 0.5 seconds.
*
* <pre>{@code
* local relay = peripheral.find("redstone_relay")
* while true do
* relay.setOutput("top", not relay.getOutput("top"))
* sleep(0.5)
* end
* }</pre>
* @cc.module redstone_relay
* @cc.since 1.114.0
*/
public final class RedstoneRelayPeripheral extends RedstoneMethods implements IPeripheral {
private final AttachedComputerSet computers = new AttachedComputerSet();
RedstoneRelayPeripheral(RedstoneAccess access) {
super(access);
}
@Nonnull
@Override
public String getType() {
return "redstone_relay";
}
@Override
public boolean equals(@Nullable IPeripheral other) {
return this == other;
}
@Override
public void attach(IComputerAccess computer) {
computers.add(computer);
}
@Override
public void detach(IComputerAccess computer) {
computers.remove(computer);
}
void queueRedstoneEvent() {
computers.queueEvent("redstone");
}
}

View File

@@ -4,11 +4,11 @@
package dan200.computercraft.shared.peripheral.speaker;
import com.google.errorprone.annotations.concurrent.GuardedBy;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.lua.LuaTable;
import dan200.computercraft.api.peripheral.AttachedComputerSet;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.util.Nullability;
@@ -33,7 +33,10 @@ import net.minecraft.world.item.RecordItem;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import javax.annotation.Nullable;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
@@ -60,7 +63,7 @@ public abstract class SpeakerPeripheral implements IPeripheral {
public static final int SAMPLE_RATE = 48000;
private final UUID source = UUID.randomUUID();
private final @GuardedBy("computers") Set<IComputerAccess> computers = new HashSet<>();
private final AttachedComputerSet computers = new AttachedComputerSet();
private long clock = 0;
private long lastPositionTime;
@@ -140,11 +143,7 @@ public abstract class SpeakerPeripheral implements IPeripheral {
syncedPosition(position);
// And notify computers that we have space for more audio.
synchronized (computers) {
for (var computer : computers) {
computer.queueEvent("speaker_audio_empty", computer.getAttachmentName());
}
}
computers.forEach(c -> c.queueEvent("speaker_audio_empty", c.getAttachmentName()));
}
// Push position updates to any speakers which have ever played a note,
@@ -353,16 +352,12 @@ public abstract class SpeakerPeripheral implements IPeripheral {
@Override
public void attach(IComputerAccess computer) {
synchronized (computers) {
computers.add(computer);
}
computers.add(computer);
}
@Override
public void detach(IComputerAccess computer) {
synchronized (computers) {
computers.remove(computer);
}
computers.remove(computer);
}
static double clampVolume(double volume) {

View File

@@ -30,6 +30,12 @@ import java.util.Objects;
* print("On something else")
* end
* }</pre>
* <p>
* ## Recipes
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:pocket_computer_normal"></mc-recipe>
* <mc-recipe recipe="computercraft:pocket_computer_advanced"></mc-recipe>
* </div>
*
* @cc.module pocket
*/

View File

@@ -24,6 +24,7 @@ import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
/**
* Holds additional state for a pocket computer. This includes pocket computer upgrade,
@@ -177,7 +178,9 @@ public final class PocketBrain implements IPocketAccess {
*/
@Override
public void setUpgrade(@Nullable UpgradeData<IPocketUpgrade> upgrade) {
this.upgrade = upgrade;
if (Objects.equals(this.upgrade, upgrade)) return;
this.upgrade = UpgradeData.copyOf(upgrade);
dirty = true;
invalidatePeripheral();
}

View File

@@ -128,12 +128,16 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
}
@Override
public void inventoryTick(ItemStack stack, Level world, Entity entity, int slotNum, boolean selected) {
public void inventoryTick(ItemStack stack, Level world, Entity entity, int compartmentSlot, boolean selected) {
// This (in vanilla at least) is only called for players. Don't bother to handle other entities.
if (world.isClientSide || !(entity instanceof ServerPlayer player)) return;
// Find the actual slot the item exists in, aborting if it can't be found.
var slot = InventoryUtil.getInventorySlotFromCompartment(player, compartmentSlot, stack);
if (slot < 0) return;
// If we're in the inventory, create a computer and keep it alive.
var holder = new PocketHolder.PlayerHolder(player, slotNum);
var holder = new PocketHolder.PlayerHolder(player, slot);
var brain = getOrCreateBrain((ServerLevel) world, holder, stack);
brain.computer().keepAlive();
@@ -263,6 +267,21 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
return getServerComputer(ServerContext.get(server).registry(), stack);
}
@Override
public void onCraftedBy(ItemStack stack, Level level, Player player) {
var tag = stack.getTag();
if (tag == null) return;
// Normally we treat the computer instance as the source of truth, and copy the computer's state back to the
// item. However, if we've just crafted the computer with an upgrade, we should sync the other way, and update
// the computer.
var server = level.getServer();
if (server != null) {
var computer = getServerComputer(server, stack);
if (computer != null) computer.getBrain().setUpgrade(getUpgradeWithData(stack));
}
}
// IComputerItem implementation
private static void setComputerID(ItemStack stack, int computerID) {

View File

@@ -47,18 +47,24 @@ import java.util.Optional;
* <p>
* ## Turtle upgrades
* While a normal turtle can move about the world and place blocks, its functionality is limited. Thankfully, turtles
* can be upgraded with *tools* and [peripherals][`peripheral`]. Turtles have two upgrade slots, one on the left and right
* sides. Upgrades can be equipped by crafting a turtle with the upgrade, or calling the [`turtle.equipLeft`]/[`turtle.equipRight`]
* functions.
* can be upgraded with upgrades. Turtles have two upgrade slots, one on the left and right sides. Upgrades can be
* equipped by crafting a turtle with the upgrade, or calling the [`turtle.equipLeft`]/[`turtle.equipRight`] functions.
* <p>
* Turtle tools allow you to break blocks ([`turtle.dig`]) and attack entities ([`turtle.attack`]). Some tools are more
* suitable to a task than others. For instance, a diamond pickaxe can break every block, while a sword does more
* damage. Other tools have more niche use-cases, for instance hoes can til dirt.
* By default, any diamond tool may be used as an upgrade (though more may be added with [datapacks]). The diamond
* pickaxe may be used to break blocks (with [`turtle.dig`]), while the sword can attack entities ([`turtle.attack`]).
* Other tools have more niche use-cases, for instance hoes can til dirt.
* <p>
* Peripherals (such as the [wireless modem][`modem`] or [`speaker`]) can also be equipped as upgrades. These are then
* accessible by accessing the `"left"` or `"right"` peripheral.
* Some peripherals (namely [speakers][`speaker`] and Ender and Wireless [modems][`modem`]) can also be equipped as
* upgrades. These are then accessible by accessing the `"left"` or `"right"` peripheral.
* <p>
* ## Recipes
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:turtle_normal"></mc-recipe>
* <mc-recipe recipe="computercraft:turtle_advanced"></mc-recipe>
* </div>
* <p>
* [Turtle Graphics]: https://en.wikipedia.org/wiki/Turtle_graphics "Turtle graphics"
* [datapacks]: https://datapacks.madefor.cc ""
*
* @cc.module turtle
* @cc.since 1.3
@@ -345,7 +351,7 @@ public class TurtleAPI implements ILuaAPI {
* For instance, if a slot contains 13 blocks of dirt, it has room for another 51.
*
* @param slot The slot we wish to check. Defaults to the {@link #select selected slot}.
* @return The space left in in this slot.
* @return The space left in this slot.
* @throws LuaException If the slot is out of range.
*/
@LuaFunction

View File

@@ -125,11 +125,15 @@ public class TurtleBlock extends AbstractComputerBlock<TurtleBlockEntity> implem
public final void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
if (state.is(newState.getBlock())) return;
if (!level.isClientSide && level.getBlockEntity(pos) instanceof TurtleBlockEntity turtle && !turtle.hasMoved()) {
Containers.dropContents(level, pos, turtle);
}
// Most blocks drop items and then remove the BE. However, if a turtle is consuming drops right now, that can
// lead to loops where it tries to insert an item back into the inventory. To prevent this, take a reference to
// the turtle BE now, remove it, and then drop the items.
var turtle = !level.isClientSide && level.getBlockEntity(pos) instanceof TurtleBlockEntity t && !t.hasMoved()
? t : null;
super.onRemove(state, level, pos, newState, isMoving);
if (turtle != null) Containers.dropContents(level, pos, turtle);
}
@Override

View File

@@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.util;
import net.minecraft.util.FastColor;
/**
* Utilities for working with 32-bit ARGB colours.
*
* @see FastColor.ARGB32
*/
public final class ARGB32 {
private ARGB32() {
}
/**
* Set the alpha channel to be fully opaque.
*
* @param colour The colour to make opaque.
* @return The fully-opaque colour
*/
public static int opaque(int colour) {
return 0xFF000000 | colour;
}
/**
* Convert an ARGB32 colour to a {@linkplain FastColor.ABGR32 ABGR32} one.
*
* @param colour The colour to convert.
* @return The converted colour.
*/
public static int toABGR32(int colour) {
// Swap B and R components, converting ARGB32 to ABGR32.
return colour & 0xFF00FF00 | (colour & 0xFF0000) >> 16 | (colour & 0xFF) << 16;
}
}

View File

@@ -9,9 +9,12 @@ import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.Container;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
@@ -35,6 +38,28 @@ public final class InventoryUtil {
};
}
/**
* Map a slot inside a player's compartment to a slot in the full player's inventory.
* <p>
* {@link Inventory#tick()} passes in a slot to {@link Item#inventoryTick(ItemStack, Level, Entity, int, boolean)}.
* However, this slot corresponds to the index within the current compartment (items, armour, offhand) and not
* the actual slot.
* <p>
* This method searches the relevant compartments (inventory and offhand, skipping armour) for the stack, returning
* its slot if found.
*
* @param player The player holding the item.
* @param slot The slot inside the compartment.
* @param stack The stack being ticked.
* @return The inventory slot, or {@code -1} if the item could not be found in the inventory.
*/
public static int getInventorySlotFromCompartment(Player player, int slot, ItemStack stack) {
if (stack.isEmpty()) throw new IllegalArgumentException("Cannot search for empty stack");
if (player.getInventory().getItem(slot) == stack) return slot;
if (player.getInventory().getItem(Inventory.SLOT_OFFHAND) == stack) return Inventory.SLOT_OFFHAND;
return -1;
}
public static @Nullable Container getEntityContainer(ServerLevel level, BlockPos pos, Direction side) {
var vecStart = new Vec3(
pos.getX() + 0.5 + 0.6 * side.getStepX(),

View File

@@ -109,8 +109,9 @@ public final class TickScheduler {
return State.UNLOADED;
} else {
// This should be impossible: either the block entity is at the above position, or it has been removed.
if (level.getBlockEntity(pos) != blockEntity) {
throw new IllegalStateException("Expected " + blockEntity + " at " + pos);
var currentBlockEntity = level.getBlockEntity(pos);
if (currentBlockEntity != blockEntity) {
throw new IllegalStateException("Expected " + blockEntity + " at " + pos + ", got " + currentBlockEntity);
}
// Otherwise schedule a tick and remove it from the queue.

View File

@@ -32,8 +32,6 @@
"commands.computercraft.generic.additional_rows": "%d řádků navíc…",
"commands.computercraft.generic.exception": "Neočekávaná chyba (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<žádná pozice>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "A",
"commands.computercraft.help.desc": "Ukáže tuto pomocnou zprávu",
"commands.computercraft.help.no_children": "%s nemá žádné podpříkazy",
@@ -98,6 +96,7 @@
"gui.computercraft.config.http.max_requests.tooltip": "Počet HTTP požadavků které počítač může udělat v jedné chvíli. Požadavky navíc\nbudou zaslány do fronty, a poslány když běžící požadavky byly dokončeny. Nastav\nna 0 pro neomezeno.\nRozsah: > 0",
"gui.computercraft.config.http.max_websockets": "Maximální souběžné websockety",
"gui.computercraft.config.http.max_websockets.tooltip": "Počet websocketů které může mít počítač otevřené najednou: Nastav na 0 pro neomezeno.\nRozsah: > 1",
"gui.computercraft.config.http.proxy": "Proxy",
"gui.computercraft.config.http.proxy.host": "Název hostitele",
"gui.computercraft.config.http.proxy.host.tooltip": "Název hostitele nebo IP adresa proxy serveru.",
"gui.computercraft.config.http.proxy.port": "Port",
@@ -164,6 +163,7 @@
"gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "Limit paliva pro roboty.\nRozsah: > 0",
"gui.computercraft.config.turtle.tooltip": "Různé možnosti o robotech.",
"gui.computercraft.config.upload_max_size": "Limit velikosti nahrávaného souboru (v bajtech)",
"gui.computercraft.config.upload_max_size.tooltip": "Limit velikosti nahrávaného souboru v bytech. Musí být v rozmezí od 1 KiB do 16 MiB.\nMěj na paměti, že nahrávání souborů je zpracováváno v jednom ticku - velké soubory nebo\nšpatný výkon sítě mohou zpomalit síťové vlákno. A nezapomeň na místo na disku!\nRozsah: 1024 ~ 16777216",
"gui.computercraft.config.upload_nag_delay": "Nahrání zpoždění nag",
"gui.computercraft.config.upload_nag_delay.tooltip": "Zpoždění v sekundách po kterém oznámíme o nezpracovaných importech. Nastav na 0 pro vypnutí.\nRozsah: 0 ~ 60",
"gui.computercraft.pocket_computer_overlay": "Kapesní počítač otevřen. Zmáčkni ESC pro uzavření.",
@@ -195,6 +195,10 @@
"item.computercraft.printed_pages": "Tisknuté stránky",
"item.computercraft.treasure_disk": "Disketa",
"itemGroup.computercraft": "ComputerCraft",
"tag.item.computercraft.computer": "Počítače",
"tag.item.computercraft.monitor": "Monitory",
"tag.item.computercraft.turtle": "Roboti",
"tag.item.computercraft.wired_modem": "Drátové modemy",
"tracking_field.computercraft.avg": "%s (průměr)",
"tracking_field.computercraft.computer_tasks.name": "Úlohy",
"tracking_field.computercraft.count": "%s (počet)",
@@ -216,11 +220,5 @@
"upgrade.minecraft.diamond_hoe.adjective": "Farmářský",
"upgrade.minecraft.diamond_pickaxe.adjective": "Těžební",
"upgrade.minecraft.diamond_shovel.adjective": "Kopací",
"upgrade.minecraft.diamond_sword.adjective": "Bojový",
"tag.item.computercraft.computer": "Počítače",
"tag.item.computercraft.monitor": "Monitory",
"tag.item.computercraft.turtle": "Roboti",
"tag.item.computercraft.wired_modem": "Drátové modemy",
"gui.computercraft.config.http.proxy": "Proxy",
"gui.computercraft.config.upload_max_size.tooltip": "Limit velikosti nahrávaného souboru v bytech. Musí být v rozmezí od 1 KiB do 16 MiB.\nMěj na paměti, že nahrávání souborů je zpracováváno v jednom ticku - velké soubory nebo\nšpatný výkon sítě mohou zpomalit síťové vlákno. A nezapomeň na místo na disku!\nRozsah: 1024 ~ 16777216"
"upgrade.minecraft.diamond_sword.adjective": "Bojový"
}

View File

@@ -1,8 +1,13 @@
{
"argument.computercraft.argument_expected": "Parameter erwartet",
"argument.computercraft.computer.family": "Computer familie",
"argument.computercraft.computer.id": "Computer ID",
"argument.computercraft.computer.instance": "einzigartige Instanz ID",
"argument.computercraft.computer.label": "Computer name",
"argument.computercraft.computer.many_matching": "Mehrere Computer passen auf '%s' (Instanzen %s)",
"argument.computercraft.computer.no_matching": "Kein Computer passt auf '%s'",
"argument.computercraft.tracking_field.no_field": "Unbekanntes Feld '%s'",
"argument.computercraft.unknown_computer_family": "Unbekannte computer familie '%s'",
"block.computercraft.cable": "Netzwerkkabel",
"block.computercraft.computer_advanced": "Erweiterter Computer",
"block.computercraft.computer_command": "Befehlscomputer",
@@ -11,6 +16,7 @@
"block.computercraft.monitor_advanced": "Erweiterter Monitor",
"block.computercraft.monitor_normal": "Monitor",
"block.computercraft.printer": "Drucker",
"block.computercraft.redstone_relay": "Redstone Relais",
"block.computercraft.speaker": "Lautsprecher",
"block.computercraft.turtle_advanced": "Erweiterte Turtle",
"block.computercraft.turtle_advanced.upgraded": "Erweiterte Turtle (%s)",
@@ -32,8 +38,6 @@
"commands.computercraft.generic.additional_rows": "%d zusätzliche Zeilen…",
"commands.computercraft.generic.exception": "Unbehandelte Ausnahme (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<Keine Position>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "J",
"commands.computercraft.help.desc": "Zeigt diese Hilfe Nachricht",
"commands.computercraft.help.no_children": "%s hat keine Unterbefehle",
@@ -82,8 +86,16 @@
"gui.computercraft.config.execution.max_main_computer_time": "Computer Servertick Zeitlimit",
"gui.computercraft.config.execution.max_main_computer_time.tooltip": "Die ideale maximale Zeit, in der ein Computer laufen kann im innerhalb von einem tick in Millisekunden.\nBeachte, dass wir wahrscheinlich über diesen Limit gehen werden, da es unmöglich ist zu bestimmen,\nwie lange ein Computer brauchen wird. Dies wird also die höhere Grenze der durchschnittlichen Zeit darstellen.\nBereich: > 1",
"gui.computercraft.config.execution.max_main_global_time": "Globales Servertick Zeitlimit",
"gui.computercraft.config.execution.max_main_global_time.tooltip": "Die maximale Zeit in millisekunden, in der Aufgaben ausgeführt werden.\nAnmerkung: Diese Zeit wird höchstwarscheinlich überschritten und dient nur als ungefähre Grenze.\nLimit: > 1",
"gui.computercraft.config.floppy_space_limit": "Speicherplatz von Disketten (Bytes)",
"gui.computercraft.config.floppy_space_limit.tooltip": "Die maximale Dateisystem Größe von Disketten (in bytes).",
"gui.computercraft.config.http": "HTTP",
"gui.computercraft.config.http.bandwidth": "Bandbreite",
"gui.computercraft.config.http.bandwidth.global_download": "Globales download limit",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "Die maximale Geschwindigkeit aller Computer in bytes/s mit der Heruntergeladen werden kann.\nBereich: > 1",
"gui.computercraft.config.http.bandwidth.global_upload": "Globales upload limit",
"gui.computercraft.config.http.bandwidth.global_upload.tooltip": "Die maximale Hochladungs Geschwindigkeit aller Computer in bytes/s.\nBereich: > 1",
"gui.computercraft.config.http.bandwidth.tooltip": "Limitiert die Bandbreite der Computer.",
"gui.computercraft.config.http.enabled": "HTTP-API aktivieren",
"gui.computercraft.config.http.max_requests": "Maximale Anzahl gleichzeitiger Anfragen",
"gui.computercraft.config.http.max_websockets": "Maximale Anzahl gleichzeitiger Websockets",
@@ -130,18 +142,5 @@
"upgrade.minecraft.diamond_hoe.adjective": "Ackerbau",
"upgrade.minecraft.diamond_pickaxe.adjective": "Bergbau",
"upgrade.minecraft.diamond_shovel.adjective": "Graben",
"upgrade.minecraft.diamond_sword.adjective": "Nahkampf",
"argument.computercraft.computer.id": "Computer ID",
"argument.computercraft.computer.instance": "einzigartige Instanz ID",
"argument.computercraft.computer.label": "Computer name",
"argument.computercraft.unknown_computer_family": "Unbekannte computer familie '%s'",
"gui.computercraft.config.floppy_space_limit.tooltip": "Die maximale Dateisystem Größe von Disketten (in bytes).",
"gui.computercraft.config.http.bandwidth": "Bandbreite",
"gui.computercraft.config.http.bandwidth.global_upload": "Globales upload limit",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "Die maximale Geschwindigkeit aller Computer in bytes/s mit der Heruntergeladen werden kann.\nBereich: > 1",
"gui.computercraft.config.http.bandwidth.global_download": "Globales download limit",
"gui.computercraft.config.http.bandwidth.tooltip": "Limitiert die Bandbreite der Computer.",
"argument.computercraft.computer.family": "Computer familie",
"gui.computercraft.config.execution.max_main_global_time.tooltip": "Die maximale Zeit in millisekunden, in der Aufgaben ausgeführt werden.\nAnmerkung: Diese Zeit wird höchstwarscheinlich überschritten und dient nur als ungefähre Grenze.\nLimit: > 1",
"gui.computercraft.config.http.bandwidth.global_upload.tooltip": "Die maximale Hochladungs Geschwindigkeit aller Computer in bytes/s.\nBereich: > 1"
"upgrade.minecraft.diamond_sword.adjective": "Nahkampf"
}

View File

@@ -1,6 +1,14 @@
{
"argument.computercraft.argument_expected": "Argumento esperado",
"argument.computercraft.computer.distance": "Distancia a entidad",
"argument.computercraft.computer.family": "Familia de computadoras",
"argument.computercraft.computer.id": "ID de la computadora",
"argument.computercraft.computer.instance": "ID de instancia único",
"argument.computercraft.computer.label": "Etiqueta de la computadora",
"argument.computercraft.computer.many_matching": "Varias computadoras que coinciden con ' %s' (instancias %s)",
"argument.computercraft.computer.no_matching": "No hay ordenadores que coincidan con '%s'",
"argument.computercraft.tracking_field.no_field": "Campo desconocido '%s'",
"argument.computercraft.unknown_computer_family": "Familia de ordenadores desconocida '%s'",
"block.computercraft.cable": "Cable de red",
"block.computercraft.computer_advanced": "Ordenador avanzado",
"block.computercraft.computer_command": "Ordenador de Comandos",
@@ -22,31 +30,167 @@
"block.computercraft.wireless_modem_normal": "Módem sin cables",
"chat.computercraft.wired_modem.peripheral_connected": "El periférico \"%s\" se conectó a la red",
"chat.computercraft.wired_modem.peripheral_disconnected": "El periférico \"%s\" se desconectó de la red",
"commands.computercraft.desc": "El comando /computercraft proporciona varias herramientas de depuración y administración para controlar e interactuar con computadoras.",
"commands.computercraft.dump.action": "Ver más info acerca de esta computadora",
"commands.computercraft.dump.desc": "Muestra el estado de todas las computadoras o información específica sobre una computadora. Puedes especificar el id de instancia de la computadora (ej. 123), el id de la computadora (ej. #123) o su etiqueta (ej. \"@Mi computadora\").",
"commands.computercraft.dump.open_path": "Ver los archivos de esta computadora",
"commands.computercraft.dump.synopsis": "Mostrar el estado de las computadoras.",
"commands.computercraft.generic.additional_rows": "%d filas adicionales…",
"commands.computercraft.generic.exception": "Excepción no controlada (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<sin pos>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "Y",
"commands.computercraft.help.desc": "Muestra este mensaje de ayuda",
"commands.computercraft.help.no_children": "%s no tiene sub-comandos",
"commands.computercraft.help.no_command": "Sin comando '%s'",
"commands.computercraft.help.synopsis": "Provee ayuda para un comando específico",
"commands.computercraft.queue.desc": "Envía un evento computer_command a un ordenador de comandos, pasándole los argumentos adicionales. Esto está diseñado principalmente para los map makers, actuando como una versión más amigable con el ordenador de /trigger. Cualquier jugador puede ejecutar el comando, lo que probablemente se haría a través de un evento de clic de un componente de texto.",
"commands.computercraft.queue.synopsis": "Envía un evento computer_command a un ordenador de comandos",
"commands.computercraft.shutdown.desc": "Apagar las computadoras listadas o todas si ninguna se especifica. Puedes especificar el id de la instancia de la computadora (ej. 123), el id de la computadora (ej. #123) o la etiqueta (ej. \"@Mi Computadora\").",
"commands.computercraft.shutdown.done": "Apague %s/%s computadoras",
"commands.computercraft.shutdown.synopsis": "Apague las computadoras de forma remota.",
"commands.computercraft.synopsis": "Varios comandos para controlar computadoras.",
"commands.computercraft.tp.action": "Teletransportarse a esta computadora",
"commands.computercraft.tp.desc": "Teletransportarse a la ubicación de una computadora. Puedes especificar tanto el id de la instancia de la computadora (ej. 123) o el id de la computadora (ej. #123).",
"commands.computercraft.tp.synopsis": "Teletransportarse a una computadora específica.",
"commands.computercraft.track.desc": "Seguimiento de qué tanto se ejecutan las computadoras, y también cuántos eventos manejan. Esto presenta información en una manera similar a /forge track y puede ser útil para diagnosticar lag.",
"commands.computercraft.track.dump.computer": "Computadora",
"commands.computercraft.track.dump.desc": "Volcar los últimos resultados del seguimiento de computadoras.",
"commands.computercraft.track.dump.no_timings": "No hay temporizaciones disponibles",
"commands.computercraft.track.dump.synopsis": "Volcar los últimos resultados de seguimiento",
"commands.computercraft.track.start.desc": "Comenzar el seguimiento de todos los tiempos y conteo de eventos de las computadoras. Esto va a descartar los resultados de ejecuciones previas.",
"commands.computercraft.track.start.stop": "Ejecute %s para detener el seguimiento y ver los resultados",
"commands.computercraft.track.start.synopsis": "Comenzar el seguimiento de todas las computadoras",
"commands.computercraft.track.stop.action": "Clic para detener el seguimiento",
"commands.computercraft.track.stop.desc": "Detener el seguimiento de todos los eventos y tiempos de ejecución de las computadoras",
"commands.computercraft.track.stop.not_enabled": "Actualmente no hay computadoras en seguimiento",
"commands.computercraft.track.stop.synopsis": "Dejar de seguir a todas las computadoras",
"commands.computercraft.track.synopsis": "Seguimiento de tiempos de ejecución para computadoras.",
"commands.computercraft.turn_on.desc": "Encender las computadoras listadas. Puedes especificar el id de la instancia de la computadora (ej. 123), el id de la computadora (ej. #123) o la etiqueta (ej. \"@Mi computadora\").",
"commands.computercraft.turn_on.done": "Encendidas %s/%s computadoras",
"commands.computercraft.turn_on.synopsis": "Encender computadoras remotamente.",
"commands.computercraft.view.action": "Ver esta computadora",
"commands.computercraft.view.desc": "Abrir la terminal de una computadora, permitiendo el control remoto de esta. Esto no proporciona acceso al inventario de tortugas. Puede tanto especificar el Id de instancia de la computadora (ej. 123) o el Id de la computadora (ej. #123).",
"commands.computercraft.view.not_player": "No se puede abrir la terminal para un no-jugador",
"commands.computercraft.view.synopsis": "Ver la terminal de una computadora",
"gui.computercraft.config.command_require_creative": "Las computadoras de comando requieren creativo",
"gui.computercraft.config.command_require_creative.tooltip": "Requiere que los jugadores estén en modo creativo y sean operadores para\ninteractuar con las computadoras de comandos. Este es el comportamiento\npredeterminado para los bloques de comandos en vanilla.",
"gui.computercraft.config.computer_space_limit": "Límite de memoria de ordenadores (en bytes)",
"gui.computercraft.config.computer_space_limit.tooltip": "Límite de espacio en disco para computadoras y tortugas, en bytes.",
"gui.computercraft.config.default_computer_settings": "Configuración de Ordenador por defecto",
"gui.computercraft.config.default_computer_settings.tooltip": "Una lista separada por comas de los ajustes predeterminados para establecer en nuevas computadoras.\nEjemplo: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\ndeshabilitará todo el autocompletado.",
"gui.computercraft.config.disabled_generic_methods": "Métodos genéricos desactivados",
"gui.computercraft.config.disabled_generic_methods.tooltip": "Una lista de métodos genéricos o métodos de fuente para deshabilitar. Los\nmétodos genéricos son métodos añadidos a un bloque/block entity cuando no hay\nun proveedor de periférico explícito. Esto incluye métodos de inventario (ej.\ninventory.getItemDetail, inventory.pushItems), y (si está en Forge), los\nmétodos fluid_storage y energy_storage.\nLos métodos en esta lista pueden ser tanto un grupo entero de métodos\n(computercraft:inventory) o un método en particular\n(computercraft:inventory#pushItems).\n",
"gui.computercraft.config.execution": "Ejecución",
"gui.computercraft.config.execution.computer_threads": "Hilos de la computadora",
"gui.computercraft.config.execution.computer_threads.tooltip": "Establece el número de hilos en los que las computadoras pueden correr. Un número\nmás alto significa que más computadoras pueden ejecutarse a la vez, pero podrían\ninducir lag. Ten en cuenta que algunos mods podrían no funcionar con un número de\nhilos mayor a 1. Usar con precaución.\nRango: > 1",
"gui.computercraft.config.execution.max_main_computer_time": "Límite de tiempo de la computadora en un tick del servidor",
"gui.computercraft.config.execution.max_main_global_time": "Límite de tiempo global en un tick del servidor",
"gui.computercraft.config.execution.tooltip": "Controla el comportamiento de ejecución de las computadoras. Esto es\nen gran medida destinado al control fino para servidores, y generalmente no\ndebería ser cambiado.",
"gui.computercraft.config.floppy_space_limit": "Límite de memoria de disquetes (en bytes)",
"gui.computercraft.config.floppy_space_limit.tooltip": "El límite de espacio en disco para los disquetes, en bytes.",
"gui.computercraft.config.http": "HTTP",
"gui.computercraft.config.http.bandwidth": "Ancho de banda",
"gui.computercraft.config.http.bandwidth.global_download": "Límite de descarga global",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "El número de bytes que se pueden descargar por segundo. Esto es compartido para todas las computadoras. (bytes/s).\nRango: > 1",
"gui.computercraft.config.http.bandwidth.global_upload": "Límite de subida global",
"gui.computercraft.config.http.bandwidth.global_upload.tooltip": "El número de bytes que se pueden subir por segundo. Esto es compartido para todas las computadoras. (bytes/s).\nRango: > 1",
"gui.computercraft.config.http.bandwidth.tooltip": "Limita el ancho de banda usado por las computadoras.",
"gui.computercraft.config.http.enabled": "Habilitar API de HTTP",
"gui.computercraft.config.http.enabled.tooltip": "Habilitar la API \"http\" en computadoras. Deshabilitar esto también desactiva los\nprogramas \"pastebin\" y \"wget\", los cuales muchos usuarios dependen. Se recomienda\ndejar esto encendido y usar la opción \"reglas\" en configuración para imponer un\ncontrol más fino.",
"gui.computercraft.config.http.max_requests": "Máximo de solicitudes simultáneas",
"gui.computercraft.config.http.max_requests.tooltip": "El número de solicitudes http que un equipo puede hacer a la vez. Las solicitudes\nadicionales se pondrán en cola, y se enviarán cuando las solicitudes en ejecución\nhayan finalizado. Establezca 0 para ilimitado.\nRango: > 0",
"gui.computercraft.config.http.max_websockets": "Máximos websockets concurrentes",
"gui.computercraft.config.http.max_websockets.tooltip": "El número de websockets que una computadora puede tener abierto\nen el mismo momento.\nRango: > 1",
"gui.computercraft.config.http.proxy": "Proxy",
"gui.computercraft.config.http.proxy.host": "Nombre del host",
"gui.computercraft.config.http.proxy.host.tooltip": "El nombre del host o la dirección IP del servidor proxy.",
"gui.computercraft.config.http.proxy.port": "Puerto",
"gui.computercraft.config.http.proxy.port.tooltip": "El puerto del servidor proxy.\nRango: 1 ~ 65536",
"gui.computercraft.config.http.proxy.tooltip": "Pasa los pedidos HTTP y websocket a través de un servidor proxy. Solo afecta a las\nreglas HTTP con \"use_proxy\" puesto en verdadero (falso por defecto).\nSi se requiere autenticación para el proxy, crea un archivo\n\"computercraft-proxy.pw\" en la misma carpeta que se encuentra\n\"computercraft-server.toml\", conteniendo el nombre de usuario y contraseña\nseparada por dos puntos, por ejemplo: \"miusuario:micontraseña\". Para proxys\nSOCKS4 solo se requiere el nombre de usuario.",
"gui.computercraft.config.http.proxy.type": "Tipo de proxy",
"gui.computercraft.config.http.proxy.type.tooltip": "El tipo de proxy a utilizar.\nValores permitidos: HTTP, HTTPS, SOCKS4, SOCKS5",
"gui.computercraft.config.http.rules": "Reglas de permitir/denegar",
"gui.computercraft.config.http.rules.tooltip": "Una lista de reglas que controlan el comportamiento de la API \"http\" para dominios\nespecíficos o IPs. Cada regla aplica a un hostname y un puerto opcional, y luego\nestablece varias propiedades para el pedido. Las reglas son evaluadas en orden,\nlo que quiere decir que las reglas primeras sobreescriben a las de después.\n\nPropiedades válidas:\n - \"host\" (requerido): El dominio o dirección IP con el que la regla va a operar.\n Este puede ser nombre de dominio (\"pastebin.com\"), wildcard (\"*.pastebin.com\")\n o notación CIDR (\"127.0.0.0/8\").\n - \"port\" (opcional): Solo aplicar a pedidos para un puerto específico, como 80\n o 443.\n - \"action\" (opcional): Permitir o denegar este pedido.\n - \"max_download\" (opcional): El tamaño máximo (en bytes) que una computadora \n puede descargar en este pedido.\n - \"max_upload\" (opcional): El tamaño máximo (en bytes) que una computadora puede\n subir en este pedido.\n - \"max_websocket_message\" (opcional): El tamaño máximo (en bytes) que una\n computadora puede enviar en un paquete websocket.\n - \"use_proxy\" (opcional): Habilitar el uso de el proxy HTTP/SOCKS si está\n configurado.",
"gui.computercraft.config.http.tooltip": "Controla la API HTTP",
"gui.computercraft.config.http.websocket_enabled": "Habilitar websockets",
"gui.computercraft.config.http.websocket_enabled.tooltip": "Habilita el uso de websockets http. Esto requiere que la opción \"http_enable\" sea verdadera.",
"gui.computercraft.config.log_computer_errors": "Grabar errores periféricos",
"gui.computercraft.config.log_computer_errors.tooltip": "Registra excepciones lanzadas por los periféricos y otros objetos de Lua. Esto facilita\ndepurar problemas para los autores de mods, pero puede resultar en spam en el\nregistro si la gente utiliza métodos con errores potenciales.",
"gui.computercraft.config.maximum_open_files": "Archivos abiertos máximos por cada ordenador",
"gui.computercraft.config.maximum_open_files.tooltip": "Establece cuántos archivos puede tener abiertos una computadora al mismo tiempo. Establezca 0 para ilimitados.\nRango: > 0",
"gui.computercraft.config.monitor_distance": "Distancia al monitor",
"gui.computercraft.config.monitor_distance.tooltip": "La distancia máxima a la que los monitores se renderizarán. El valor\npredeterminado es el límite de los tile entities, pero puede ser extendido si quieres\nconstruir monitores más grandes.\nRango: 16 ~ 1024",
"gui.computercraft.config.monitor_renderer": "Renderizador del monitor",
"gui.computercraft.config.monitor_renderer.tooltip": "El renderizador a usar en monitores. Generalmente esto debe estar en \"BEST\"\n(mejor) - si los monitores tienen problemas de rendimiento, podrías querer\nexperimentar con renderizadores alternativos.\nValores permitidos: BEST, TBO, VBO",
"gui.computercraft.config.peripheral": "Periféricos",
"gui.computercraft.config.peripheral.command_block_enabled": "Habilitar bloque de comandos periférico",
"gui.computercraft.config.peripheral.command_block_enabled.tooltip": "Habilitar soporte del periférico Bloque de Comandos",
"gui.computercraft.config.peripheral.max_notes_per_tick": "Notas máximas que un ordenador puede tocar a la vez",
"gui.computercraft.config.peripheral.max_notes_per_tick.tooltip": "Cantidad máxima de notas que un parlante puede reproducir a la vez.\nRango: > 1",
"gui.computercraft.config.peripheral.modem_high_altitude_range": "Rango del módem (en altitud)",
"gui.computercraft.config.peripheral.modem_high_altitude_range.tooltip": "El rango de los Modems inalámbricos a máxima altitud en clima despejado, en metros.\nRango: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm": "Rango del módem (en altitud con mal tiempo)",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm.tooltip": "El rango de los Modems inalámbricos a máxima altitud durante las tormentas, en metros.\nRango: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range": "Rango del módem (Por defecto)",
"gui.computercraft.config.peripheral.modem_range.tooltip": "El rango de los Modems inalámbricos a baja altitud en clima despejado, en metros.\nRango: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range_during_storm": "Rango del módem (mal tiempo)",
"gui.computercraft.config.peripheral.modem_range_during_storm.tooltip": "El rango de los Modems inalámbricos a baja altitud durante las tormentas, en metros.\nRango: 0 ~ 100000",
"gui.computercraft.config.peripheral.monitor_bandwidth": "Ancho de banda del monitor",
"gui.computercraft.config.peripheral.monitor_bandwidth.tooltip": "El límite de datos que un monitor puede enviar *por tick* Nota:\n - El ancho de banda es medido antes de la compresión, así que los datos enviados\n al cliente son más pequeños.\n - Esto ignora el número de jugadores a los que se les envían los paquetes.\n Actualizar un monitor para un jugador consume lo mismo que actualizarlo para\n 20.\n - Un monitor del tamaño más grande envía ~25kb de datos. Así que el límite\n predeterminado (1MB) permite actualizar ~40 monitores en un solo tick.\nEstablezca en 0 para desactivar.\nRango: > 0",
"gui.computercraft.config.peripheral.tooltip": "Varias opciones relacionadas con los periféricos.",
"gui.computercraft.config.term_sizes": "Tamaños de la terminal",
"gui.computercraft.config.term_sizes.computer": "Computadora",
"gui.computercraft.config.term_sizes.computer.height": "Altura de la terminal",
"gui.computercraft.config.term_sizes.computer.height.tooltip": "Rango: 1 ~ 255",
"gui.computercraft.config.term_sizes.computer.tooltip": "Tamaño de la terminal de las computadoras.",
"gui.computercraft.config.term_sizes.computer.width": "Ancho de la terminal",
"gui.computercraft.config.term_sizes.computer.width.tooltip": "Rango: 1 ~ 255",
"gui.computercraft.config.term_sizes.monitor": "Monitor",
"gui.computercraft.config.term_sizes.monitor.height": "Altura máxima del monitor",
"gui.computercraft.config.term_sizes.monitor.height.tooltip": "Rango: 1 ~ 32",
"gui.computercraft.config.term_sizes.monitor.tooltip": "Tamaño máximo de los monitores (en bloques).",
"gui.computercraft.config.term_sizes.monitor.width": "Anchura máxima del monitor",
"gui.computercraft.config.term_sizes.monitor.width.tooltip": "Rango: 1 ~ 32",
"gui.computercraft.config.term_sizes.pocket_computer": "Computadora de bolsillo",
"gui.computercraft.config.term_sizes.pocket_computer.height": "Altura de la terminal",
"gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "Rango: 1 ~ 255",
"gui.computercraft.config.term_sizes.pocket_computer.tooltip": "Tamaño de la terminal de las computadoras de bolsillo.",
"gui.computercraft.config.term_sizes.pocket_computer.width": "Ancho de la terminal",
"gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "Rango: 1 ~ 255",
"gui.computercraft.config.term_sizes.tooltip": "Configura el tamaño de las terminales de varias computadoras.\nTerminales más grandes requieren mayor ancho de banda, así que úselo con cuidado.",
"gui.computercraft.config.turtle": "Tortugas",
"gui.computercraft.config.turtle.advanced_fuel_limit": "Límite de combustible de las tortugas avanzadas",
"gui.computercraft.config.turtle.advanced_fuel_limit.tooltip": "El límite de combustible para Tortugas Avanzadas.\nRango: > 0",
"gui.computercraft.config.turtle.can_push": "Las tortugas pueden empujar entidades",
"gui.computercraft.config.turtle.can_push.tooltip": "Si es verdadero, las tortugas empujarán a las entidades de su camino en\nlugar de detenerse si hay espacio para hacerlo.",
"gui.computercraft.config.turtle.need_fuel": "Habilitar combustible",
"gui.computercraft.config.turtle.need_fuel.tooltip": "Establece si las tortugas requieren combustible para moverse.",
"gui.computercraft.config.turtle.normal_fuel_limit": "Límite de combustible de las tortugas",
"gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "Límite de combustible para las Tortugas.\nRango: > 0",
"gui.computercraft.config.turtle.tooltip": "Varias opciones relacionadas con las tortugas.",
"gui.computercraft.config.upload_max_size": "Límite de tamaño del archivo subido (bytes)",
"gui.computercraft.config.upload_max_size.tooltip": "El límite de subida por archivo, en bytes. Debe estar en un rango de entre 1 KiB y 16 MiB.\nTen en cuenta que las subidas son procesadas en un un solo tick - archivos grandes o\nun rendimiento de internet malo puede paralizar el hilo de red. Y tamién ten en cuenta el espacio en disco!\nRango: 1024 ~ 16777216",
"gui.computercraft.config.upload_nag_delay": "Retraso de subida nag",
"gui.computercraft.config.upload_nag_delay.tooltip": "El retraso en segundos después de los cuales notificaremos las importaciones no manejadas. Establecer en 0 para deshabilitar.\nRango: 0 ~ 60",
"gui.computercraft.pocket_computer_overlay": "Computadora de bolsillo abierta. Pulsa ESC para cerrar.",
"gui.computercraft.terminal": "Terminal de la Computadora",
"gui.computercraft.tooltip.computer_id": "ID de la Computadora: %s",
"gui.computercraft.tooltip.copy": "Copiar al portapapeles",
"gui.computercraft.tooltip.disk_id": "ID del disquete: %s",
"gui.computercraft.tooltip.terminate": "Detener el código en ejecución",
"gui.computercraft.tooltip.terminate.key": "Mantenga Ctrl+T",
"gui.computercraft.tooltip.turn_off": "Apagar esta computadora",
"gui.computercraft.tooltip.turn_off.key": "Mantenga Ctrl+S",
"gui.computercraft.tooltip.turn_on": "Encender esta computadora",
"gui.computercraft.upload.failed": "Subida fallida",
"gui.computercraft.upload.failed.computer_off": "Debes encender la computadora antes de subir archivos.",
"gui.computercraft.upload.failed.corrupted": "Archivos corruptos al subir. Por favor, inténtelo de nuevo.",
"gui.computercraft.upload.failed.generic": "Error al subir archivos (%s)",
"gui.computercraft.upload.failed.name_too_long": "Los nombres de los archivos son demasiado largos para ser cargados.",
"gui.computercraft.upload.failed.too_many_files": "No se pueden subir tantos archivos.",
"gui.computercraft.upload.failed.too_much": "Tus archivos son demasiado grandes para ser subidos.",
"gui.computercraft.upload.no_response": "Transfiriendo archivos",
"gui.computercraft.upload.no_response.msg": "Tu computadora no ha usado tus archivos transferidos. Es posible que debas ejecutar el programa %s e intentar de nuevo.",
"item.computercraft.disk": "Disquete",
"item.computercraft.pocket_computer_advanced": "Ordenador de bolsillo avanzado",
"item.computercraft.pocket_computer_advanced.upgraded": "Ordenador de bolsillo %s avanzado",
@@ -56,6 +200,25 @@
"item.computercraft.printed_page": "Página impresa",
"item.computercraft.printed_pages": "Páginas impresas",
"item.computercraft.treasure_disk": "Disquete (Tesoro)",
"itemGroup.computercraft": "ComputerCraft",
"tag.item.computercraft.computer": "Computadoras",
"tag.item.computercraft.monitor": "Monitores",
"tag.item.computercraft.turtle": "Tortugas",
"tag.item.computercraft.wired_modem": "Módems cableados",
"tracking_field.computercraft.avg": "%s (promedio)",
"tracking_field.computercraft.computer_tasks.name": "Tareas",
"tracking_field.computercraft.count": "%s (cuenta)",
"tracking_field.computercraft.fs.name": "Operaciones del sistema de archivos",
"tracking_field.computercraft.http_download.name": "Descarga HTTP",
"tracking_field.computercraft.http_requests.name": "Peticiones HTTP",
"tracking_field.computercraft.http_upload.name": "Subida HTTP",
"tracking_field.computercraft.java_allocation.name": "Asignaciones de Java",
"tracking_field.computercraft.max": "%s (max)",
"tracking_field.computercraft.peripheral.name": "Llamadas del periférico",
"tracking_field.computercraft.server_tasks.name": "Tareas del servidor",
"tracking_field.computercraft.turtle_ops.name": "Operaciones de la Tortuga",
"tracking_field.computercraft.websocket_incoming.name": "Websocket entrante",
"tracking_field.computercraft.websocket_outgoing.name": "Websocket saliente",
"upgrade.computercraft.speaker.adjective": "ruidosa",
"upgrade.computercraft.wireless_modem_advanced.adjective": "ender",
"upgrade.computercraft.wireless_modem_normal.adjective": "sin cables",

View File

@@ -32,8 +32,6 @@
"commands.computercraft.generic.additional_rows": "%d lignes supplémentaires…",
"commands.computercraft.generic.exception": "Exception non gérée (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<pas de position>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "O",
"commands.computercraft.help.desc": "Affiche ce message d'aide",
"commands.computercraft.help.no_children": "%s n'a pas de sous-commandes",

View File

@@ -1,15 +1,19 @@
{
"argument.computercraft.argument_expected": "È previsto un argomento",
"argument.computercraft.computer.distance": "Distanza dall'entità",
"argument.computercraft.computer.family": "Famiglia computer",
"argument.computercraft.computer.id": "ID computer",
"argument.computercraft.computer.instance": "ID istanza unica",
"argument.computercraft.computer.label": "Etichetta computer",
"argument.computercraft.computer.many_matching": "Molteplici computer che combaciano con '%s' (istanze %s)",
"argument.computercraft.computer.no_matching": "Nessun computer che combacia con '%s'",
"argument.computercraft.tracking_field.no_field": "Campo sconosciuto '%s'",
"argument.computercraft.unknown_computer_family": "Famiglia computer '%s' sconosciuta",
"block.computercraft.cable": "Cavo Di Rete",
"block.computercraft.computer_advanced": "Computer Avanzato",
"block.computercraft.computer_command": "Computer Comando",
"block.computercraft.computer_normal": "Computer",
"block.computercraft.disk_drive": "Lettore Di Dischi",
"block.computercraft.monitor_advanced": "Monitor Avanzato",
"block.computercraft.monitor_normal": "Monitor",
"block.computercraft.printer": "Stampante",
"block.computercraft.speaker": "Altoparlante",
"block.computercraft.turtle_advanced": "Tartaruga Avanzata",
@@ -31,9 +35,6 @@
"commands.computercraft.dump.synopsis": "Mostra lo stato dei computer.",
"commands.computercraft.generic.additional_rows": "%d colonne aggiuntive…",
"commands.computercraft.generic.exception": "Eccezione non gestita (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<no posizione>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "S",
"commands.computercraft.help.desc": "Mostra questo messaggio d'aiuto",
"commands.computercraft.help.no_children": "%s non ha sottocomandi",
@@ -49,7 +50,6 @@
"commands.computercraft.tp.desc": "Teletrasporta alla posizione di un computer. Puoi specificare il computer con l'instance id (e.g. 123) o con l'id (e.g. #123).",
"commands.computercraft.tp.synopsis": "Teletrasporta al computer specificato.",
"commands.computercraft.track.desc": "Monitora per quanto tempo i computer vengono eseguiti e quanti eventi ricevono. Questo comando fornisce le informazioni in modo simile a /forge track e può essere utile per diagnosticare il lag.",
"commands.computercraft.track.dump.computer": "Computer",
"commands.computercraft.track.dump.desc": "Cancella gli ultimi risultati del monitoraggio dei computer.",
"commands.computercraft.track.dump.no_timings": "No ci sono tempi disponibili",
"commands.computercraft.track.dump.synopsis": "Cancella gli ultimi risultati monitorati",
@@ -74,6 +74,8 @@
"gui.computercraft.config.computer_space_limit.tooltip": "Limite di spazio di archiviazione per i computer e le tartarughe, in byte.",
"gui.computercraft.config.default_computer_settings": "Impostazioni Computer predefinite",
"gui.computercraft.config.default_computer_settings.tooltip": "Una lista di impostazioni predefinite per i nuovi computer, separate da virgola.\nEsempio: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\ndisattiverà tutti gli autocompletamenti.",
"gui.computercraft.config.disabled_generic_methods": "Metodi generici disattivati",
"gui.computercraft.config.disabled_generic_methods.tooltip": "Una lista di metodi generici o sorgenti di metodi da disattivare. I metodi generici sono\nmetodi aggiunti a blocchi/entità blocchi quando non c'è un provider della periferica esplicito.\nQuesto include metodi dell'inventario (ad es. inventory.getItemDetail, inventory.pushItems) e,\nse su Forge, i metodi fluid_storage e energy_storage.\nI metodi in questa lista possono essere sia un gruppo intero di metodi (computer:inventory)\no un singolo metodo (computer:inventory#pushItems).\n",
"gui.computercraft.config.execution": "Esecuzione",
"gui.computercraft.config.execution.computer_threads": "Threads computer",
"gui.computercraft.config.execution.computer_threads.tooltip": "Imposta la quantità di thread che possono eseguire i computer. Un numero più alto significa\nche più computer possono essere eseguiti alla volta, ma può indurre a lag. Alcune mod potrebbero\nnon funzionare con numeri di thread maggiore a 1. Usare con cautela.\nRange: > 1",
@@ -84,7 +86,6 @@
"gui.computercraft.config.execution.tooltip": "Controlla comportamento esecuzione dei computer. Questo è largamente utilizzato\nper ritoccare la performance dei server, e generale non dovrebbe essere toccato.",
"gui.computercraft.config.floppy_space_limit": "Limite spazio Disco Floppy (bytes)",
"gui.computercraft.config.floppy_space_limit.tooltip": "Limite di spazio di archiviazione per i dischi floppy, in byte.",
"gui.computercraft.config.http": "HTTP",
"gui.computercraft.config.http.bandwidth": "Banda larga",
"gui.computercraft.config.http.bandwidth.global_download": "Limite download globale",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "Numero di byte che possono essere scaricati in un secondo. Questo è condiviso tra tutti i computer. (bytes/s).\nRange: > 1",
@@ -97,7 +98,6 @@
"gui.computercraft.config.http.max_requests.tooltip": "Il numero di richieste http che un computer può fare alla volta. Ulteriori richieste\nverranno messe in coda, ed inviate quando le richieste correnti sono terminate.\nImposta a 0 per illimitato.\nRange: > 0",
"gui.computercraft.config.http.max_websockets": "Connessioni websocket massime",
"gui.computercraft.config.http.max_websockets.tooltip": "Il numero di websocket che un computer può avere aperte allo stesso momento.\nImposta a 0 per illimitato.\nRange: > 1",
"gui.computercraft.config.http.proxy": "Proxy",
"gui.computercraft.config.http.proxy.host": "Nome host",
"gui.computercraft.config.http.proxy.host.tooltip": "Il nome dell'host o l'indirizzo IP del server proxy.",
"gui.computercraft.config.http.proxy.port": "Porta",
@@ -135,24 +135,17 @@
"gui.computercraft.config.peripheral.monitor_bandwidth.tooltip": "Il limite di quanti dati dei monitor possono essere inviati *al tick*. Nota:\n - La banda larga è misurata prima della compressione, così che il dato inviato al client è\n più piccolo.\n - Questo ignora il numero di giocatori a cui viene inviato il pacchetto. Aggiornare un monitor\n per un giocatore consuma lo stesso limite di banda larga dell'invio a 20 giocatori.\n - Un monitor alla massima grandezza invia ~25kb di dati. Quindi il valore predefinito (1MB) concede\n ~40 monitor di essere aggiornati in un singolo tick.\nImposta a 0 per disattivare.\nRange: > 0",
"gui.computercraft.config.peripheral.tooltip": "Opzioni varie riguardo le periferiche.",
"gui.computercraft.config.term_sizes": "Dimensioni terminale",
"gui.computercraft.config.term_sizes.computer": "Computer",
"gui.computercraft.config.term_sizes.computer.height": "Altezza terminale",
"gui.computercraft.config.term_sizes.computer.height.tooltip": "Range: 1 ~ 255",
"gui.computercraft.config.term_sizes.computer.tooltip": "Dimensioni del terminale dei computer.",
"gui.computercraft.config.term_sizes.computer.width": "Larghezza terminale",
"gui.computercraft.config.term_sizes.computer.width.tooltip": "Intervallo: 1 ~ 255",
"gui.computercraft.config.term_sizes.monitor": "Monitor",
"gui.computercraft.config.term_sizes.monitor.height": "Massima altezza del monitor",
"gui.computercraft.config.term_sizes.monitor.height.tooltip": "Range: 1 ~ 32",
"gui.computercraft.config.term_sizes.monitor.tooltip": "Massima grandezza dei monitor (in blocchi).",
"gui.computercraft.config.term_sizes.monitor.width": "Larghezza massima del monitor",
"gui.computercraft.config.term_sizes.monitor.width.tooltip": "Range: 1 ~ 32",
"gui.computercraft.config.term_sizes.pocket_computer": "Computer Tascabile",
"gui.computercraft.config.term_sizes.pocket_computer.height": "Altezza terminale",
"gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "Range: 1 ~ 255",
"gui.computercraft.config.term_sizes.pocket_computer.tooltip": "Dimensioni del terminale dei computer tascabili.",
"gui.computercraft.config.term_sizes.pocket_computer.width": "Larghezza terminale",
"gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "Range: 1 ~ 255",
"gui.computercraft.config.term_sizes.tooltip": "Configura le dimensioni dei terminali di vari computer.\nTerminali più grandi richiedono più banda larga, usa con cautela.",
"gui.computercraft.config.turtle": "Tartarughe",
"gui.computercraft.config.turtle.advanced_fuel_limit": "Limite carburante tartarughe avanzate",
@@ -196,7 +189,10 @@
"item.computercraft.printed_page": "Pagina Stampata",
"item.computercraft.printed_pages": "Pagine Stampate",
"item.computercraft.treasure_disk": "Disco Floppy",
"itemGroup.computercraft": "ComputerCraft",
"tag.item.computercraft.computer": "Computer",
"tag.item.computercraft.monitor": "Monitor",
"tag.item.computercraft.turtle": "Tartarughe",
"tag.item.computercraft.wired_modem": "Modem cablati",
"tracking_field.computercraft.avg": "%s (media)",
"tracking_field.computercraft.computer_tasks.name": "Attività",
"tracking_field.computercraft.count": "%s (conta)",
@@ -204,6 +200,7 @@
"tracking_field.computercraft.http_download.name": "Download HTTP",
"tracking_field.computercraft.http_requests.name": "Richieste HTTP",
"tracking_field.computercraft.http_upload.name": "Upload HTTP",
"tracking_field.computercraft.java_allocation.name": "Allocazioni Java",
"tracking_field.computercraft.max": "%s (massimo)",
"tracking_field.computercraft.peripheral.name": "Chiamate alle periferiche",
"tracking_field.computercraft.server_tasks.name": "Attività server",
@@ -211,25 +208,10 @@
"tracking_field.computercraft.websocket_incoming.name": "Websocket in arrivo",
"tracking_field.computercraft.websocket_outgoing.name": "Websocket in uscita",
"upgrade.computercraft.speaker.adjective": "Rumoroso",
"upgrade.computercraft.wireless_modem_advanced.adjective": "Ender",
"upgrade.computercraft.wireless_modem_normal.adjective": "Wireless",
"upgrade.minecraft.crafting_table.adjective": "Artigiana",
"upgrade.minecraft.diamond_axe.adjective": "Taglialegna",
"upgrade.minecraft.diamond_hoe.adjective": "Contadina",
"upgrade.minecraft.diamond_pickaxe.adjective": "Minatrice",
"upgrade.minecraft.diamond_shovel.adjective": "Scavatrice",
"upgrade.minecraft.diamond_sword.adjective": "Da Combattimento",
"tag.item.computercraft.computer": "Computer",
"tag.item.computercraft.wired_modem": "Modem cablati",
"argument.computercraft.computer.distance": "Distanza dall'entità",
"argument.computercraft.computer.family": "Famiglia computer",
"argument.computercraft.computer.id": "ID computer",
"argument.computercraft.computer.instance": "ID istanza unica",
"argument.computercraft.computer.label": "Etichetta computer",
"argument.computercraft.unknown_computer_family": "Famiglia computer '%s' sconosciuta",
"gui.computercraft.config.disabled_generic_methods": "Metodi generici disattivati",
"gui.computercraft.config.disabled_generic_methods.tooltip": "Una lista di metodi generici o sorgenti di metodi da disattivare. I metodi generici sono\nmetodi aggiunti a blocchi/entità blocchi quando non c'è un provider della periferica esplicito.\nQuesto include metodi dell'inventario (ad es. inventory.getItemDetail, inventory.pushItems) e,\nse su Forge, i metodi fluid_storage e energy_storage.\nI metodi in questa lista possono essere sia un gruppo intero di metodi (computer:inventory)\no un singolo metodo (computer:inventory#pushItems).\n",
"tag.item.computercraft.monitor": "Monitor",
"tag.item.computercraft.turtle": "Tartarughe",
"tracking_field.computercraft.java_allocation.name": "Allocazioni Java"
"upgrade.minecraft.diamond_sword.adjective": "Da Combattimento"
}

View File

@@ -1,8 +1,14 @@
{
"argument.computercraft.argument_expected": "引数が期待される",
"argument.computercraft.computer.distance": "エンティティまでの距離",
"argument.computercraft.computer.family": "コンピューターファミリー",
"argument.computercraft.computer.id": "コンピューターID",
"argument.computercraft.computer.instance": "固有インスタンスID",
"argument.computercraft.computer.label": "コンピューターラベル",
"argument.computercraft.computer.many_matching": "'%s'に一致する複数のコンピューター (インスタンス %s)",
"argument.computercraft.computer.no_matching": "'%s'に一致するコンピュータはありません",
"argument.computercraft.computer.no_matching": "'%s'に一致するコンピュータはありません",
"argument.computercraft.tracking_field.no_field": "'%s'は未知のフィールドです",
"argument.computercraft.unknown_computer_family": "'%s'は未知のコンピューターファミリーです",
"block.computercraft.cable": "ネットワークケーブル",
"block.computercraft.computer_advanced": "高度なコンピューター",
"block.computercraft.computer_command": "コマンドコンピューター",
@@ -12,9 +18,9 @@
"block.computercraft.monitor_normal": "モニター",
"block.computercraft.printer": "プリンター",
"block.computercraft.speaker": "スピーカー",
"block.computercraft.turtle_advanced": "高度なタートル",
"block.computercraft.turtle_advanced.upgraded": "高度な%sタートル",
"block.computercraft.turtle_advanced.upgraded_twice": "高度な%s%sタートル",
"block.computercraft.turtle_advanced": "アドバンスドタートル",
"block.computercraft.turtle_advanced.upgraded": "アドバンスド%sタートル",
"block.computercraft.turtle_advanced.upgraded_twice": "アドバンスド%s%sタートル",
"block.computercraft.turtle_normal": "タートル",
"block.computercraft.turtle_normal.upgraded": "%sタートル",
"block.computercraft.turtle_normal.upgraded_twice": "%s%sタートル",
@@ -24,80 +30,195 @@
"block.computercraft.wireless_modem_normal": "無線モデム",
"chat.computercraft.wired_modem.peripheral_connected": "周辺の\"%s\"のネットワークに接続されました",
"chat.computercraft.wired_modem.peripheral_disconnected": "周辺の\"%s\"のネットワークから切断されました",
"commands.computercraft.desc": "/computercraft コマンドは、コンピュータとの制御および対話するためのさまざまなデバッグツールと管理者ツールを提供します。",
"commands.computercraft.dump.action": "このコンピュータの詳細を表示します",
"commands.computercraft.dump.desc": "すべてのコンピューターの状態、または一台のコンピューターの特定の情報を表示する。 コンピュータのインスタンスID (例えば 123), コンピュータID (例えば #123) またはラベル (例えば \\\"@My Computer\\\") を指定することができます。",
"commands.computercraft.dump.open_path": "このコンピュータのファイルを表示します",
"commands.computercraft.dump.synopsis": "コンピュータの状態を表示します。",
"commands.computercraft.desc": "/computercraft コマンドは、コンピュータとの制御および対話するためのさまざまなデバッグツールと管理者ツールを提供します。",
"commands.computercraft.dump.action": "このコンピュータの詳細を表示します",
"commands.computercraft.dump.desc": "すべてのコンピューターの状態、または一台のコンピューターの特定の情報を表示する。 コンピュータのインスタンスID (例えば 123), コンピュータID (例えば #123) またはラベル (例えば \\\"@My Computer\\\") を指定することができます。",
"commands.computercraft.dump.open_path": "このコンピュータのファイルを表示します",
"commands.computercraft.dump.synopsis": "コンピュータの状態を表示します。",
"commands.computercraft.generic.additional_rows": "%d行を追加…",
"commands.computercraft.generic.exception": "未処理の例外 (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<no pos>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "Y",
"commands.computercraft.help.desc": "このヘルプメッセージを表示します",
"commands.computercraft.help.no_children": "%s にサブコマンドはありません",
"commands.computercraft.help.no_command": "%s というコマンドはありません",
"commands.computercraft.help.synopsis": "特定のコマンドのヘルプを提供します",
"commands.computercraft.queue.desc": "追加の引数を通過する computer_command インベントをコマンドコンピューターに送信します。これは主にマップメーカーのために設計されており、よりコンピュータフレンドリーバージョンの /trigger として機能します。 どのプレイヤーでもコマンドを実行できます。これは、テキストコンポーネントのクリックイベントを介して行われる可能性があります。",
"commands.computercraft.queue.desc": "追加の引数を通過する computer_command インベントをコマンドコンピューターに送信します。これは主にマップメーカーのために設計されており、よりコンピュータフレンドリーバージョンの /trigger として機能します。 どのプレイヤーでもコマンドを実行できます。これは、テキストコンポーネントのクリックイベントを介して行われる可能性があります。",
"commands.computercraft.queue.synopsis": "computer_command インベントをコマンドコンピューターに送信します",
"commands.computercraft.shutdown.desc": "指定されたコンピュータ、指定されていない場合はすべてのコンピュータをシャットダウンします。 コンピュータのインスタンスID (例えば 123), コンピュータID (例えば #123) またはラベル (例えば \\\"@My Computer\\\") を指定することができます。",
"commands.computercraft.shutdown.desc": "指定されたコンピュータ、指定されていない場合はすべてのコンピュータをシャットダウンします。 コンピュータのインスタンスID (例えば 123), コンピュータID (例えば #123) またはラベル (例えば \\\"@My Computer\\\") を指定することができます。",
"commands.computercraft.shutdown.done": "%s/%s コンピューターをシャットダウンしました",
"commands.computercraft.shutdown.synopsis": "コンピュータをリモートでシャットダウンする。",
"commands.computercraft.synopsis": "コンピュータを制御するためのさまざまなコマンド。",
"commands.computercraft.shutdown.synopsis": "コンピュータをリモートでシャットダウンする。",
"commands.computercraft.synopsis": "コンピュータを制御するためのさまざまなコマンド。",
"commands.computercraft.tp.action": "このコンピューターへテレポートします",
"commands.computercraft.tp.desc": "コンピュータの場所にテレポート.コンピュータのインスタンスID例えば 123またはコンピュータID例えば #123を指定することができます。",
"commands.computercraft.tp.synopsis": "特定のコンピュータにテレポート。",
"commands.computercraft.track.desc": "コンピュータの実行時間を追跡するだけでなく、イベントを確認することができます。 これは /forge と同様の方法で情報を提示し、遅れを診断するのに役立ちます。",
"commands.computercraft.tp.desc": "コンピュータの場所にテレポート.コンピュータのインスタンスID例えば 123またはコンピュータID例えば #123を指定することができます。",
"commands.computercraft.tp.synopsis": "特定のコンピュータにテレポート。",
"commands.computercraft.track.desc": "コンピュータの実行時間を追跡するだけでなく、イベントを確認することができます。 これは /forge と同様の方法で情報を提示し、遅れを診断するのに役立ちます。",
"commands.computercraft.track.dump.computer": "コンピューター",
"commands.computercraft.track.dump.desc": "コンピュータの最新の追跡結果をダンプしてください。",
"commands.computercraft.track.dump.desc": "コンピュータの最新の追跡結果をダンプしてください。",
"commands.computercraft.track.dump.no_timings": "利用可能なタイミングはありません",
"commands.computercraft.track.dump.synopsis": "最新の追跡結果をダンプしてください",
"commands.computercraft.track.start.desc": "すべてのコンピュータの実行時間とイベント数の追跡を開始します。 これにより、以前の実行結果が破棄されます。",
"commands.computercraft.track.start.desc": "すべてのコンピュータの実行時間とイベント数の追跡を開始します。 これにより、以前の実行結果が破棄されます。",
"commands.computercraft.track.start.stop": "トラッキングを停止して結果を表示するには %s を実行してください",
"commands.computercraft.track.start.synopsis": "すべてのコンピュータの追跡を開始します",
"commands.computercraft.track.start.synopsis": "すべてのコンピュータの追跡を開始します",
"commands.computercraft.track.stop.action": "追跡を中止するためにクリックしてください",
"commands.computercraft.track.stop.desc": "すべてのコンピュータのイベントと実行時間の追跡を停止します",
"commands.computercraft.track.stop.not_enabled": "現在コンピュータを追跡していません",
"commands.computercraft.track.stop.synopsis": "すべてのコンピュータの追跡を停止します",
"commands.computercraft.track.synopsis": "コンピュータの実行時間を追跡します。",
"commands.computercraft.turn_on.desc": "指定されているコンピュータを起動します。 コンピュータのインスタンスID (例えば 123), コンピュータID (例えば #123) またはラベル (例えば \\\"@My Computer\\\") を指定することができます。",
"commands.computercraft.track.stop.desc": "すべてのコンピュータのイベントと実行時間の追跡を停止します",
"commands.computercraft.track.stop.not_enabled": "現在コンピュータを追跡していません",
"commands.computercraft.track.stop.synopsis": "すべてのコンピュータの追跡を停止します",
"commands.computercraft.track.synopsis": "コンピュータの実行時間を追跡します。",
"commands.computercraft.turn_on.desc": "指定されているコンピュータを起動します。 コンピュータのインスタンスID (例えば 123), コンピュータID (例えば #123) またはラベル (例えば \\\"@My Computer\\\") を指定することができます。",
"commands.computercraft.turn_on.done": "%s/%s コンピューターを起動しました",
"commands.computercraft.turn_on.synopsis": "コンピューターをリモートで起動します。",
"commands.computercraft.view.action": "このコンピュータを見ます",
"commands.computercraft.view.desc": "コンピュータのターミナルを開き、コンピュータのリモートコントロールを可能にします。 これはタートルのインベントリへのアクセスを提供しません。 コンピュータのインスタンスID例えば 123またはコンピュータID例えば #123を指定することができます。",
"commands.computercraft.view.action": "このコンピュータを見ます",
"commands.computercraft.view.desc": "コンピュータのターミナルを開き、コンピュータのリモートコントロールを可能にします。 これはタートルのインベントリへのアクセスを提供しません。 コンピュータのインスタンスID例えば 123またはコンピュータID例えば #123を指定することができます。",
"commands.computercraft.view.not_player": "非プレイヤー用のターミナルを開くことができません",
"commands.computercraft.view.synopsis": "コンピュータのターミナルを表示します。",
"gui.computercraft.pocket_computer_overlay": "ポケットコンピュータを開いています。 ESCを押して閉じます。",
"gui.computercraft.tooltip.computer_id": "コンピュータID: %s",
"commands.computercraft.view.synopsis": "コンピュータのターミナルを表示します。",
"gui.computercraft.config.command_require_creative": "コマンドコンピューターはクリエイティブモードが必要です。",
"gui.computercraft.config.command_require_creative.tooltip": "コマンドコンピューターと対話するためにはプレイヤーがクリエイティブモードかつOP権限保有者でなければなりません。\nこれはバニラのコマンドブロックのデフォルト挙動です。",
"gui.computercraft.config.computer_space_limit": "コンピューターの限容制限(バイト)",
"gui.computercraft.config.computer_space_limit.tooltip": "コンピューターとタートルのディスク容量制限、バイト単位。",
"gui.computercraft.config.default_computer_settings": "デフォルトのコンピューター設定",
"gui.computercraft.config.default_computer_settings.tooltip": "新しいコンピューターに設定するデフォルトのシステム設定のコンマ区切りのリスト。\n例: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\nは全ての自動補完を無効にします。",
"gui.computercraft.config.disabled_generic_methods": "無効化するジェネリックメソッド",
"gui.computercraft.config.disabled_generic_methods.tooltip": "無効にするジェネリックメソッドまたはメソッドソースのリスト。\nジェネリックメソッドは、明示的な周辺プロバイダがない場合にブロック/ブロックエンティティに追加されるメソッドです。\nこれには、インベントリメソッド (inventory.getItemDetail や inventory.pushItems) や、(Forgeであれば)fluid_storage や energy_storage メソッドが含まれます。\nこのリストに含まれるメソッドは、メソッド群全体 (computercraft:inventory) か、単一のメソッド (computercraft:inventory#pushItems) のどちらかになります。",
"gui.computercraft.config.execution": "実行",
"gui.computercraft.config.execution.computer_threads": "コンピューターのスレッド",
"gui.computercraft.config.execution.computer_threads.tooltip": "コンピューターが実行できるスレッド数を設定する。\n数値が高いほどより多くのコンピューターが一度に実行できますが、ラグを誘発する可能性があります。\nスレッド数が1より大きいと動作しないMODもあるので注意してください\n範囲: > 1",
"gui.computercraft.config.execution.max_main_computer_time": "サーバーティックのコンピューター時間上限",
"gui.computercraft.config.execution.max_main_computer_time.tooltip": "コンピューターが1ティックで実行できる理想的な最大時間、ミリ秒単位。\nどれぐらい時間がかかるか不明であるため、上限を超える可能性があることに注意。\nこれは平均時間の上限を目的とする。\n範囲: > 1",
"gui.computercraft.config.execution.max_main_global_time": "サーバーティックのグローバル回数上限",
"gui.computercraft.config.execution.max_main_global_time.tooltip": "1ティックでタスクを実行できる最大時間、ミリ秒単位。\nどれぐらい時間がかかるか不明であるため、上限を超える可能性があることに注意。\nこれは平均回数の上限を時間とする。",
"gui.computercraft.config.execution.tooltip": "コンピュータの実行挙動を制御する。\nこれは主にサーバーを微調整するためのもので、一般的には触る必要はない。",
"gui.computercraft.config.floppy_space_limit": "フロッピーディスクの容量制限(バイト)",
"gui.computercraft.config.floppy_space_limit.tooltip": "フロッピーディスクのディスク容量制限(バイト単位)。",
"gui.computercraft.config.http": "HTTP",
"gui.computercraft.config.http.bandwidth": "帯域幅",
"gui.computercraft.config.http.bandwidth.global_download": "グローバルダウンロード制限",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "1秒間にダウンロードできるバイト数。これはすべてのコンピュータで共有されます。(byte/s).\n範囲: > 1",
"gui.computercraft.config.http.bandwidth.global_upload": "グローバルアップロード制限",
"gui.computercraft.config.http.bandwidth.global_upload.tooltip": "1秒間にアップロードできるバイト数。これはすべてのコンピュータで共有されます。(byte/s).\n範囲: > 1",
"gui.computercraft.config.http.bandwidth.tooltip": "コンピュータが使用する帯域幅を制限する。",
"gui.computercraft.config.http.enabled": "HTTP APIを有効にする",
"gui.computercraft.config.http.enabled.tooltip": "コンピュータの\"http\" APIを有効にする。これを無効にすると、多くのユーザーが依存している\"pastebin\"と\"wget\"プログラムも無効になる。\nこのオプションはオンのままにしておき、よりきめ細かい制御を行うために\"ルール\"の設定オプションを使用することを推奨する。",
"gui.computercraft.config.http.max_requests": "最大同時リクエスト数",
"gui.computercraft.config.http.max_requests.tooltip": "コンピューターが一度にできるhttpリクエストの数。追加のリクエストはキューに入れられ、実行中のリクエストが終了したときに送信されます。無制限の場合は0に設定します。\n範囲: > 0",
"gui.computercraft.config.http.max_websockets": "最大同時ウェブソケット数",
"gui.computercraft.config.http.max_websockets.tooltip": "コンピュータが一度に開くことのできるウェブソケットの数。\n範囲: > 1",
"gui.computercraft.config.http.proxy": "プロキシ",
"gui.computercraft.config.http.proxy.host": "ホスト名",
"gui.computercraft.config.http.proxy.host.tooltip": "プロキシサーバーのホスト名またはIPアドレス。",
"gui.computercraft.config.http.proxy.port": "ポート",
"gui.computercraft.config.http.proxy.port.tooltip": "プロキシサーバーのポート。\n範囲: 1 ~ 65536",
"gui.computercraft.config.http.proxy.tooltip": "HTTPとウェブソケットリクエストをプロキシサーバ経由でトンネリングする。\"use_proxy\"が\"true\"(デフォルトでは\"off\")に設定されている HTTPルールにのみ影響します。\nプロキシに認証が必要な場合は、\"computercraft-server.toml\"と同じディレクトリに\"myuser:mypassword\"のようにユーザー名とパスワードをコロンで区切って記述した\"computercraft-proxy.pw\"ファイルを作成します。\nSOCKS4プロキシでは、ユーザー名のみが必要です。",
"gui.computercraft.config.http.proxy.type": "プロキシ種類",
"gui.computercraft.config.http.proxy.type.tooltip": "使用するプロキシの種類。\n許可された値: HTTP, HTTPS, SOCKS4, SOCKS5",
"gui.computercraft.config.http.rules": "ルールの許可/拒否",
"gui.computercraft.config.http.rules.tooltip": "特定のドメインやIPに対する\"http\" APIの動作を制御するルールのリスト。それぞれのルールはホスト名とオプションのポートに対して対応し、 リクエストに対していくつかのプロパティを設定します。 ルールは順番に評価され、前のルールが後のルールを上書きします。\n\n有効なプロパティ:\n - \"host\" (必須): このルールが対応するドメインまたはIPアドレス。 これはドメイン名(\"pastebin.com\")、ワイルドカード(\"*.pastebin.com\")、あるいはCIDR表記(\"127.0.0.0/8\")となります。\n - \"port\" (オプション): 80や 443など、特定のポートに対するリクエストにのみマッチする。.\n\n - \"action\" (オプション): このリクエストを許可するか拒否するか。\n - \"max_download\" (オプション): このリクエストでコンピューターがダウンロードできる最大サイズ(バイト単位)。\n - \"max_upload\" (オプション): このリクエストでコンピューターがアップロードできる最大サイズ(バイト)。\n - \"max_websocket_message\" (オプション): コンピューターが1つのウェブソケット・パケットで送受信できる最大サイズバイト。\n - \"use_proxy\" (オプション): HTTP/SOCKSプロキシが設定されている場合は、その使用を有効にする。",
"gui.computercraft.config.http.tooltip": "HTTP APIの制御",
"gui.computercraft.config.http.websocket_enabled": "ウェブソケットを有効にする",
"gui.computercraft.config.http.websocket_enabled.tooltip": "httpウェブソケットの使用を有効にする。これには、\"http_enable\"オプションもtrueである必要があります。.",
"gui.computercraft.config.log_computer_errors": "コンピュータのエラーを記録する",
"gui.computercraft.config.log_computer_errors.tooltip": "周辺機器やその他のLuaオブジェクトが発生させた例外を記録します。これにより、MODの作者が問題をデバッグしやすくなりますが、バグを含んだメソッドを使用した場合、ログスパムが発生する可能性があります。",
"gui.computercraft.config.maximum_open_files": "1台のコンピューターで開けるファイルの最大数",
"gui.computercraft.config.maximum_open_files.tooltip": "コンピューターが同時に開くことができるファイルの数を設定します。無制限の場合は0に設定します。\n範囲: > 0",
"gui.computercraft.config.monitor_distance": "モニター距離",
"gui.computercraft.config.monitor_distance.tooltip": "モニターがレンダリングする最大距離。デフォルトは標準的なタイルエンティティの制限値ですが、より大きなモニタを構築したい場合は拡張することができます。\n範囲: 16 ~ 1024",
"gui.computercraft.config.monitor_renderer": "モニターレンダラー",
"gui.computercraft.config.monitor_renderer.tooltip": "モニターに使用するレンダラー。一般的に、この値は\"best\"に保つたれるべきです。 - モニターにパフォーマンス上の問題がある場合は、別のレンダラーを試してみるとよいでしょう。\n許可された値: BEST, TBO, VBO",
"gui.computercraft.config.peripheral": "周辺機器",
"gui.computercraft.config.peripheral.command_block_enabled": "コマンドブロック周辺機器を有効にする",
"gui.computercraft.config.peripheral.command_block_enabled.tooltip": "コマンドブロック周辺機器サポートを有効にする",
"gui.computercraft.config.peripheral.max_notes_per_tick": "コンピューターが一度に演奏できる最大音符数",
"gui.computercraft.config.peripheral.max_notes_per_tick.tooltip": "スピーカーが一度に演奏できる最大音符数。\n範囲: > 1",
"gui.computercraft.config.peripheral.modem_high_altitude_range": "モデム範囲(高高度)",
"gui.computercraft.config.peripheral.modem_high_altitude_range.tooltip": "晴天時の最大高度におけるワイヤレスモデムの通信距離、メートル単位。\n範囲: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm": "モデム範囲(高高度、悪天候)",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm.tooltip": "悪天候の最大高度におけるワイヤレスモデムの通信距離、メートル単位。\n範囲: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range": "モデム範囲(デフォルト)",
"gui.computercraft.config.peripheral.modem_range.tooltip": "晴天時の低高度におけるワイヤレスモデムの通信距離、メートル単位。\n範囲: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range_during_storm": "モデム範囲(悪天候)",
"gui.computercraft.config.peripheral.modem_range_during_storm.tooltip": "荒天時の低高度におけるワイヤレスモデムの通信距離、メートル単位。\n範囲: 0 ~ 100000",
"gui.computercraft.config.peripheral.monitor_bandwidth": "モニター帯域幅",
"gui.computercraft.config.peripheral.monitor_bandwidth.tooltip": "1ティックあたりのモニターデータ送信量の上限。注:\n - 帯域幅は圧縮前に測定されるため、クライアントに送信されるデータはより小さくなります。\n - これは、パケットを送信するプレーヤーの数を無視する。1人のプレーヤーのモニターを更新することは、20人に送信するのと同じ帯域幅の制限を消費する。\n - フルサイズのモニターは~25kbのデータを送信する。そのため、デフォルト(1MB)では、1回のティックで~40個のモニターを更新することができる。\n 無効にするには 0 を設定する。\n範囲: > 0",
"gui.computercraft.config.peripheral.tooltip": "周辺機器に関する各種オプション。",
"gui.computercraft.config.term_sizes": "ターミナルサイズ",
"gui.computercraft.config.term_sizes.computer": "コンピューター",
"gui.computercraft.config.term_sizes.computer.height": "ターミナルの高さ",
"gui.computercraft.config.term_sizes.computer.height.tooltip": "範囲: 1 ~ 255",
"gui.computercraft.config.term_sizes.computer.tooltip": "コンピュータの端末サイズ。",
"gui.computercraft.config.term_sizes.computer.width": "ターミナルの幅",
"gui.computercraft.config.term_sizes.computer.width.tooltip": "範囲: 1 ~ 255",
"gui.computercraft.config.term_sizes.monitor": "モニター",
"gui.computercraft.config.term_sizes.monitor.height": "モニターの最大高さ",
"gui.computercraft.config.term_sizes.monitor.height.tooltip": "範囲: 1 ~ 32",
"gui.computercraft.config.term_sizes.monitor.tooltip": "モニターの最大サイズ(ブロック単位).",
"gui.computercraft.config.term_sizes.monitor.width": "モニターの最大幅",
"gui.computercraft.config.term_sizes.monitor.width.tooltip": "範囲: 1 ~ 32",
"gui.computercraft.config.term_sizes.pocket_computer": "ポケットコンピューター",
"gui.computercraft.config.term_sizes.pocket_computer.height": "ターミナルの高さ",
"gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "範囲: 1 ~ 255",
"gui.computercraft.config.term_sizes.pocket_computer.tooltip": "ポケットコンピュータのターミナルサイズ。",
"gui.computercraft.config.term_sizes.pocket_computer.width": "ターミナルの幅",
"gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "範囲: 1 ~ 255",
"gui.computercraft.config.term_sizes.tooltip": "各種コンピュータのターミナルサイズを設定します。ターミナルサイズが大きくなるとより多くの帯域幅を必要としますので、注意して使用してください。",
"gui.computercraft.config.turtle": "タートル",
"gui.computercraft.config.turtle.advanced_fuel_limit": "アドバンスドタートルの燃料制限",
"gui.computercraft.config.turtle.advanced_fuel_limit.tooltip": "アドバンスドタートルの燃料制限。\n範囲: > 0",
"gui.computercraft.config.turtle.can_push": "タートルのによるエンティティ押出し",
"gui.computercraft.config.turtle.can_push.tooltip": "trueに設定すると、タートルは空間がある場合停止する代わりにエンティティを押し出す。",
"gui.computercraft.config.turtle.need_fuel": "燃料を有効にする",
"gui.computercraft.config.turtle.need_fuel.tooltip": "タートルズが移動に燃料を必要とするかどうかを設定する。",
"gui.computercraft.config.turtle.normal_fuel_limit": "タートルの燃料制限",
"gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "タートルの燃料制限。\n範囲: > 0",
"gui.computercraft.config.turtle.tooltip": "タートルに関する様々なオプション。",
"gui.computercraft.config.upload_max_size": "ファイルアップロードサイズ制限(バイト)",
"gui.computercraft.config.upload_max_size.tooltip": "ファイルアップロードサイズの上限をバイト数で指定します。1KiBから16MiBの範囲でなければなりません。 \nアップロードは1ティックで処理されることを覚えておいてください - 大きなファイルやネットワークパフォーマンスの低下はネットワーキングスレッドを停止させる可能性があります。\nディスク容量にも注意してください\n範囲: 1024 ~ 16777216",
"gui.computercraft.config.upload_nag_delay": "アップロード催促遅延",
"gui.computercraft.config.upload_nag_delay.tooltip": "未処理の入力について通知するまでの遅延時間(秒)。無効にするには0を設定する。\n範囲: 0 ~ 60",
"gui.computercraft.pocket_computer_overlay": "ポケットコンピューターを開いています。 ESCを押して閉じます。",
"gui.computercraft.terminal": "コンピューターターミナル",
"gui.computercraft.tooltip.computer_id": "コンピューターID: %s",
"gui.computercraft.tooltip.copy": "クリップボードにコピー",
"gui.computercraft.tooltip.disk_id": "ディスクID: %s",
"gui.computercraft.tooltip.terminate": "現在実行中のコードを停止する",
"gui.computercraft.tooltip.terminate.key": "Ctrl+T 長押し",
"gui.computercraft.tooltip.turn_off": "このコンピュータをオフにする",
"gui.computercraft.tooltip.turn_off": "このコンピュータをオフにする",
"gui.computercraft.tooltip.turn_off.key": "Ctrl+S 長押し",
"gui.computercraft.tooltip.turn_on": "このコンピュータをオンにする",
"gui.computercraft.tooltip.turn_on": "このコンピュータをオンにする",
"gui.computercraft.upload.failed": "アップロードに失敗しました",
"gui.computercraft.upload.failed.computer_off": "ファイルをアップロードする前にコンピュータを起動する必要があります。",
"gui.computercraft.upload.failed.computer_off": "ファイルをアップロードする前にコンピュータを起動する必要があります。",
"gui.computercraft.upload.failed.corrupted": "アップロード時にファイルが破損しました。 もう一度やり直してください。",
"gui.computercraft.upload.failed.generic": "ファイルのアップロードに失敗しました(%s)",
"gui.computercraft.upload.failed.name_too_long": "ファイル名が長すぎてアップロードできません。",
"gui.computercraft.upload.failed.too_many_files": "多くのファイルをアップロードできません。",
"gui.computercraft.upload.failed.too_much": "アップロードするにはファイルが大きスギます。",
"gui.computercraft.upload.no_response": "ファイルの転送",
"gui.computercraft.upload.no_response.msg": "コンピュータが転送されたファイルを使用していません。プログラム %s を実行して再試行する必要があります。",
"item.computercraft.disk": "フロッピーディスク",
"item.computercraft.pocket_computer_advanced": "高度なポケットコンピュータ",
"item.computercraft.pocket_computer_advanced.upgraded": "高度な%sポケットコンピュータ",
"item.computercraft.pocket_computer_normal": "ポケットコンピュータ",
"item.computercraft.pocket_computer_normal.upgraded": "%sポケットコンピュータ",
"item.computercraft.pocket_computer_advanced": "高度なポケットコンピュータ",
"item.computercraft.pocket_computer_advanced.upgraded": "高度な%sポケットコンピュータ",
"item.computercraft.pocket_computer_normal": "ポケットコンピュータ",
"item.computercraft.pocket_computer_normal.upgraded": "%sポケットコンピュータ",
"item.computercraft.printed_book": "印刷された本",
"item.computercraft.printed_page": "印刷された紙",
"item.computercraft.printed_pages": "印刷された紙束",
"item.computercraft.treasure_disk": "フロッピーディスク",
"itemGroup.computercraft": "ComputerCraft",
"tag.item.computercraft.computer": "コンピューター",
"tag.item.computercraft.monitor": "モニター",
"tag.item.computercraft.turtle": "タートル",
"tag.item.computercraft.wired_modem": "有線モデム",
"tracking_field.computercraft.avg": "%s (平均)",
"tracking_field.computercraft.computer_tasks.name": "タスク",
"tracking_field.computercraft.count": "%s (回)",
"tracking_field.computercraft.fs.name": "ファイルシステム演算",
"tracking_field.computercraft.http_download.name": "HTTPダウンロード",
"tracking_field.computercraft.http_requests.name": "HTTPリクエスト",
"tracking_field.computercraft.http_upload.name": "HTTPアップロード",
"tracking_field.computercraft.java_allocation.name": "Java割当",
"tracking_field.computercraft.max": "%s (最大)",
"tracking_field.computercraft.peripheral.name": "実行呼び出し",
"tracking_field.computercraft.server_tasks.name": "サーバータスク",
"tracking_field.computercraft.turtle_ops.name": "タートル操作",
"tracking_field.computercraft.websocket_incoming.name": "Websocket 受信",
"tracking_field.computercraft.websocket_outgoing.name": "Websocket 送信",
"upgrade.computercraft.speaker.adjective": "騒音",

View File

@@ -32,8 +32,6 @@
"commands.computercraft.generic.additional_rows": "%d개의 추가 행…",
"commands.computercraft.generic.exception": "처리되지 않은 예외 (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<no pos>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "Y",
"commands.computercraft.help.desc": "이 도움말 메시지를 표시합니다.",
"commands.computercraft.help.no_children": "%s에는 하위 명령어가 없습니다.",

View File

@@ -10,7 +10,6 @@
"block.computercraft.disk_drive": "Diskstasjon",
"block.computercraft.monitor_advanced": "Avansert Skjerm",
"block.computercraft.monitor_normal": "Skjerm",
"block.computercraft.printer": "Printer",
"block.computercraft.speaker": "Høytaler",
"block.computercraft.turtle_advanced": "Avansert Skilpadde",
"block.computercraft.turtle_advanced.upgraded": "Avansert %s Skilpadde",
@@ -20,7 +19,6 @@
"block.computercraft.turtle_normal.upgraded_twice": "%s %s Skilpadde",
"block.computercraft.wired_modem": "Kablet Modem",
"block.computercraft.wired_modem_full": "Kablet Modem",
"block.computercraft.wireless_modem_advanced": "Ender Modem",
"block.computercraft.wireless_modem_normal": "Trådløst Modem",
"chat.computercraft.wired_modem.peripheral_connected": "Perifer \"%s\" koblet til nettverk",
"chat.computercraft.wired_modem.peripheral_disconnected": "Perifer \"%s\" koblet fra nettverk",
@@ -31,9 +29,6 @@
"commands.computercraft.dump.synopsis": "Viser statusen av datamaskiner.",
"commands.computercraft.generic.additional_rows": "%d flere rader…",
"commands.computercraft.generic.exception": "Uhåndtert unntak (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<ingen posisjon>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "J",
"commands.computercraft.help.desc": "Viser denne hjelpemeldingen",
"commands.computercraft.help.no_children": "%s har ingen underkommandoer",
@@ -69,7 +64,6 @@
"commands.computercraft.view.not_player": "Kan kun åpne terminal for spillere",
"commands.computercraft.view.synopsis": "Vis terminal til en datamaskin.",
"gui.computercraft.config.command_require_creative": "Kommando datamaskiner trenger kreativ",
"gui.computercraft.config.http": "HTTP",
"gui.computercraft.config.http.enabled": "Slå på HTTP APIen",
"gui.computercraft.config.http.rules": "Godta/Avslå regler",
"gui.computercraft.config.monitor_distance": "Skjerm distanse",
@@ -88,7 +82,6 @@
"gui.computercraft.terminal": "Datamaskin terminal",
"gui.computercraft.tooltip.computer_id": "Datamaskin ID: %s",
"gui.computercraft.tooltip.copy": "Kopier til utklippstavle",
"gui.computercraft.tooltip.disk_id": "Disk ID: %s",
"gui.computercraft.tooltip.terminate": "Stopp den kjørende koden",
"gui.computercraft.tooltip.terminate.key": "Hold Ctrl + T",
"gui.computercraft.tooltip.turn_off": "Skru denne datamaskinen av",
@@ -102,7 +95,6 @@
"gui.computercraft.upload.failed.too_many_files": "Kan ikke laste opp så mange filer.",
"gui.computercraft.upload.failed.too_much": "Filene dine er for store for å kunne bli lastet opp.",
"gui.computercraft.upload.no_response": "Overfører Filer",
"item.computercraft.disk": "Floppy Disk",
"item.computercraft.pocket_computer_advanced": "Avansert Lomme Datamaskin",
"item.computercraft.pocket_computer_advanced.upgraded": "Avansert %s Lomme Datamaskin",
"item.computercraft.pocket_computer_normal": "Lomme datamaskin",
@@ -110,8 +102,6 @@
"item.computercraft.printed_book": "Printet Bok",
"item.computercraft.printed_page": "Printet Side",
"item.computercraft.printed_pages": "Printet Sider",
"item.computercraft.treasure_disk": "Floppy Disk",
"itemGroup.computercraft": "ComputerCraft",
"tracking_field.computercraft.computer_tasks.name": "Oppgaver",
"tracking_field.computercraft.count": "%s (antall)",
"tracking_field.computercraft.fs.name": "Filsystem operasjoner",
@@ -123,7 +113,6 @@
"tracking_field.computercraft.websocket_incoming.name": "Innkommende Websocket",
"tracking_field.computercraft.websocket_outgoing.name": "Utgående Websocket",
"upgrade.computercraft.speaker.adjective": "Høylydt",
"upgrade.computercraft.wireless_modem_advanced.adjective": "Ender",
"upgrade.computercraft.wireless_modem_normal.adjective": "Trådløs",
"upgrade.minecraft.crafting_table.adjective": "Håndverks",
"upgrade.minecraft.diamond_axe.adjective": "Hoggende",

View File

@@ -32,8 +32,6 @@
"commands.computercraft.generic.additional_rows": "%d additionele rijen…",
"commands.computercraft.generic.exception": "Niet-afgehandelde exception (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<geen positie>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "J",
"commands.computercraft.help.desc": "Geeft dit hulpbericht weer",
"commands.computercraft.help.no_children": "%s heeft geen sub-commando's",

View File

@@ -19,8 +19,6 @@
"commands.computercraft.dump.desc": "Wyświetla status wszystkich komputerów lub informacje o jednym komputerze. Możesz wybrać numer sesji komputera (np. 123), ID komputera (np. #123) lub jego etykietę (np. \"@Mój Komputer\").",
"commands.computercraft.dump.open_path": "Przeglądaj pliki tego komputera",
"commands.computercraft.dump.synopsis": "Wyświetl stan komputerów.",
"commands.computercraft.generic.no_position": "<brak pozycji>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "T",
"commands.computercraft.help.no_children": "%s nie ma pod-komend",
"commands.computercraft.help.no_command": "Nie odnaleziono komendy '%s'",

View File

@@ -1,4 +1,14 @@
{
"argument.computercraft.argument_expected": "Argumento esperado",
"argument.computercraft.computer.distance": "Distância para a entidade",
"argument.computercraft.computer.family": "Família de Computadores",
"argument.computercraft.computer.id": "ID do Computador",
"argument.computercraft.computer.instance": "ID de Instância Única",
"argument.computercraft.computer.label": "Rótulo do Computador",
"argument.computercraft.computer.many_matching": "Vários computadores correspondendo a '%s' (instâncias %s)",
"argument.computercraft.computer.no_matching": "Sem computadores correspondentes a '%s'",
"argument.computercraft.tracking_field.no_field": "Campo desconhecido '%s'",
"argument.computercraft.unknown_computer_family": "Família de computador desconhecida '%s'",
"block.computercraft.cable": "Cabo de Rede",
"block.computercraft.computer_advanced": "Computador Avançado",
"block.computercraft.computer_command": "Computador de Comandos",
@@ -23,43 +33,166 @@
"commands.computercraft.desc": "O comando /computercraft providencia várias ferramentas de depuração e administração para controle e interação com computadores.",
"commands.computercraft.dump.action": "Ver mais informação sobre este computador",
"commands.computercraft.dump.desc": "Mostra o status de todos os computadores ou uma informação específica sobre um computador. Você pode especificar o id de instância do computador (ex.: 123), id do computador (ex.: #123) ou o rótulo (ex.: \"@MeuComputador\").",
"commands.computercraft.dump.open_path": "Ver arquivos deste computador",
"commands.computercraft.dump.synopsis": "Mostra status de computadores.",
"commands.computercraft.generic.additional_rows": "%d linhas adicionais…",
"commands.computercraft.generic.exception": "Exceção não tratada (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.yes": "S",
"commands.computercraft.help.desc": "Mostra essa mensagem de ajuda",
"commands.computercraft.help.no_children": "%s não tem sub-comandos",
"commands.computercraft.help.no_command": "Comando '%s' não existe",
"commands.computercraft.help.synopsis": "Providencia ajuda para um comando específico",
"commands.computercraft.queue.desc": "Envie um evento computer_command para um computador de comando, passando os argumentos adicionais. Isso é projetado principalmente para criadores de mapas, funcionando como uma versão mais amigável do computador do comando /trigger. Qualquer jogador pode executar o comando, que provavelmente será feito por meio do evento de clique de um componente de texto.",
"commands.computercraft.queue.synopsis": "Envie um evento computer_command para um computador de comando",
"commands.computercraft.shutdown.desc": "Desliga os computadores em escuta ou todos caso não tenha sido especificado. Você pode especificar o id de instância do computador (ex.: 123), id do computador (ex.: #123) ou o rótulo (ex.: \"@MeuComputador\").",
"commands.computercraft.shutdown.done": "Desliga %s/%s computadores",
"commands.computercraft.shutdown.synopsis": "Desliga computadores remotamente.",
"commands.computercraft.synopsis": "Vários comandos para controlar computadores.",
"commands.computercraft.tp.action": "Teletransportar para este computador",
"commands.computercraft.tp.desc": "Teletransporte para a localização de um computador. Você pode especificar o Id da instância do computador (por exemplo, 123) ou o Id do computador (por exemplo, #123).",
"commands.computercraft.tp.synopsis": "Teleprota para um computador específico.",
"commands.computercraft.track.desc": "Rastreie quanto tempo os computadores executam, bem como quantos eventos eles manipulam. Isso apresenta informações de maneira semelhante ao /forge track e pode ser útil para diagnosticar lag.",
"commands.computercraft.track.dump.computer": "Computador",
"commands.computercraft.track.dump.desc": "Despeje os últimos resultados do rastreamento de computadores.",
"commands.computercraft.track.dump.no_timings": "Nenhum tempo disponível",
"commands.computercraft.track.dump.synopsis": "Despeje os últimos resultados de rastreamento",
"commands.computercraft.track.start.desc": "Comece a rastrear os tempos de execução e contagens de eventos de todos os computadores. Isso descartará os resultados de execuções anteriores.",
"commands.computercraft.track.start.stop": "Execute %s para parar o rastreamento e visualizar os resultados",
"commands.computercraft.track.start.synopsis": "Comece a rastrear todos os computadores",
"commands.computercraft.track.stop.action": "Clique para parar o rastreamento",
"commands.computercraft.track.stop.desc": "Parar de rastrear eventos de todos os computadores e tempos de execução",
"commands.computercraft.track.stop.not_enabled": "Não está rastreando computadores",
"commands.computercraft.track.stop.synopsis": "Parar de rastrear todos os computadores",
"commands.computercraft.track.synopsis": "Acompanhe os tempos de execução para computadores.",
"commands.computercraft.turn_on.desc": "Liga os computadores em escuta. Você pode especificar o id de instância do computador (ex.: 123), id do computador (ex.: #123) ou o rótulo (ex.: \"@MeuComputador\").",
"commands.computercraft.turn_on.done": "Ligou %s/%s computadores",
"commands.computercraft.turn_on.synopsis": "Liga computadores remotamente.",
"commands.computercraft.view.action": "Visualizar este computador",
"commands.computercraft.view.desc": "Abra o terminal de um computador, permitindo o controle remoto de um computador. Isso não fornece acesso aos inventários das tartarugas. Você pode especificar o Id da instância do computador (por exemplo, 123) ou o Id do computador (por exemplo, #123).",
"commands.computercraft.view.not_player": "Não é possível abrir terminal para um não-jogador",
"commands.computercraft.view.synopsis": "Ver o terminal de um computador.",
"gui.computercraft.config.command_require_creative": "Computadores de comando requerem criativo",
"gui.computercraft.config.command_require_creative.tooltip": "Exigir que os jogadores estejam no modo criativo e tenham permissões de operador (opped) para interagir com computadores de comando. Este é o comportamento padrão dos blocos de comando no modo vanilla.",
"gui.computercraft.config.computer_space_limit": "Limite de espaço dos Computadores (bytes)",
"gui.computercraft.config.computer_space_limit.tooltip": "O limite de espaço em disco para computadores e tartarugas, em bytes.",
"gui.computercraft.config.default_computer_settings": "Configurações padrão para Computadores",
"gui.computercraft.config.default_computer_settings.tooltip": "Uma lista separada por vírgulas das configurações padrão do sistema a serem definidas em novos computadores. \nExemplo: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" desativará todas as funcionalidades de autocompletar.",
"gui.computercraft.config.disabled_generic_methods": "Métodos genéricos desativados",
"gui.computercraft.config.disabled_generic_methods.tooltip": "Uma lista de métodos genéricos ou fontes de métodos a serem desativados. Métodos genéricos são aqueles adicionados a um bloco ou entidade de bloco quando não há um provedor de periféricos explícito. Isso inclui métodos de inventário (ou seja, inventory.getItemDetail, inventory.pushItems) e, se estiver usando Forge, os métodos fluid_storage e energy_storage. \nOs métodos nesta lista podem ser um grupo inteiro de métodos (computercraft:inventory) ou um único método (computercraft:inventory#pushItems).\n",
"gui.computercraft.config.execution": "Execução",
"gui.computercraft.config.execution.computer_threads": "Threads por computador",
"gui.computercraft.config.execution.computer_threads.tooltip": "Defina o número de threads que os computadores podem utilizar. Um número maior significa que mais computadores podem ser executados ao mesmo tempo, mas pode causar lag. Observe que alguns mods podem não funcionar com uma contagem de threads superior a 1. Use com cautela. \nIntervalo: > 1",
"gui.computercraft.config.execution.max_main_computer_time": "Limite de tempo do computador por tick do servidor",
"gui.computercraft.config.execution.max_main_computer_time.tooltip": "O tempo máximo ideal que um computador pode executar em um tick, em milissegundos. \nObserve que é bastante provável que ultrapassemos esse limite, pois não há como saber exatamente quanto tempo uma operação levará - isso visa ser o limite superior do tempo médio. \nIntervalo: > 1",
"gui.computercraft.config.execution.max_main_global_time": "Limite de tempo global por tick do servidor",
"gui.computercraft.config.execution.max_main_global_time.tooltip": "O tempo máximo que pode ser gasto executando tarefas em um único tick, em milissegundos. \nObserve que é bastante provável que ultrapassemos esse limite, pois não há como saber exatamente quanto tempo uma operação levará - isso visa ser o limite superior do tempo médio. \nIntervalo: > 1",
"gui.computercraft.config.execution.tooltip": "Controla o comportamento de execução dos computadores. Isso é principalmente destinado ao ajuste fino dos servidores e, geralmente, não deve ser alterado.",
"gui.computercraft.config.floppy_space_limit": "Limite de espaço dos Disquetes (bytes)",
"gui.computercraft.config.floppy_space_limit.tooltip": "O limite de espaço em disco para disquete em bytes.",
"gui.computercraft.config.http": "HTTP",
"gui.computercraft.config.http.bandwidth": "Largura de banda",
"gui.computercraft.config.http.bandwidth.global_download": "Limite de download global",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "O número de bytes que podem ser baixados em um segundo. Isso é compartilhado entre todos os computadores. (bytes/s). \nIntervalo: > 1",
"gui.computercraft.config.http.bandwidth.global_upload": "Limite de upload global",
"gui.computercraft.config.http.bandwidth.global_upload.tooltip": "O número de bytes que podem ser enviados em um segundo. Isso é compartilhado entre todos os computadores. (bytes/s). \nIntervalo: > 1",
"gui.computercraft.config.http.bandwidth.tooltip": "Limita a banda usada pelos computadores.",
"gui.computercraft.config.http.enabled": "Habilitar a biblioteca de HTTP",
"gui.computercraft.config.http.enabled.tooltip": "Ative a API \"http\" nos Computadores. Desativar isso também desativa os programas \"pastebin\" e \"wget\", dos quais muitos usuários dependem. É recomendado deixar isso ativado e usar a opção de configuração \"rules\" para impor um controle mais detalhado.",
"gui.computercraft.config.http.max_requests": "Limite de conexões paralelas",
"gui.computercraft.config.http.max_requests.tooltip": "O número de solicitações Http que um computador pode fazer ao mesmo tempo. Solicitações adicionais serão enfileiradas e enviadas quando as solicitações em execução forem concluídas. Defina como 0 para ilimitado.\nIntervalo: > 0",
"gui.computercraft.config.http.max_websockets": "Limite de conexões websocket",
"gui.computercraft.config.http.max_websockets.tooltip": "O número de websockets que um computador pode ter abertos ao mesmo tempo.\nIntervalo: > 1",
"gui.computercraft.config.http.proxy": "Proxy",
"gui.computercraft.config.http.proxy.host": "Nome de host",
"gui.computercraft.config.http.proxy.host.tooltip": "O nome do host ou endereço IP do servidor proxy.",
"gui.computercraft.config.http.proxy.port": "Porta",
"gui.computercraft.config.http.proxy.port.tooltip": "A porta do servidor proxy.\nIntervalo: 1 ~ 65536",
"gui.computercraft.config.http.proxy.tooltip": "Tunéis de solicitações HTTP e websocket através de um servidor proxy. Afeta apenas as regras HTTP com \"use_proxy\" definido como verdadeiro (desligado por padrão). Se a autenticação for necessária para o proxy, crie um arquivo \"computercraft-proxy.pw\" no mesmo diretório que \"computercraft-server.toml\", contendo o nome de usuário e a senha separados por dois pontos, por exemplo, \"meuusuario:minhasenha\". Para proxies SOCKS4, apenas o nome de usuário é necessário.",
"gui.computercraft.config.http.proxy.type": "Tipo de proxy",
"gui.computercraft.config.http.proxy.type.tooltip": "O tipo de proxy para usar.\nValores permitidos: HTTP, HTTPS, SOCKS4, SOCKS5",
"gui.computercraft.config.http.rules": "Regras Permitir/Negar",
"gui.computercraft.config.http.rules.tooltip": "Uma lista de regras que controlam o comportamento da API \"http\" para domínios ou IPs específicos. Cada regra corresponde a um nome de host e uma porta opcional, e então define várias propriedades para a solicitação. As regras são avaliadas em ordem, o que significa que regras anteriores sobrescrevem as posteriores.\n\nPropriedades válidas:\n- \"host\" (obrigatório): O domínio ou endereço IP que esta regra corresponde. Isso pode ser um nome de domínio (\"pastebin.com\"), um curinga (\"*.pastebin.com\") ou notação CIDR (\"127.0.0.0/8\").\n- \"port\" (opcional): Corresponder apenas a solicitações para uma porta específica, como 80 ou 443.\n\n- \"action\" (opcional): Se permitir ou negar esta solicitação.\n- \"max_download\" (opcional): O tamanho máximo (em bytes) que um computador pode baixar nesta solicitação.\n- \"max_upload\" (opcional): O tamanho máximo (em bytes) que um computador pode enviar em uma solicitação.\n- \"max_websocket_message\" (opcional): O tamanho máximo (em bytes) que um computador pode enviar ou receber em um pacote websocket.\n- \"use_proxy\" (opcional): Habilitar o uso do proxy HTTP/SOCKS se estiver configurado.",
"gui.computercraft.config.http.tooltip": "Controla a API HTTP",
"gui.computercraft.config.http.websocket_enabled": "Habilitar websockets",
"gui.computercraft.config.http.websocket_enabled.tooltip": "Habilitar o uso de websockets Http. Isso requer que a opção \"http_enable\" também esteja definida como verdadeira.",
"gui.computercraft.config.log_computer_errors": "Registrar erros de computadores",
"gui.computercraft.config.log_computer_errors.tooltip": "Registrar exceções lançadas por periféricos e outros objetos Lua. Isso facilita a depuração de problemas para os autores de mods, mas pode resultar em excesso de registros caso as pessoas utilizem métodos com falhas.",
"gui.computercraft.config.maximum_open_files": "Número máximo de arquivos em um computador",
"gui.computercraft.config.maximum_open_files.tooltip": "Defina quantos arquivos um computador pode ter aberto ao mesmo tempo. Defina como 0 para ilimitado.\nIntervalo: > 0",
"gui.computercraft.config.monitor_distance": "Distância do monitor",
"gui.computercraft.config.monitor_distance.tooltip": "A distância máxima que os monitores renderizarão. Isso padrão é o limite padrão de entidades de tile, mas pode ser estendido se você desejar construir monitores maiores. \nIntervalo: 16 ~ 1024",
"gui.computercraft.config.monitor_renderer": "Renderizador do monitor",
"gui.computercraft.config.monitor_renderer.tooltip": "O renderizador a ser utilizado para os monitores. Geralmente, isso deve ser mantido em \"best\" - se os monitores apresentarem problemas de desempenho, você pode querer experimentar renderizadores alternativos. \nValores Permitidos: BEST, TBO, VBO",
"gui.computercraft.config.peripheral": "Periféricos",
"gui.computercraft.config.peripheral.command_block_enabled": "Habilitar periférico do bloco de comando",
"gui.computercraft.config.peripheral.command_block_enabled.tooltip": "Habilitar periférico do bloco de comando",
"gui.computercraft.config.peripheral.max_notes_per_tick": "Número de notas que um computador pode tocar simultâneamente",
"gui.computercraft.config.peripheral.max_notes_per_tick.tooltip": "Quantidade máxima de notas que um alto-falante pode jogar de uma vez.\nIntervalo: > 1",
"gui.computercraft.config.peripheral.modem_high_altitude_range": "Alcance do modem (altitude elevada)",
"gui.computercraft.config.peripheral.modem_high_altitude_range.tooltip": "O intervalo de Modems Sem Fio a altitude máxima em tempo limpo, em metros.\nIntervalo: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm": "Alcance do modem (altitude elevada, clima ruim)",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm.tooltip": "O intervalo de Modems Sem Fio à altitude máxima em clima tempestuoso, em metros.\nIntervalo: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range": "Alcance do modem (padrão)",
"gui.computercraft.config.peripheral.modem_range.tooltip": "O alcance de Modems Sem Fio a baixa altitude em clima limpo, em metros.\nIntervalo: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range_during_storm": "Alcance do modem (clima ruim)",
"gui.computercraft.config.peripheral.modem_range_during_storm.tooltip": "A variedade de Modems Sem Fio a baixa altitude em clima tempestuoso, em metros.\nIntervalo: 0 ~ 100000",
"gui.computercraft.config.peripheral.monitor_bandwidth": "Monitorar banda",
"gui.computercraft.config.peripheral.monitor_bandwidth.tooltip": "O limite de quanta informação de monitor pode ser enviada *por tick*. Nota:\n- A largura de banda é medida antes da compressão, então os dados enviados ao cliente são menores.\n- Isso ignora o número de jogadores para os quais um pacote é enviado. Atualizar um monitor para um jogador consome o mesmo limite de largura de banda que enviar para 20.\n- Um monitor de tamanho completo envia ~25kb de dados. Portanto, o padrão (1MB) permite que ~40 monitores sejam atualizados em um único tick. \nDefina como 0 para desativar. \nIntervalo: > 0",
"gui.computercraft.config.peripheral.tooltip": "Várias opções relacionadas com os periféricos.",
"gui.computercraft.config.term_sizes": "Tamanhos do terminal",
"gui.computercraft.config.term_sizes.computer": "Computador",
"gui.computercraft.config.term_sizes.computer.height": "Altura do terminal",
"gui.computercraft.config.term_sizes.computer.height.tooltip": "Intervalo: 1 ~ 255",
"gui.computercraft.config.term_sizes.computer.tooltip": "Tamanho do terminal dos computadores portátil.",
"gui.computercraft.config.term_sizes.computer.width": "Largura do terminal",
"gui.computercraft.config.term_sizes.computer.width.tooltip": "Intervalo: 1 ~ 255",
"gui.computercraft.config.term_sizes.monitor": "Monitor",
"gui.computercraft.config.term_sizes.monitor.height": "Altura máxima da monitor",
"gui.computercraft.config.term_sizes.monitor.height.tooltip": "Intervalo: 1 ~ 32",
"gui.computercraft.config.term_sizes.monitor.tooltip": "Tamanho máximo de monitores (em blocos).",
"gui.computercraft.config.term_sizes.monitor.width": "Largura máxima do monitor",
"gui.computercraft.config.term_sizes.monitor.width.tooltip": "Intervalo: 1 ~ 32",
"gui.computercraft.config.term_sizes.pocket_computer": "Computador Portátil",
"gui.computercraft.config.term_sizes.pocket_computer.height": "Altura do terminal",
"gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "Intervalo: 1 ~ 255",
"gui.computercraft.config.term_sizes.pocket_computer.tooltip": "Tamanho do terminal dos computadores portátil.",
"gui.computercraft.config.term_sizes.pocket_computer.width": "Largura do terminal",
"gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "Intervalo: 1 ~ 255",
"gui.computercraft.config.term_sizes.tooltip": "Configure o tamanho dos terminais de vários computadores. Terminais maiores exigem mais largura de banda, portanto, use com cuidado.",
"gui.computercraft.config.turtle": "Tartarugas",
"gui.computercraft.config.turtle.advanced_fuel_limit": "Limite de combustível de Tartarugas Avançadas",
"gui.computercraft.config.turtle.advanced_fuel_limit.tooltip": "O limite de combustível para Advanced Turtles. \nIntervalo: > 0",
"gui.computercraft.config.turtle.can_push": "Tartarugas podem empurrar entidades",
"gui.computercraft.config.turtle.can_push.tooltip": "Se definido como verdadeiro, as Tartarugas empurrarão entidades para o lado em vez de parar, caso haja espaço para isso.",
"gui.computercraft.config.turtle.need_fuel": "Habilitar combustível",
"gui.computercraft.config.turtle.need_fuel.tooltip": "Defina se as tartarugas requerem combustível para se mover.",
"gui.computercraft.config.turtle.normal_fuel_limit": "Limite de combustível de Tartarugas",
"gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "O limite de combustível para Advanced Turtles. \nIntervalo: > 0",
"gui.computercraft.config.turtle.tooltip": "Várias opções relacionadas às Tartarugas.",
"gui.computercraft.config.upload_max_size": "Tamanho máximo para upload de arquivos (bytes)",
"gui.computercraft.config.upload_max_size.tooltip": "O limite de tamanho de upload de arquivos, em bytes. Deve estar na faixa de 1 KiB a 16 MiB. \nTenha em mente que os uploads são processados em um único tick - arquivos grandes ou desempenho de rede ruim podem travar a thread de rede. E cuidado com o espaço em disco! \nIntervalo: 1024 ~ 16777216",
"gui.computercraft.config.upload_nag_delay": "Atraso de notificação de upload",
"gui.computercraft.config.upload_nag_delay.tooltip": "O atraso em segundos após o qual seremos notificados sobre importações não tratadas. Defina como 0 para desabilitar. \nIntervalo: 0 ~ 60",
"gui.computercraft.pocket_computer_overlay": "Computador portátil aberto. Pressione ESC para fechar.",
"gui.computercraft.terminal": "Terminal do Computador",
"gui.computercraft.tooltip.computer_id": "ID do Computador: %s",
"gui.computercraft.tooltip.copy": "Copiar para a área de transferência",
"gui.computercraft.tooltip.disk_id": "ID do Disco: %s",
"gui.computercraft.tooltip.terminate": "Parar o código atualmente em execução",
"gui.computercraft.tooltip.terminate.key": "Segure Ctrl+T",
"gui.computercraft.tooltip.turn_off": "Desligar este computador",
"gui.computercraft.tooltip.turn_off.key": "Segure Ctrl+S",
"gui.computercraft.tooltip.turn_on": "Ligar este computador",
"gui.computercraft.upload.failed": "Falha no Upload",
"gui.computercraft.upload.failed.computer_off": "Você deve ligar o computador antes de fazer o upload de arquivos.",
"gui.computercraft.upload.failed.corrupted": "Arquivos corrompidos ao dar upload. Por favor, tente novamente.",
"gui.computercraft.upload.failed.generic": "Upload de arquivos falhou (%s)",
"gui.computercraft.upload.failed.name_too_long": "Nomes de arquivos são muito longos para dar upload.",
"gui.computercraft.upload.failed.too_many_files": "Não é possível dar upload nesta quantidade de arquivos.",
"gui.computercraft.upload.failed.too_much": "Seus arquivos são muito grandes para dar upload.",
"gui.computercraft.upload.no_response": "Transferindo Arquivos",
"gui.computercraft.upload.no_response.msg": "Seu computador não usou os arquivos transferidos. Você pode precisar executar o programa %s e tentar novamente.",
"item.computercraft.disk": "Disquete",
"item.computercraft.pocket_computer_advanced": "Computador Portátil Avançado",
"item.computercraft.pocket_computer_advanced.upgraded": "Computador Portátil Avançado %s",
@@ -69,6 +202,25 @@
"item.computercraft.printed_page": "Página Impressa",
"item.computercraft.printed_pages": "Páginas Impressas",
"item.computercraft.treasure_disk": "Disquete",
"itemGroup.computercraft": "ComputerCraft",
"tag.item.computercraft.computer": "Computadores",
"tag.item.computercraft.monitor": "Monitores",
"tag.item.computercraft.turtle": "Tartarugas",
"tag.item.computercraft.wired_modem": "Modems com Fio",
"tracking_field.computercraft.avg": "%s (média)",
"tracking_field.computercraft.computer_tasks.name": "Tarefas",
"tracking_field.computercraft.count": "%s (contagem)",
"tracking_field.computercraft.fs.name": "Operações de sistema",
"tracking_field.computercraft.http_download.name": "Download HTTP",
"tracking_field.computercraft.http_requests.name": "Solicitações HTTP",
"tracking_field.computercraft.http_upload.name": "Upload de HTTP",
"tracking_field.computercraft.java_allocation.name": "Alocações Java",
"tracking_field.computercraft.max": "%s (máximo)",
"tracking_field.computercraft.peripheral.name": "Chamadas Periféricas",
"tracking_field.computercraft.server_tasks.name": "Tarefas do servidor",
"tracking_field.computercraft.turtle_ops.name": "Operações de tartaruga",
"tracking_field.computercraft.websocket_incoming.name": "Entrada do Websocket",
"tracking_field.computercraft.websocket_outgoing.name": "Saída do Websocket",
"upgrade.computercraft.speaker.adjective": "(Alto-Falante)",
"upgrade.computercraft.wireless_modem_advanced.adjective": "Ender",
"upgrade.computercraft.wireless_modem_normal.adjective": "sem Fio",

View File

@@ -32,8 +32,6 @@
"commands.computercraft.generic.additional_rows": "%d дополнительных строк …",
"commands.computercraft.generic.exception": "Необработанное исключение (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<нет позиции>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "Y",
"commands.computercraft.help.desc": "Отображает это сообщение справки",
"commands.computercraft.help.no_children": "%s не имеет подкоманд",

View File

@@ -32,8 +32,6 @@
"commands.computercraft.generic.additional_rows": "%d ytterligare rader…",
"commands.computercraft.generic.exception": "Ohanterat felfall (%s)",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.no_position": "<no pos>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "J",
"commands.computercraft.help.desc": "Visa detta hjälpmeddelande",
"commands.computercraft.help.no_children": "%s har inget underkommando",

Some files were not shown because too many files have changed in this diff Show More