1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-17 06:57:38 +00:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Jonathan Coates
94e7d2d03b Render pocket computers in tooltips 2024-10-24 18:49:14 +01: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
50 changed files with 1051 additions and 270 deletions

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

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/

27
crowdin.yml Normal file
View File

@@ -0,0 +1,27 @@
# 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_cs # 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

@@ -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.113.0
modVersion=1.113.1
# 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 = "0.9.4"
commonsCli = "1.6.0"
jetbrainsAnnotations = "24.1.0"
jsr305 = "3.0.2"
@@ -71,6 +71,7 @@ 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 +95,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" }
@@ -175,6 +177,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" }

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

@@ -56,4 +56,8 @@ public final class ClientPocketComputers {
var id = PocketComputerItem.getInstanceID(stack);
return id == null ? null : instances.get(id);
}
static @Nullable PocketComputerData get(UUID id) {
return instances.get(id);
}
}

View File

@@ -0,0 +1,101 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.client.pocket;
import com.mojang.blaze3d.vertex.PoseStack;
import dan200.computercraft.client.gui.GuiSprites;
import dan200.computercraft.client.render.ComputerBorderRenderer;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.SpriteRenderer;
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
import dan200.computercraft.shared.pocket.items.PocketTooltipComponent;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.client.renderer.MultiBufferSource;
import javax.annotation.Nullable;
import java.util.UUID;
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT;
import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_WIDTH;
/**
* Renders the pocket computer's terminal in the item's tooltip.
* <p>
* The rendered terminal is downscaled by a factor of {@link #SCALE}.
*/
public class PocketClientTooltipComponent implements ClientTooltipComponent {
private static final float SCALE = 0.5f;
private final UUID id;
private final ComputerFamily family;
public PocketClientTooltipComponent(PocketTooltipComponent component) {
this.id = component.id();
this.family = component.family();
}
private @Nullable PocketComputerData computer() {
return ClientPocketComputers.get(id);
}
private @Nullable NetworkedTerminal terminal() {
var computer = computer();
return computer == null ? null : computer.getTerminal();
}
@Override
public int getHeight() {
var terminal = terminal();
if (terminal == null) return 0;
return (int) Math.ceil(
(terminal.getHeight() * FixedWidthFontRenderer.FONT_HEIGHT + ComputerBorderRenderer.BORDER * 2 + ComputerBorderRenderer.MARGIN * 2) * SCALE
);
}
@Override
public int getWidth(Font font) {
var terminal = terminal();
if (terminal == null) return 0;
return (int) Math.ceil(
(terminal.getWidth() * FixedWidthFontRenderer.FONT_WIDTH + ComputerBorderRenderer.BORDER * 2 + ComputerBorderRenderer.MARGIN * 2) * SCALE
);
}
@Override
public void renderImage(Font font, int x, int y, GuiGraphics guiGraphics) {
var terminal = terminal();
if (terminal == null) return;
var pose = guiGraphics.pose();
pose.pushPose();
pose.translate(x, y, 0);
pose.scale(SCALE, SCALE, 1);
render(pose, guiGraphics.bufferSource(), terminal);
pose.popPose();
}
private void render(PoseStack stack, MultiBufferSource buffers, Terminal terminal) {
var width = terminal.getWidth() * FONT_WIDTH + MARGIN * 2;
var height = terminal.getHeight() * FONT_HEIGHT + MARGIN * 2;
var renderer = SpriteRenderer.createForGui(stack.last().pose(), buffers.getBuffer(RenderTypes.GUI_SPRITES));
ComputerBorderRenderer.render(renderer, GuiSprites.getComputerTextures(family), BORDER, BORDER, width, height, false);
var quadEmitter = FixedWidthFontRenderer.toVertexConsumer(stack, buffers.getBuffer(RenderTypes.TERMINAL));
FixedWidthFontRenderer.drawTerminal(quadEmitter, BORDER + MARGIN, BORDER + MARGIN, terminal, MARGIN, MARGIN, MARGIN, MARGIN);
}
}

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

@@ -34,11 +34,12 @@ public class SpriteRenderer {
this.b = b;
}
public static SpriteRenderer createForGui(Matrix4f transform, VertexConsumer builder) {
return new SpriteRenderer(transform, builder, 0, RenderTypes.FULL_BRIGHT_LIGHTMAP, 255, 255, 255);
}
public static SpriteRenderer createForGui(GuiGraphics graphics, RenderType renderType) {
return new SpriteRenderer(
graphics.pose().last().pose(), graphics.bufferSource().getBuffer(renderType),
0, RenderTypes.FULL_BRIGHT_LIGHTMAP, 255, 255, 255
);
return createForGui(graphics.pose().last().pose(), graphics.bufferSource().getBuffer(renderType));
}
/**

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

@@ -38,8 +38,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

@@ -160,8 +160,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)");

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

@@ -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);
computers.forEach(fun);
}
}
}

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

@@ -28,7 +28,6 @@ import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
@@ -39,6 +38,7 @@ import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
@@ -47,6 +47,7 @@ import net.minecraft.world.level.Level;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
public class PocketComputerItem extends Item implements IComputerItem, IMedia, IColouredItem {
@@ -196,6 +197,11 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
}
}
@Override
public Optional<TooltipComponent> getTooltipImage(ItemStack stack) {
var id = getInstanceID(stack);
return id == null ? Optional.empty() : Optional.of(new PocketTooltipComponent(id, family));
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> list, TooltipFlag flag) {
@@ -350,8 +356,4 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
compound.put(NBT_UPGRADE_INFO, upgrade.data().copy());
}
}
public static CompoundTag getUpgradeInfo(ItemStack stack) {
return stack.getOrCreateTagElement(NBT_UPGRADE_INFO);
}
}

View File

@@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.pocket.items;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.ItemStack;
import java.util.UUID;
/**
* A tooltip computer describing a pocket computer.
* <p>
* This has no behaviour on its own. When rendering, this is converted to an equivalent client-side component,
* that renders the computer's terminal.
*
* @param id The instance ID of this pocket computer.
* @param family The family of this pocket computer.
* @see PocketComputerItem#getTooltipImage(ItemStack)
* @see dan200.computercraft.client.pocket.PocketClientTooltipComponent
*/
public record PocketTooltipComponent(UUID id, ComputerFamily family) implements TooltipComponent {
}

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

@@ -57,7 +57,7 @@
"commands.computercraft.track.start.stop": "Führe %s aus um die Aufzeichnung zu stoppen und die Ergebnisse anzusehen",
"commands.computercraft.track.start.synopsis": "Startet die Aufzeichnung von Computern",
"commands.computercraft.track.stop.action": "Klicke um die Aufzeichnung zu stoppen",
"commands.computercraft.track.stop.desc": "Stopt die Aufzeichnung aller Computer Events und Laufzeiten",
"commands.computercraft.track.stop.desc": "Stopt die Aufzeichnung aller Computer-Events und Laufzeiten",
"commands.computercraft.track.stop.not_enabled": "Momentan werden keine Computer aufgezeichnet",
"commands.computercraft.track.stop.synopsis": "Stoppt die Aufzeichnung aller Computer",
"commands.computercraft.track.synopsis": "Zeichnet die Laufzeiten von Computern auf.",
@@ -75,7 +75,7 @@
"gui.computercraft.config.default_computer_settings": "Computer-Standardeinstellungen",
"gui.computercraft.config.default_computer_settings.tooltip": "eine mit Komma separierte Liste an standardmäßige Systemeinstellungen für neuen Computern.\nBeispiel: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\nwürde jegliche Autovervollständigung deaktivieren.",
"gui.computercraft.config.disabled_generic_methods": "Generische Methoden deaktiviert.",
"gui.computercraft.config.disabled_generic_methods.tooltip": "Eine Liste an generischen Methoden oder Methodenquellen zum deaktivieren.\nGenerische Methoden sind Methoden die zu einem block/block entity hinzugefügt werden, insofern kein expliziter Peripheral Provider\ngefunden wurde. Mitbetroffen sind Inventarmethoden (d.h. inventory.getItemDetail,\ninventory.pushItems) und, wenn in Forge gespielt wird, die fluid_storage und energy_storage\nMethoden.\nMethoden in dieser Liste können entweder Gruppen von Methoden (wie computercraft:inventory)\noder einzelne Methoden (wie computercraft:inventory#pushItems) sein.\n",
"gui.computercraft.config.disabled_generic_methods.tooltip": "Eine Liste an generischen Methoden oder Methodenquellen zum deaktivieren.\nGenerische Methoden sind Methoden die zu einem Block oder Blockentity hinzugefügt werden, insofern kein expliziter Peripheral Provider\ngefunden wurde. Mitbetroffen sind Inventarmethoden (d.h. inventory.getItemDetail,\ninventory.pushItems) und, wenn in Forge gespielt wird, die fluid_storage und energy_storage\nMethoden.\nMethoden in dieser Liste können entweder Gruppen von Methoden (wie computercraft:inventory)\noder einzelne Methoden (wie computercraft:inventory#pushItems) sein.\n",
"gui.computercraft.config.execution": "Ausführung",
"gui.computercraft.config.execution.computer_threads": "Computer Threads",
"gui.computercraft.config.execution.computer_threads.tooltip": "Setzt die Anzahl an Hintergrundprozessen fest, auf denen Computer laufen können. Eine hohe Nummer heißt,\ndass mehrere Computer zur selben Zeit laufen können, jedoch aber auch ggf. mehr Verzögerungen verursachen. Bitte beachte, dass manche mods\nnicht mit einer Anzahl an Hintergrundprozessen laufen, die höher als 1 ist. Benutze also mit bedacht.\nBereich: > 1",
@@ -133,15 +133,15 @@
"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'",
"argument.computercraft.computer.label": "Computername",
"argument.computercraft.unknown_computer_family": "Unbekannte Computerfamilie '%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.global_upload": "Globale Uploadbandbreite",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "Die maximale Bandbreite aller Computer in bytes/s mit der heruntergeladen werden kann.\nBereich: > 1",
"gui.computercraft.config.http.bandwidth.global_download": "Globale Downloadbandbreite",
"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"
"argument.computercraft.computer.family": "Computerfamilie",
"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 Bandbreite aller Computer in bytes/s mit der hochgeladen werden kann.\nBereich: > 1"
}

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,11 +30,11 @@
"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",
@@ -39,65 +45,182 @@
"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

@@ -0,0 +1,237 @@
{
"argument.computercraft.argument_expected": "Beklenen Argüman",
"argument.computercraft.computer.distance": "Varlığa olan mesafe",
"argument.computercraft.computer.family": "Bilgisayar ailesi",
"argument.computercraft.computer.id": "Bilgisayar Kimliği",
"argument.computercraft.computer.instance": "Benzersiz örnek kimliği",
"argument.computercraft.computer.label": "Bilgisayar etiketi",
"argument.computercraft.computer.many_matching": "Birden fazla bilgisayar eşleşiyor '%s' (örnekler %s)",
"argument.computercraft.computer.no_matching": "Eşleşen bilgisayar yok '%s'",
"argument.computercraft.tracking_field.no_field": "Bilinmeyen alan '%s'",
"argument.computercraft.unknown_computer_family": "Bilinmeyen bilgisayar ailesi '%s'",
"block.computercraft.cable": "Ağ Kablosu",
"block.computercraft.computer_advanced": "Gelişmiş Bilgisayar",
"block.computercraft.computer_command": "Komut Bilgisayarı",
"block.computercraft.computer_normal": "Bilgisayar",
"block.computercraft.disk_drive": "Disk Sürücüsü",
"block.computercraft.monitor_advanced": "Gelişmiş Monitör",
"block.computercraft.monitor_normal": "Monitör",
"block.computercraft.printer": "Yazıcı",
"block.computercraft.speaker": "Hoparlör",
"block.computercraft.turtle_advanced": "Gelişmiş Kaplumbağa",
"block.computercraft.turtle_advanced.upgraded": "Gelişmiş %s Kaplumbağa",
"block.computercraft.turtle_advanced.upgraded_twice": "Gelişmiş %s %s Kaplumbağa",
"block.computercraft.turtle_normal": "Kaplumbağa",
"block.computercraft.turtle_normal.upgraded": "%s Kaplumbağa",
"block.computercraft.turtle_normal.upgraded_twice": "%s %s Kaplumbağa",
"block.computercraft.wired_modem": "Kablolu Modem",
"block.computercraft.wired_modem_full": "Kablolu Modem",
"block.computercraft.wireless_modem_advanced": "Ender Modem",
"block.computercraft.wireless_modem_normal": "Kablosuz Modem",
"chat.computercraft.wired_modem.peripheral_connected": "Çevre birimi \"%s\" ağa bağlandı",
"chat.computercraft.wired_modem.peripheral_disconnected": "Çevre birimi \"%s\" ağ ile bağlantısı kesildi",
"commands.computercraft.desc": "/computercraft komutu, bilgisayarları kontrol etmek ve bilgisayarlarla etkileşimde bulunmak için çeşitli hata ayıklama ve yönetici araçları sağlar.",
"commands.computercraft.dump.action": "Bu bilgisayar hakkında daha fazla bilgi görüntüle",
"commands.computercraft.dump.desc": "Tüm bilgisayarların durumunu veya bir bilgisayarla ilgili belirli bilgileri görüntüleme. Bilgisayarın örnek kimliğini (örn. 123), bilgisayar kimliğini (örn. #123) ya da etiketini (örn. \"@Bilgisayar\") belirtebilirsiniz.",
"commands.computercraft.dump.open_path": "Bu bilgisayarın dosyalarını görüntüle",
"commands.computercraft.dump.synopsis": "Bilgisayarların durumunu görüntüle.",
"commands.computercraft.generic.additional_rows": "%d ek satır…",
"commands.computercraft.generic.exception": "Beklenmeyen durum (%s)",
"commands.computercraft.generic.no": "H",
"commands.computercraft.generic.no_position": "<no poz>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "E",
"commands.computercraft.help.desc": "Bu yardım mesajını görüntüler",
"commands.computercraft.help.no_children": "%s alt komutları yok",
"commands.computercraft.help.no_command": "Böyle bir komut yok '%s'",
"commands.computercraft.help.synopsis": "Belirli bir komut için yardım sağlar",
"commands.computercraft.queue.desc": "Komut bilgisayarına bir computer_command olayı gönder, ek argümanları geçerek. Bu çoğunlukla harita yapımcıları için tasarlanmıştır ve /trigger'ın daha bilgisayar dostu bir versiyonu olarak işlev görür. Herhangi bir oyuncu komutu çalıştırabilir, bu da büyük olasılıkla bir metin bileşeninin tıklama olayı aracılığıyla yapılır.",
"commands.computercraft.queue.synopsis": "Bir komut bilgisayarına computer_command olayı gönder",
"commands.computercraft.shutdown.desc": "Listelenen bilgisayarları veya hiçbiri belirtilmemişse tümünü kapatma. Bilgisayarın örnek kimliğini (örn. 123), bilgisayar kimliğini (örn. #123) ya da etiketini (örn. \"@Bilgisayar\") belirtebilirsiniz.",
"commands.computercraft.shutdown.done": "%s/%s bilgisayarı kapat",
"commands.computercraft.shutdown.synopsis": "Bilgisayarları uzaktan kapat.",
"commands.computercraft.synopsis": "Bilgisayarları kontrol etmek için çeşitli komutlar.",
"commands.computercraft.tp.action": "Bu bilgisayara ışınlan",
"commands.computercraft.tp.desc": "Bir bilgisayarın bulunduğu yere ışınlan. Bilgisayarın örnek kimliğini (örn. 123), bilgisayar kimliğini (örn. #123) belirtebilirsiniz.",
"commands.computercraft.tp.synopsis": "Belirli bir bilgisayara ışınlan.",
"commands.computercraft.track.desc": "Bilgisayarların ne kadar süre çalıştığını ve kaç olay işlediğini takip et. Bu, /forge track'e benzer bir şekilde bilgi sunar ve gecikmeyi teşhis etmek için yararlı olabilir.",
"commands.computercraft.track.dump.computer": "Bilgisayar",
"commands.computercraft.track.dump.desc": "Bilgisayar takibinin en son sonuçlarını boşalt.",
"commands.computercraft.track.dump.no_timings": "Zamanlama mevcut değil",
"commands.computercraft.track.dump.synopsis": "En son izleme sonuçlarını boşalt",
"commands.computercraft.track.start.desc": "Tüm bilgisayarların yürütme sürelerini ve olay sayılarını izlemeye başla. Bu, önceki çalıştırmaların sonuçlarını atacaktır.",
"commands.computercraft.track.start.stop": "İzlemeyi durdurmak ve sonuçları görüntülemek için %s çalıştır",
"commands.computercraft.track.start.synopsis": "Tüm bilgisayarları izlemeyi başlat",
"commands.computercraft.track.stop.action": "İzlemeyi durdurmak için tıkla",
"commands.computercraft.track.stop.desc": "Tüm bilgisayarların olaylarını ve yürütme sürelerini izlemeyi durdur",
"commands.computercraft.track.stop.not_enabled": "Şu anda bilgisayarlar izlenmiyor",
"commands.computercraft.track.stop.synopsis": "Tüm bilgisayarları izlemeyi durdur",
"commands.computercraft.track.synopsis": "Bilgisayarların yürütme sürelerini takip et.",
"commands.computercraft.turn_on.desc": "Listelenen bilgisayarları aç. Bilgisayarın örnek kimliğini (örn. 123), bilgisayar kimliğini (örn. #123) ya da etiketini (örn. \"@Bilgisayar\") belirtebilirsiniz.",
"commands.computercraft.turn_on.done": "%s/%s bilgisayar açıldı",
"commands.computercraft.turn_on.synopsis": "Bilgisayarları uzaktan aç.",
"commands.computercraft.view.action": "Bu bilgisayarı görüntüle",
"commands.computercraft.view.desc": "Bir bilgisayarın terminalinin açılması, bir bilgisayarın uzaktan kontrolüne izin verir. Bu, kaplumbağanın envanterlerine erişim sağlamaz. Bilgisayarın örnek kimliğini (örn. 123), bilgisayar kimliğini (örn. #123) belirtebilirsiniz.",
"commands.computercraft.view.not_player": "Oyuncu olmayanlar için terminal açılamıyor",
"commands.computercraft.view.synopsis": "Bir bilgisayarın terminalini görüntüle.",
"gui.computercraft.config.command_require_creative": "Komut bilgisayarları yaratıcı modu gerektirir",
"gui.computercraft.config.command_require_creative.tooltip": "Oyuncuların komut bilgisayarlarıyla etkileşime girebilmesi için yaratıcı modda olmalarını\nve op'lu olmalarını gerektirir. Bu, vanilla'nın Komut blokları için varsayılan davranıştır.",
"gui.computercraft.config.computer_space_limit": "Bilgisayar alan sınırı (bayt)",
"gui.computercraft.config.computer_space_limit.tooltip": "Bilgisayarlar ve kaplumbağalar için bayt cinsinden disk alanı sınırı.",
"gui.computercraft.config.default_computer_settings": "Varsayılan Bilgisayar ayarları",
"gui.computercraft.config.default_computer_settings.tooltip": "Yeni bilgisayarlarda ayarlanacak varsayılan sistem ayarlarının virgülle\nayrılmış bir listesi.\nÖrnek: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\ntüm otomatik tamamlamayı devre dışı bırakır.",
"gui.computercraft.config.disabled_generic_methods": "Devre dışı bırakılmış genel yöntemler",
"gui.computercraft.config.disabled_generic_methods.tooltip": "Devre dışı bırakılacak genel yöntemlerin veya yöntem kaynaklarının bir listesi.\nGenel yöntemler açık bir çevresel sağlayıcı olmadığında bir blok/blok varlığına\neklenen yöntemlerdir. Bu, envanter yöntemlerini (yani inventory.getItemDetail,\ninventory.pushItems), ve (Forge'da ise), fluid_storage ve energy_storage\nyöntemlerini içerir.\nBu listedeki yöntemler bir grup yöntem (computercraft:inventory)\nya da tek bir yöntem (computercraft:inventory#pushItems) olabilir.\n",
"gui.computercraft.config.execution": "Yürüt",
"gui.computercraft.config.execution.computer_threads": "Bilgisayar iş parçacıkları",
"gui.computercraft.config.execution.computer_threads.tooltip": "Bilgisayarların çalışabileceği iş parçacığı sayısını ayarla. Daha yüksek bir\nsayı, aynı anda daha fazla bilgisayarın çalışabileceği anlamına gelir, ancak\ngecikmeye neden olabilir. Lütfen bazı modların 1'den yüksek iş parçacığı sayısı\nile çalışmayabileceğini unutmayın. Dikkatli kullanın.\nAralık: > 1",
"gui.computercraft.config.execution.max_main_computer_time": "Sunucu tik bilgisayar zaman sınırı",
"gui.computercraft.config.execution.max_main_computer_time.tooltip": "Milisaniye cinsinden, bilgisayarın bir tik içinde yürütebileceği ideal maksimum süre.\nUnutmayın, ne kadar süreceğini söylemenin bir yolu olmadığı için büyük olasılıkla\nbu sınırı aşacağız - bu, ortalama sürenin üst sınırı olmayı\namaçlamaktadır.\nAralık: > 1",
"gui.computercraft.config.execution.max_main_global_time": "Sunucu tik genel zaman sınırı",
"gui.computercraft.config.execution.max_main_global_time.tooltip": "Milisaniye cinsinden, tek bir tikte görevleri yürütmek için harcanabilecek\nmaksimum süre.\nUnutmayın, ne kadar süreceğini söylemenin bir yolu olmadığı için büyük\nolasılıkla bu sınırı aşacağız - bu, ortalama sürenin üst sınırı olmayı\namaçlamaktadır.\nAralık: > 1",
"gui.computercraft.config.execution.tooltip": "Bilgisayarların yürütme davranışını kontrol eder. Bu, büyük ölçüde sunuculara\nince ayar yapmak için tasarlanmıştır ve genellikle dokunulması gerekmez.",
"gui.computercraft.config.floppy_space_limit": "Disket alan sınırı (bayt)",
"gui.computercraft.config.floppy_space_limit.tooltip": "Disketler için bayt cinsinden disk alanı sınırı.",
"gui.computercraft.config.http": "HTTP",
"gui.computercraft.config.http.bandwidth": "Bant Genişliği",
"gui.computercraft.config.http.bandwidth.global_download": "Genel indirme sınırı",
"gui.computercraft.config.http.bandwidth.global_download.tooltip": "Bir saniye içinde indirilebilecek bayt sayısı. Bu tüm bilgisayarlar arasında paylaşılır. (bayt/s).\nAralık: > 1",
"gui.computercraft.config.http.bandwidth.global_upload": "Genel yükleme sınırı",
"gui.computercraft.config.http.bandwidth.global_upload.tooltip": "Bir saniye içinde yüklenebilecek bayt sayısı. Bu tüm bilgisayarlar arasında paylaşılır. (bayt/s).\nAralık: > 1",
"gui.computercraft.config.http.bandwidth.tooltip": "Bilgisayarlar tarafından kullanılan bant genişliğini sınırlar.",
"gui.computercraft.config.http.enabled": "HTTP API'sini etkinleştir",
"gui.computercraft.config.http.enabled.tooltip": "Bilgisayarlarda \"http\" API'sini etkinleştir. Bunu devre dışı bırakmak, birçok kullanıcının güvendiği \"pastebin\" ve\n\"wget\" programlarını da devre dışı bırakır. Bunu açık bırakmanız ve daha ayrıntılı denetim uygulamak için\n\"rules\" yapılandırma seçeneğini kullanmanız önerilir.",
"gui.computercraft.config.http.max_requests": "Maksimum eşzamanlı istekler",
"gui.computercraft.config.http.max_requests.tooltip": "Bir bilgisayarın tek seferde yapabileceği http isteği sayısı. Ek istekler\nkuyruğa alınacak ve çalışan istekler bittiğinde gönderilecektir. Sınırsız için\n0 olarak ayarla.\nAralık: > 0",
"gui.computercraft.config.http.max_websockets": "Maksimum eşzamanlı websocketleri",
"gui.computercraft.config.http.max_websockets.tooltip": "Bir bilgisayarın tek seferde açık tutabileceği websocket sayısı.\nAralık: > 1",
"gui.computercraft.config.http.proxy": "Proxy",
"gui.computercraft.config.http.proxy.host": "Ana bilgisayar adı",
"gui.computercraft.config.http.proxy.host.tooltip": "Proxy sunucusunun ana bilgisayar adı veya IP adresi.",
"gui.computercraft.config.http.proxy.port": "Port",
"gui.computercraft.config.http.proxy.port.tooltip": "Proxy sunucusunun portu.\nAralık: 1 ~ 65536",
"gui.computercraft.config.http.proxy.tooltip": "HTTP ve websocket isteklerini bir proxy sunucusu üzerinden aktarır. Yalnızca \n\"use_proxy\" olan HTTP kurallarını etkiler, true olarak ayarla (varsayılan\nolarak kapalıdır).\nProxy için kimlik doğrulaması gerekiyorsa, \"computercraft-server.toml\" ile\naynı dizinde, iki nokta üst üste ile ayrılmış kullanıcı adı ve parolayı içeren\nbir \"computercraft-proxy.pw\" dosyası oluştur. örn. \"myuser:mypassword\".\nSOCKS4 proxy'leri için yalnızca kullanıcı adı gereklidir.",
"gui.computercraft.config.http.proxy.type": "Proxy türü",
"gui.computercraft.config.http.proxy.type.tooltip": "Kullanılacak proxy türü.\nİzin Verilen Değerler: HTTP, HTTPS, SOCKS4, SOCKS5",
"gui.computercraft.config.http.rules": "Kurallara izin ver/reddet",
"gui.computercraft.config.http.rules.tooltip": "Belirli alan adları veya IP'ler için \"http\" API davranışını denetleyen\nkurallar listesi. Her kural bir ana bilgisayar adı ve isteğe bağlı bir port ile\neşleşir ve ardından istek için çeşitli özellikler ayarlar. Kurallar sırayla\ndeğerlendirilir, yani önceki kurallar sonrakileri geçersiz kılar.\n\nGeçerli özellikler:\n - \"host\" (gerekli): Bu kuralın eşleştiği alan adı veya IP adresi. Bu bir alan adı olabilir\n (\"pastebin.com\"), wildcard (\"*.pastebin.com\") ya da CIDR gösterimi (\"127.0.0.0/8\").\n - \"port\" (isteğe bağlı): Belirli bir porta yönelik istekleri eşleştir\n80 veya 443 gibi\n\n - \"action\" (isteğe bağlı): Bu isteğe izin verilip verilmeyeceği veya\nreddedilip reddedilmeyeceği.\n - \"max_download\" (isteğe bağlı): Bir bilgisayarın bu istekte indirebileceği\nmaksimum boyut (bayt cinsinden).\n - \"max_upload\" (isteğe bağlı): Bir bilgisayarın bu istekte yükleyebileceği\nmaksimum boyut (bayt cinsinden).\n - \"max_websocket_message\" (isteğe bağlı): Bir bilgisayarın bir websocket\npaketinde gönderebileceği veya alabileceği maksimum boyut (bayt cinsinden).\n - \"use_proxy\" (isteğe bağlı): Yapılandırılmışsa HTTP/SOCKS proxy'sinin kullanımını etkinleştir.",
"gui.computercraft.config.http.tooltip": "HTTP API'sini kontrol eder",
"gui.computercraft.config.http.websocket_enabled": "Websocket'leri etkinleştir",
"gui.computercraft.config.http.websocket_enabled.tooltip": "Http websocket kullanımını etkinleştir. Bunun için \"http_enable\" seçeneğinin de true olması gerekir.",
"gui.computercraft.config.log_computer_errors": "Bilgisayar hatalarını günlüğe kaydet",
"gui.computercraft.config.log_computer_errors.tooltip": "Çevre birimleri ve diğer Lua nesneleri tarafından atılan istisnaları\ngünlüğe kaydet. Bu, mod yapımcılarının sorunları ayıklamasını kolaylaştırır\nancak insanların hatalı yöntemler kullanması durumunda günlük spam'ına neden\nolabilir.",
"gui.computercraft.config.maximum_open_files": "Bilgisayar başına maksimum açık dosya",
"gui.computercraft.config.maximum_open_files.tooltip": "Bir bilgisayarda aynı anda kaç dosyanın açık olabileceğini ayarla. Sınırsız için 0 olarak ayarla.\nAralık: > 0",
"gui.computercraft.config.monitor_distance": "Monitör mesafesi",
"gui.computercraft.config.monitor_distance.tooltip": "Monitörlerin görüntü oluşturacağı maksimum mesafe. Bu, varsayılan olarak\nstandart tile entity sınırıdır, ancak daha büyük monitörler oluşturmak\nisterseniz genişletilebilir.\nAralık: 16 ~ 1024",
"gui.computercraft.config.monitor_renderer": "Monitör oluşturucu",
"gui.computercraft.config.monitor_renderer.tooltip": "Monitörler için kullanılacak oluşturucu. Genellikle bu \"best\" değerinde\ntutulmalıdır - monitörlerde performans sorunları varsa, alternatif oluşturucuları\ndenemek isteyebilirsiniz.\nİzin Verilen Değerler: BEST, TBO, VBO",
"gui.computercraft.config.peripheral": "Çevre birimleri",
"gui.computercraft.config.peripheral.command_block_enabled": "Komut bloğu çevresel birimini etkinleştir",
"gui.computercraft.config.peripheral.command_block_enabled.tooltip": "Komut Bloğu çevre birimi desteğini etkinleştir",
"gui.computercraft.config.peripheral.max_notes_per_tick": "Bir bilgisayarın aynı anda çalabileceği maksimum nota sayısı",
"gui.computercraft.config.peripheral.max_notes_per_tick.tooltip": "Bir hoparlörün aynı anda çalabileceği maksimum nota miktarı.\nAralık: > 1",
"gui.computercraft.config.peripheral.modem_high_altitude_range": "Modem menzili (yüksek irtifa)",
"gui.computercraft.config.peripheral.modem_high_altitude_range.tooltip": "Kablosuz Modemlerin açık havada maksimum irtifadaki menzili, metre cinsinden.\nAralık: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm": "Modem menzili (yüksek irtifa, kötü hava koşulları)",
"gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm.tooltip": "Kablosuz Modemlerin fırtınalı havalarda maksimum irtifadaki menzili, metre cinsinden.\nAralık: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range": "Modem menzili (varsayılan)",
"gui.computercraft.config.peripheral.modem_range.tooltip": "Kablosuz Modemlerin açık havada alçak irtifadaki menzili, metre cinsinden.\nAralık: 0 ~ 100000",
"gui.computercraft.config.peripheral.modem_range_during_storm": "Modem menzili (kötü hava koşulları)",
"gui.computercraft.config.peripheral.modem_range_during_storm.tooltip": "Kablosuz Modemlerin fırtınalı havalarda alçak irtifadaki menzili, metre cinsinden.\nAralık: 0 ~ 100000",
"gui.computercraft.config.peripheral.monitor_bandwidth": "Monitör bant genişliği",
"gui.computercraft.config.peripheral.monitor_bandwidth.tooltip": "Tik başına* ne kadar monitör verisi gönderilebileceğinin sınırı. Not:\n - Bant genişliği sıkıştırmadan önce ölçülür, bu nedenle istemciye gönderilen veriler\n daha küçüktür.\n - Bu, bir paketin gönderildiği oyuncu sayısını göz ardı eder. Bir oyuncu için bir\nmonitörü güncellemek, 20 oyuncuya göndermekle aynı bant genişliği sınırını tüketir.\n - Tam boyutlu bir monitör ~25kb veri gönderir. Dolayısıyla varsayılan değer (1MB)\ntek bir tikte ~40 monitörün güncellenmesine izin verir.\nDevre dışı bırakmak için 0 olarak ayarla.\nAralık: > 0",
"gui.computercraft.config.peripheral.tooltip": "Çevre birimlerine ilişkin çeşitli seçenekler.",
"gui.computercraft.config.term_sizes": "Terminal boyutları",
"gui.computercraft.config.term_sizes.computer": "Bilgisayar",
"gui.computercraft.config.term_sizes.computer.height": "Terminal yüksekliği",
"gui.computercraft.config.term_sizes.computer.height.tooltip": "Aralık: 1 ~ 255",
"gui.computercraft.config.term_sizes.computer.tooltip": "Bilgisayarların terminal boyutu.",
"gui.computercraft.config.term_sizes.computer.width": "Terminal genişliği",
"gui.computercraft.config.term_sizes.computer.width.tooltip": "Aralık: 1 ~ 255",
"gui.computercraft.config.term_sizes.monitor": "Monitör",
"gui.computercraft.config.term_sizes.monitor.height": "Maks monitör yüksekliği",
"gui.computercraft.config.term_sizes.monitor.height.tooltip": "Aralık: 1 ~ 32",
"gui.computercraft.config.term_sizes.monitor.tooltip": "Maksimum monitör boyutu (blok olarak).",
"gui.computercraft.config.term_sizes.monitor.width": "Maks monitör genişliği",
"gui.computercraft.config.term_sizes.monitor.width.tooltip": "Aralık: 1 ~ 32",
"gui.computercraft.config.term_sizes.pocket_computer": "Cep Bilgisayarı",
"gui.computercraft.config.term_sizes.pocket_computer.height": "Terminal yüksekliği",
"gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "Aralık: 1 ~ 255",
"gui.computercraft.config.term_sizes.pocket_computer.tooltip": "Cep bilgisayarlarının terminal boyutu.",
"gui.computercraft.config.term_sizes.pocket_computer.width": "Terminal genişliği",
"gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "Aralık: 1 ~ 255",
"gui.computercraft.config.term_sizes.tooltip": "Çeşitli bilgisayar terminallerinin boyutunu yapılandır.\nDaha büyük terminaller daha fazla bant genişliği gerektirir, bu nedenle dikkatli\nkullanın.",
"gui.computercraft.config.turtle": "Kaplumbağalar",
"gui.computercraft.config.turtle.advanced_fuel_limit": "Gelişmiş Kaplumbağa yakıt limiti",
"gui.computercraft.config.turtle.advanced_fuel_limit.tooltip": "Gelişmiş Kaplumbağaların yakıt limiti.\nAralık: > 0",
"gui.computercraft.config.turtle.can_push": "Kaplumbağalar varlıkları itebilir",
"gui.computercraft.config.turtle.can_push.tooltip": "true olarak ayarlanırsa, Kaplumbağalar yer varsa durmak yerine varlıkları yolun\ndışına iter.",
"gui.computercraft.config.turtle.need_fuel": "Yakıtı etkinleştir",
"gui.computercraft.config.turtle.need_fuel.tooltip": "Kaplumbağaların hareket etmek için yakıta ihtiyaç duyup duymadığını ayarla.",
"gui.computercraft.config.turtle.normal_fuel_limit": "Kaplumbağa yakıt limiti",
"gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "Kaplumbağaların yakıt limiti.\nAralık: > 0",
"gui.computercraft.config.turtle.tooltip": "Kaplumbağalarla ilgili çeşitli seçenekler.",
"gui.computercraft.config.upload_max_size": "Dosya yükleme boyut sınırı (bayt)",
"gui.computercraft.config.upload_max_size.tooltip": "Bayt cinsinden dosya yükleme boyut sınırı. 1 KiB ve 16 MiB aralığında olmalıdır.\nYüklemelerin tek bir tikte işlendiğini unutmayın - büyük dosyalar veya düşük ağ\nperformansı ağ iş parçacığını bekletebilir. Ve disk alanına dikkat edin!\nAralık: 1024 ~ 16777216",
"gui.computercraft.config.upload_nag_delay": "Yükleme nag gecikmesi",
"gui.computercraft.config.upload_nag_delay.tooltip": "Beklenmeyen içe aktarmalar hakkında bildirimde bulunacağımız saniye cinsinden gecikme. Devre dışı bırakmak için 0 olarak ayarla.\nAralık: 0 ~ 60",
"gui.computercraft.pocket_computer_overlay": "Cep bilgisayarıık. Kapatmak için ESC tuşuna bas.",
"gui.computercraft.terminal": "Bilgisayar terminali",
"gui.computercraft.tooltip.computer_id": "Bilgisayar Kimliği: %s",
"gui.computercraft.tooltip.copy": "Panoya kopyala",
"gui.computercraft.tooltip.disk_id": "Disk Kimliği: %s",
"gui.computercraft.tooltip.terminate": "Çalışmakta olan kodu durdur",
"gui.computercraft.tooltip.terminate.key": "Ctrl+T basılı tut",
"gui.computercraft.tooltip.turn_off": "Bu bilgisayarı kapat",
"gui.computercraft.tooltip.turn_off.key": "Ctrl+S basılı tut",
"gui.computercraft.tooltip.turn_on": "Bu bilgisayarı aç",
"gui.computercraft.upload.failed": "Yükleme Başarısız",
"gui.computercraft.upload.failed.computer_off": "Dosyaları yüklemeden önce bilgisayarı açmalısın.",
"gui.computercraft.upload.failed.corrupted": "Dosyalar yüklenirken bozuldu. Lütfen tekrar dene.",
"gui.computercraft.upload.failed.generic": "Dosya yükleme başarısız (%s)",
"gui.computercraft.upload.failed.name_too_long": "Dosya adları yüklenemeyecek kadar uzun.",
"gui.computercraft.upload.failed.too_many_files": "Bu kadar dosya yüklenemiyor.",
"gui.computercraft.upload.failed.too_much": "Dosyalarınız yüklenemeyecek kadar büyük.",
"gui.computercraft.upload.no_response": "Dosyalar Aktarılıyor",
"gui.computercraft.upload.no_response.msg": "Bilgisayarınız aktarılan dosyalarınızı kullanmadı. %s programını çalıştırmanız ve tekrar denemeniz gerekebilir.",
"item.computercraft.disk": "Disket",
"item.computercraft.pocket_computer_advanced": "Gelişmiş Cep Bilgisayarı",
"item.computercraft.pocket_computer_advanced.upgraded": "Gelişmiş %s Cep Bilgisayarı",
"item.computercraft.pocket_computer_normal": "Cep Bilgisayarı",
"item.computercraft.pocket_computer_normal.upgraded": "%s Cep Bilgisayarı",
"item.computercraft.printed_book": "Yazdırılmış Kitap",
"item.computercraft.printed_page": "Yazdırılmış Sayfa",
"item.computercraft.printed_pages": "Yazdırılmış Sayfalar",
"item.computercraft.treasure_disk": "Disket",
"itemGroup.computercraft": "ComputerCraft",
"tag.item.computercraft.computer": "Bilgisayarlar",
"tag.item.computercraft.dyeable": "Boyanabilir eşyalar",
"tag.item.computercraft.monitor": "Monitörler",
"tag.item.computercraft.turtle": "Kaplumbağalar",
"tag.item.computercraft.turtle_can_place": "Kaplumbağa-koyulabilir eşyalar",
"tag.item.computercraft.wired_modem": "Kablolu modemler",
"tracking_field.computercraft.avg": "%s (ort)",
"tracking_field.computercraft.computer_tasks.name": "Görevler",
"tracking_field.computercraft.count": "%s (sayı)",
"tracking_field.computercraft.fs.name": "Dosya sistemi işlemleri",
"tracking_field.computercraft.http_download.name": "HTTP indir",
"tracking_field.computercraft.http_requests.name": "HTTP istekleri",
"tracking_field.computercraft.http_upload.name": "HTTP yükleme",
"tracking_field.computercraft.java_allocation.name": "Java Ayırmaları",
"tracking_field.computercraft.max": "%s (maks)",
"tracking_field.computercraft.peripheral.name": "Çevre birimi çağrıları",
"tracking_field.computercraft.server_tasks.name": "Sunucu görevleri",
"tracking_field.computercraft.turtle_ops.name": "Kaplumbağa işlemleri",
"tracking_field.computercraft.websocket_incoming.name": "Websocket gelen",
"tracking_field.computercraft.websocket_outgoing.name": "Websocket giden",
"upgrade.computercraft.speaker.adjective": "Gürültücü",
"upgrade.computercraft.wireless_modem_advanced.adjective": "Ender",
"upgrade.computercraft.wireless_modem_normal.adjective": "Kablosuz",
"upgrade.minecraft.crafting_table.adjective": "Üretken",
"upgrade.minecraft.diamond_axe.adjective": "Düşen",
"upgrade.minecraft.diamond_hoe.adjective": "Çiftçi",
"upgrade.minecraft.diamond_pickaxe.adjective": "Madenci",
"upgrade.minecraft.diamond_shovel.adjective": "Kazıcı",
"upgrade.minecraft.diamond_sword.adjective": "Dövüşçü"
}

View File

@@ -160,5 +160,7 @@ class Monitor_Test {
}
thenScreenshot()
thenExecute { helper.level.dayTime = Times.NOON }
}
}

View File

@@ -53,5 +53,7 @@ class Printout_Test {
}
thenScreenshot()
thenExecute { helper.level.dayTime = Times.NOON }
}
}

View File

@@ -701,7 +701,7 @@ class Turtle_Test {
@GameTest
fun Breaks_exploding_block(context: GameTestHelper) = context.sequence {
thenOnComputer { turtle.dig(Optional.empty()) }
thenIdle(2)
thenWaitUntil { context.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) }
thenExecute {
context.assertItemEntityCountIs(ModRegistry.Items.TURTLE_NORMAL.get(), 1)
context.assertItemEntityCountIs(Items.BONE_BLOCK, 65)

View File

@@ -15,6 +15,7 @@ import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.gui.screens.TitleScreen
import net.minecraft.client.tutorial.TutorialSteps
import net.minecraft.core.BlockPos
import net.minecraft.core.registries.Registries
import net.minecraft.gametest.framework.*
import net.minecraft.server.MinecraftServer
import net.minecraft.sounds.SoundSource
@@ -74,6 +75,7 @@ object ClientTestHooks {
minecraft.options.cloudStatus().set(CloudStatus.OFF)
minecraft.options.particles().set(ParticleStatus.MINIMAL)
minecraft.options.tutorialStep = TutorialSteps.NONE
minecraft.options.pauseOnLostFocus = false
minecraft.options.renderDistance().set(6)
minecraft.options.gamma().set(1.0)
minecraft.options.getSoundSourceOptionInstance(SoundSource.MUSIC).set(0.0)
@@ -93,7 +95,7 @@ object ClientTestHooks {
LEVEL_NAME,
LevelSettings("Test Level", GameType.CREATIVE, false, Difficulty.EASY, true, rules, WorldDataConfiguration.DEFAULT),
WorldOptions(WorldOptions.randomSeed(), false, false),
) { WorldPresets.createNormalWorldDimensions(it) }
) { it.registryOrThrow(Registries.WORLD_PRESET).getOrThrow(WorldPresets.FLAT).createWorldDimensions() }
}
}
@@ -108,7 +110,20 @@ object ClientTestHooks {
val testTracker = when (val tracker = this.testTracker) {
null -> {
if (server.overworld().players().isEmpty()) return
// Place our players above where the tests will run, looking down. This at least ensures they're in the
// right area when the tests start running.
for (player in server.overworld().players()) {
player.abilities.flying = true
player.onUpdateAbilities()
player.connection.teleport(0.0, -30.0, 0.0, 0.0f, 90.0f)
player.inventory.clearContent()
}
// Wait for all chunks to be rendered.
if (!Minecraft.getInstance().isRenderingStable()) return
// Then a little more just in case.
if (startupDelay >= 0) {
// TODO: Is there a better way? Maybe set a flag when the client starts rendering?
startupDelay--

View File

@@ -130,10 +130,10 @@
],
entities: [
{blockPos: [2, 1, 0], pos: [2.5d, 1.0d, 0.5d], nbt: {AbsorptionAmount: 0.0f, Air: 300s, ArmorItems: [{}, {}, {}, {}], Attributes: [{Base: 0.699999988079071d, Name: "minecraft:generic.movement_speed"}], Brain: {memories: {}}, CustomName: '{"text":"turtle_test.render_turtle_items"}', DeathTime: 0s, DisabledSlots: 0, FallDistance: 0.0f, FallFlying: 0b, Fire: -1s, HandItems: [{}, {}], Health: 20.0f, HurtByTimestamp: 0, HurtTime: 0s, Invisible: 1b, Invulnerable: 0b, Marker: 1b, Motion: [0.0d, 0.0d, 0.0d], NoBasePlate: 0b, OnGround: 0b, PortalCooldown: 0, Pos: [125.5d, -58.0d, 53.6501934495752d], Pose: {}, Rotation: [0.14965993f, 4.066999f], ShowArms: 0b, Small: 0b, UUID: [I; -1678989666, 1780632657, -1267321893, 665166246], id: "minecraft:armor_stand"}},
{blockPos: [3, 1, 3], pos: [3.5d, 1.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [-90.0f, 0.0f], UUID: [I; 671334450, -268547745, -1360971514, -649716242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], display: {Name: '{"text":"Dinnerbone"}'}, On: 1b, RightUpgrade: "minecraft:diamond_pickaxe", RightUpgradeNbt: {Tag: {Damage: 0}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}},
{blockPos: [3, 3, 3], pos: [3.5d, 3.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [-90.0f, 0.0f], UUID: [I; 671334422, -268542345, -1362491514, -649716242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], On: 1b, RightUpgrade: "minecraft:diamond_pickaxe", RightUpgradeNbt: {Tag: {Damage: 0}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}},
{blockPos: [1, 1, 3], pos: [1.5d, 1.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [90.0f, 0.0f], UUID: [I; 625334450, -268647745, -1360971514, -649724242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], On: 1b, LeftUpgrade: "cctest:netherite_pickaxe", LeftUpgradeNbt: {Tag: {Damage: 0, Enchantments: [{id: "minecraft:efficiency", lvl: 5s}], RepairCost: 1}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}},
{blockPos: [1, 3, 3], pos: [1.5d, 3.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [90.0f, 0.0f], UUID: [I; 675334422, -268542245, -1362491514, -649755242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], display: {Name: '{"text":"Dinnerbone"}'}, On: 1b, LeftUpgrade: "cctest:netherite_pickaxe", LeftUpgradeNbt: {Tag: {Damage: 0, Enchantments: [{id: "minecraft:efficiency", lvl: 5s}], RepairCost: 1}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}}
{blockPos: [3, 1, 3], pos: [3.5d, 1.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [90.0f, 0.0f], UUID: [I; 671334450, -268547745, -1360971514, -649716242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], display: {Name: '{"text":"Dinnerbone"}'}, On: 1b, RightUpgrade: "minecraft:diamond_pickaxe", RightUpgradeNbt: {Tag: {Damage: 0}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}},
{blockPos: [3, 3, 3], pos: [3.5d, 3.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [90.0f, 0.0f], UUID: [I; 671334422, -268542345, -1362491514, -649716242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], On: 1b, RightUpgrade: "minecraft:diamond_pickaxe", RightUpgradeNbt: {Tag: {Damage: 0}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}},
{blockPos: [1, 1, 3], pos: [1.5d, 1.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [-90.0f, 0.0f], UUID: [I; 625334450, -268647745, -1360971514, -649724242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], On: 1b, LeftUpgrade: "cctest:netherite_pickaxe", LeftUpgradeNbt: {Tag: {Damage: 0, Enchantments: [{id: "minecraft:efficiency", lvl: 5s}], RepairCost: 1}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}},
{blockPos: [1, 3, 3], pos: [1.5d, 3.5d, 3.5d], nbt: {Air: 300s, FallDistance: 0.0f, Fire: 0s, Invulnerable: 0b, Motion: [0.0d, 0.0d, 0.0d], OnGround: 0b, PortalCooldown: 0, Pos: [126.5d, -57.5d, 56.5d], Rotation: [-90.0f, 0.0f], UUID: [I; 675334422, -268542245, -1362491514, -649755242], billboard: "fixed", glow_color_override: -1, height: 0.0f, id: "minecraft:item_display", interpolation_duration: 0, item: {Count: 1b, id: "computercraft:turtle_normal", tag: {ComputerId: 8, Fuel: 0, Items: [], display: {Name: '{"text":"Dinnerbone"}'}, On: 1b, LeftUpgrade: "cctest:netherite_pickaxe", LeftUpgradeNbt: {Tag: {Damage: 0, Enchantments: [{id: "minecraft:efficiency", lvl: 5s}], RepairCost: 1}}}}, item_display: "none", shadow_radius: 0.0f, shadow_strength: 1.0f, transformation: {left_rotation: [0.0f, 0.0f, 0.0f, 1.0f], right_rotation: [0.0f, 0.0f, 0.0f, 1.0f], scale: [1.0f, 1.0f, 1.0f], translation: [0.0f, 0.0f, 0.0f]}, view_range: 1.0f, width: 0.0f}}
],
palette: [
"minecraft:polished_andesite",

View File

@@ -0,0 +1,129 @@
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.api.peripheral;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
/**
* A thread-safe collection of computers.
* <p>
* This collection is intended to be used by peripherals that need to maintain a set of all attached computers.
* <p>
* It is recommended to use over Java's built-in concurrent collections (e.g. {@link CopyOnWriteArraySet} or
* {@link ConcurrentHashMap}), as {@link AttachedComputerSet} ensures that computers cannot be accessed after they are
* detached, guaranteeing that {@link NotAttachedException}s will not be thrown.
* <p>
* To ensure this, {@link AttachedComputerSet} is not directly iterable, as we cannot ensure that computers are not
* detached while the iterator is running (and so trying to use the computer would error). Instead, computers should be
* looped over using {@link #forEach(Consumer)}.
*
* <h2>Example</h2>
*
* <pre>{@code
* public class MyPeripheral implements IPeripheral {
* private final AttachedComputerSet computers = new ComputerCollection();
*
* @Override
* public void attach(IComputerAccess computer) {
* computers.add(computer);
* }
*
* @Override
* public void detach(IComputerAccess computer) {
* computers.remove(computer);
* }
* }
* }</pre>
*
* @see IComputerAccess
* @see IPeripheral#attach(IComputerAccess)
* @see IPeripheral#detach(IComputerAccess)
*/
public final class AttachedComputerSet {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final Set<IComputerAccess> computers = new HashSet<>(0);
/**
* Add a computer to this collection of computers. This should be called from
* {@link IPeripheral#attach(IComputerAccess)}.
*
* @param computer The computer to add.
*/
public void add(IComputerAccess computer) {
lock.writeLock().lock();
try {
computers.add(computer);
} finally {
lock.writeLock().unlock();
}
}
/**
* Remove a computer from this collection of computers. This should be called from
* {@link IPeripheral#detach(IComputerAccess)}.
*
* @param computer The computer to remove.
*/
public void remove(IComputerAccess computer) {
lock.writeLock().lock();
try {
computers.remove(computer);
} finally {
lock.writeLock().unlock();
}
}
/**
* Apply an action to each computer in this collection.
*
* @param action The action to apply.
*/
public void forEach(Consumer<? super IComputerAccess> action) {
lock.readLock().lock();
try {
computers.forEach(action);
} finally {
lock.readLock().unlock();
}
}
/**
* {@linkplain IComputerAccess#queueEvent(String, Object...) Queue an event} on all computers.
*
* @param event The name of the event to queue.
* @param arguments The arguments for this event.
* @see IComputerAccess#queueEvent(String, Object...)
*/
public void queueEvent(String event, @Nullable Object... arguments) {
forEach(c -> c.queueEvent(event, arguments));
}
/**
* Determine if this collection contains any computers.
* <p>
* This method is primarily intended for presentation purposes (such as rendering an icon in the UI if a computer
* is attached to your peripheral). Due to the multi-threaded nature of peripherals, it is not recommended to guard
* any logic behind this check.
* <p>
* For instance, {@code if(computers.hasComputers()) computers.queueEvent("foo");} contains a race condition, as
* there's no guarantee that any computers are still attached within the body of the if statement.
*
* @return Whether this collection is non-empty.
*/
public boolean hasComputers() {
lock.readLock().lock();
try {
return !computers.isEmpty();
} finally {
lock.readLock().unlock();
}
}
}

View File

@@ -48,8 +48,9 @@ public interface IPeripheral {
* {@code peripheral.call()}. This method can be used to keep track of which computers are attached to the
* peripheral, or to take action when attachment occurs.
* <p>
* Be aware that will be called from both the server thread and ComputerCraft Lua thread, and so must be thread-safe
* and reentrant.
* Be aware that may be called from both the server thread and ComputerCraft Lua thread, and so must be thread-safe
* and reentrant. If you need to store a list of attached computers, it is recommended you use a
* {@link AttachedComputerSet}.
*
* @param computer The interface to the computer that is being attached. Remember that multiple computers can be
* attached to a peripheral at once.
@@ -68,8 +69,9 @@ public interface IPeripheral {
* This method can be used to keep track of which computers are attached to the peripheral, or to take action when
* detachment occurs.
* <p>
* Be aware that this will be called from both the server and ComputerCraft Lua thread, and must be thread-safe
* and reentrant.
* Be aware that this may be called from both the server and ComputerCraft Lua thread, and must be thread-safe
* and reentrant. If you need to store a list of attached computers, it is recommended you use a
* {@link AttachedComputerSet}.
*
* @param computer The interface to the computer that is being detached. Remember that multiple computers can be
* attached to a peripheral at once.

View File

@@ -7,6 +7,7 @@ import cc.tweaked.gradle.getAbsolutePath
plugins {
`java-library`
`java-test-fixtures`
alias(libs.plugins.shadow)
id("cc-tweaked.kotlin-convention")
id("cc-tweaked.java-convention")
@@ -57,3 +58,22 @@ val checkChangelog by tasks.registering(cc.tweaked.gradle.CheckChangelog::class)
}
tasks.check { dependsOn(checkChangelog) }
// We configure the shadow jar to ship netty-codec and all its dependencies, relocating them under the
// dan200.computercraft.core package.
// This is used as part of the Forge build, so that our version of netty-codec is loaded under the GAME layer, and so
// has access to our jar-in-jar'ed jzlib.
tasks.shadowJar {
minimize()
dependencies {
include(dependency(libs.netty.codec.get()))
include(dependency(libs.netty.http.get()))
include(dependency(libs.netty.socks.get()))
include(dependency(libs.netty.proxy.get()))
}
for (pkg in listOf("io.netty.handler.codec", "io.netty.handler.proxy")) {
relocate(pkg, "dan200.computercraft.core.vendor.$pkg")
}
}

View File

@@ -403,21 +403,39 @@ public class OSAPI implements ILuaAPI {
* function. The format string can also be prefixed with an exclamation mark
* ({@code !}) to use UTC time instead of the server's local timezone.
* <p>
* If the format is exactly {@code *t} (optionally prefixed with {@code !}), a
* table will be returned instead. This table has fields for the year, month,
* day, hour, minute, second, day of the week, day of the year, and whether
* Daylight Savings Time is in effect. This table can be converted to a UNIX
* timestamp (days since 1 January 1970) with {@link #date}.
* If the format is exactly {@code "*t"} (or {@code "!*t"} ), a table
* representation of the timestamp will be returned instead. This table has
* fields for the year, month, day, hour, minute, second, day of the week,
* day of the year, and whether Daylight Savings Time is in effect. This
* table can be converted back to a timestamp with {@link #time(IArguments)}.
*
* @param formatA The format of the string to return. This defaults to {@code %c}, which expands to a string similar to "Sat Dec 24 16:58:00 2011".
* @param timeA The time to convert to a string. This defaults to the current time.
* @return The resulting format string.
* @param timeA The timestamp to convert to a string. This defaults to the current time.
* @return The resulting formated string, or table.
* @throws LuaException If an invalid format is passed.
* @cc.since 1.83.0
* @cc.usage Print the current date in a user-friendly string.
* <pre>{@code
* os.date("%A %d %B %Y") -- See the reference above!
* }</pre>
*
* @cc.usage Convert a timestamp to a table.
* <pre>{@code
* os.date("!*t", 1242534247)
* --[=[ {
* -- Date
* year = 2009,
* month = 5,
* day = 17,
* yday = 137,
* wday = 1,
* -- Time
* hour = 4,
* min = 24,
* sec = 7,
* isdst = false,
* } ]=]
* }</pre>
*/
@LuaFunction
public final Object date(Optional<String> formatA, Optional<Long> timeA) throws LuaException {

View File

@@ -95,11 +95,8 @@ public class CobaltLuaMachine implements ILuaMachine {
private void addAPI(LuaState state, LuaTable globals, ILuaAPI api) throws LuaError {
// Add the methods of an API to the global table
var table = wrapLuaObject(api);
if (table == null) {
LOG.warn("API {} does not provide any methods", api);
table = new LuaTable();
}
var table = new LuaTable();
if (!makeLuaObject(api, table)) LOG.warn("API {} does not provide any methods", api);
var names = api.getNames();
for (var name : names) globals.rawset(name, table);
@@ -163,13 +160,16 @@ public class CobaltLuaMachine implements ILuaMachine {
timeout.removeListener(timeoutListener);
}
@Nullable
private LuaTable wrapLuaObject(Object object) {
var table = new LuaTable();
var found = luaMethods.forEachMethod(object, (target, name, method, info) ->
/**
* Populate a table with methods from an object.
*
* @param object The object to draw methods from.
* @param table The table to fill.
* @return Whether any methods were found.
*/
private boolean makeLuaObject(Object object, LuaTable table) {
return luaMethods.forEachMethod(object, (target, name, method, info) ->
table.rawset(name, new ResultInterpreterFunction(this, method, target, context, name)));
return found ? table : null;
}
private LuaValue toValue(@Nullable Object object, @Nullable IdentityHashMap<Object, LuaValue> values) throws LuaError {
@@ -184,47 +184,35 @@ public class CobaltLuaMachine implements ILuaMachine {
return ValueFactory.valueOf(bytes);
}
// Don't share singleton values, and instead convert them to a new table.
if (LuaUtil.isSingletonCollection(object)) return new LuaTable();
// We have a more complex object, which is possibly recursive. First look up our object in the lookup map,
// and reuse it if present.
if (values == null) values = new IdentityHashMap<>(1);
var result = values.get(object);
if (result != null) return result;
var wrapped = toValueWorker(object, values);
if (wrapped == null) {
LOG.warn(Logging.JAVA_ERROR, "Received unknown type '{}', returning nil.", object.getClass().getName());
return Constants.NIL;
}
values.put(object, wrapped);
return wrapped;
}
/**
* Convert a complex Java object (such as a collection or Lua object) to a Lua value.
* <p>
* This is a worker function for {@link #toValue(Object, IdentityHashMap)}, which handles the actual construction
* of values, without reading/writing from the value map.
*
* @param object The object to convert.
* @param values The map of Java to Lua values.
* @return The converted value, or {@code null} if it could not be converted.
* @throws LuaError If the value could not be converted.
*/
private @Nullable LuaValue toValueWorker(Object object, IdentityHashMap<Object, LuaValue> values) throws LuaError {
if (object instanceof ILuaFunction) {
return new ResultInterpreterFunction(this, FUNCTION_METHOD, object, context, object.toString());
var function = new ResultInterpreterFunction(this, FUNCTION_METHOD, object, context, object.toString());
values.put(object, function);
return function;
}
if (object instanceof IDynamicLuaObject) {
LuaValue wrapped = wrapLuaObject(object);
if (wrapped == null) wrapped = new LuaTable();
return wrapped;
var table = new LuaTable();
makeLuaObject(object, table);
values.put(object, table);
return table;
}
// The following objects may be recursive. In these instances, we need to be careful to store the value *before*
// recursing, to avoid stack overflows.
if (object instanceof Map<?, ?> map) {
// Don't share singleton values, and instead convert them to a new table.
if (LuaUtil.isSingletonMap(map)) return new LuaTable();
var table = new LuaTable();
values.put(object, table);
for (var pair : map.entrySet()) {
var key = toValue(pair.getKey(), values);
var value = toValue(pair.getValue(), values);
@@ -234,7 +222,12 @@ public class CobaltLuaMachine implements ILuaMachine {
}
if (object instanceof Collection<?> objects) {
// Don't share singleton values, and instead convert them to a new table.
if (LuaUtil.isSingletonCollection(objects)) return new LuaTable();
var table = new LuaTable(objects.size(), 0);
values.put(object, table);
var i = 0;
for (var child : objects) table.rawset(++i, toValue(child, values));
return table;
@@ -242,11 +235,20 @@ public class CobaltLuaMachine implements ILuaMachine {
if (object instanceof Object[] objects) {
var table = new LuaTable(objects.length, 0);
values.put(object, table);
for (var i = 0; i < objects.length; i++) table.rawset(i + 1, toValue(objects[i], values));
return table;
}
return wrapLuaObject(object);
var table = new LuaTable();
if (makeLuaObject(object, table)) {
values.put(object, table);
return table;
}
LOG.warn(Logging.JAVA_ERROR, "Received unknown type '{}', returning nil.", object.getClass().getName());
return Constants.NIL;
}
Varargs toValues(@Nullable Object[] objects) throws LuaError {

View File

@@ -12,15 +12,13 @@ public class Palette {
private final boolean colour;
private final double[][] colours = new double[PALETTE_SIZE][3];
private final byte[][] byteColours = new byte[PALETTE_SIZE][4];
private final int[] byteColours = new int[PALETTE_SIZE];
public static final Palette DEFAULT = new Palette(true);
public Palette(boolean colour) {
this.colour = colour;
resetColours();
for (var i = 0; i < PALETTE_SIZE; i++) byteColours[i][3] = (byte) 255;
}
public void setColour(int i, double r, double g, double b) {
@@ -30,15 +28,17 @@ public class Palette {
colours[i][2] = b;
if (colour) {
byteColours[i][0] = (byte) (int) (r * 255);
byteColours[i][1] = (byte) (int) (g * 255);
byteColours[i][2] = (byte) (int) (b * 255);
byteColours[i] = packColour((int) (r * 255), (int) (g * 255), (int) (b * 255));
} else {
var grey = (byte) (int) ((r + g + b) / 3 * 255);
byteColours[i][0] = byteColours[i][1] = byteColours[i][2] = grey;
var grey = (int) ((r + g + b) / 3 * 255);
byteColours[i] = packColour(grey, grey, grey);
}
}
private static int packColour(int r, int g, int b) {
return 255 << 24 | (r & 255) << 16 | (g & 255) << 8 | b & 255;
}
public void setColour(int i, Colour colour) {
setColour(i, colour.getR(), colour.getG(), colour.getB());
}
@@ -48,26 +48,20 @@ public class Palette {
}
/**
* Get the colour as a set of RGB values suitable for rendering. Colours are automatically converted to greyscale
* Get the colour as a set of ARGB values suitable for rendering. Colours are automatically converted to greyscale
* when using a black and white palette.
* <p>
* This returns a byte array, suitable for being used directly by our terminal vertex format.
* This returns a packed 32-bit ARGB colour.
*
* @param i The colour index.
* @return The number as a tuple of bytes.
* @return The actual RGB colour.
*/
public byte[] getRenderColours(int i) {
public int getRenderColours(int i) {
return byteColours[i];
}
public void resetColour(int i) {
if (i >= 0 && i < PALETTE_SIZE) setColour(i, Colour.VALUES[i]);
}
public void resetColours() {
for (var i = 0; i < Colour.VALUES.length; i++) {
resetColour(i);
}
for (var i = 0; i < Colour.VALUES.length; i++) setColour(i, Colour.VALUES[i]);
}
public static int encodeRGB8(double[] rgb) {

View File

@@ -4,8 +4,6 @@
package dan200.computercraft.core.util;
import javax.annotation.Nullable;
public enum Colour {
BLACK(0x111111),
RED(0xcc4c4c),
@@ -30,15 +28,6 @@ public enum Colour {
return Colour.VALUES[colour];
}
@Nullable
public static Colour fromHex(int colour) {
for (var entry : VALUES) {
if (entry.getHex() == colour) return entry;
}
return null;
}
private final int hex;
private final float red, green, blue;

View File

@@ -36,7 +36,20 @@ public class LuaUtil {
* @param value The value to test.
* @return Whether this is a singleton collection.
*/
public static boolean isSingletonCollection(Object value) {
return value == EMPTY_LIST || value == EMPTY_SET || value == EMPTY_MAP;
public static boolean isSingletonCollection(Collection<?> value) {
return value == EMPTY_LIST || value == EMPTY_SET;
}
/**
* Determine whether a value is a singleton map, such as one created with {@link Map#of()}.
* <p>
* These collections are treated specially by {@link ILuaMachine} implementations: we skip sharing for them, and
* create a new table each time.
*
* @param value The value to test.
* @return Whether this is a singleton map.
*/
public static boolean isSingletonMap(Map<?, ?> value) {
return value == EMPTY_MAP;
}
}

View File

@@ -944,22 +944,21 @@ unserialiseJSON = unserialise_json
-- @since 1.31
function urlEncode(str)
expect(1, str, "string")
if str then
str = string.gsub(str, "\n", "\r\n")
str = string.gsub(str, "([^A-Za-z0-9 %-%_%.])", function(c)
local n = string.byte(c)
if n < 128 then
-- ASCII
return string.format("%%%02X", n)
else
-- Non-ASCII (encode as UTF-8)
return
string.format("%%%02X", 192 + bit32.band(bit32.arshift(n, 6), 31)) ..
string.format("%%%02X", 128 + bit32.band(n, 63))
end
end)
str = string.gsub(str, " ", "+")
end
local gsub, byte, format, band, arshift = string.gsub, string.byte, string.format, bit32.band, bit32.arshift
str = gsub(str, "\n", "\r\n")
str = gsub(str, "[^A-Za-z0-9%-%_%.]", function(c)
if c == " " then return "+" end
local n = byte(c)
if n < 128 then
-- ASCII
return format("%%%02X", n)
else
-- Non-ASCII (encode as UTF-8)
return format("%%%02X%%%02X", 192 + band(arshift(n, 6), 31), 128 + band(n, 63))
end
end)
return str
end

View File

@@ -1,3 +1,12 @@
# New features in CC: Tweaked 1.113.1
* Update Japanese translation (konumatakaki).
* Improve performance of `textutils.urlEncode`.
Several bug fixes:
* Fix overflow when converting recursive objects from Java to Lua.
* Fix websocket compression not working under Forge.
# New features in CC: Tweaked 1.113.0
* Allow placing printed pages and books in lecterns.

View File

@@ -1,11 +1,10 @@
New features in CC: Tweaked 1.113.0
New features in CC: Tweaked 1.113.1
* Allow placing printed pages and books in lecterns.
* Update Japanese translation (konumatakaki).
* Improve performance of `textutils.urlEncode`.
Several bug fixes:
* Various documentation fixes (MCJack123)
* Fix computers and turtles not being dropped when exploded with TNT.
* Fix crash when turtles are broken while mining a block.
* Fix pocket computer terminals not updating when in the off-hand.
* Fix overflow when converting recursive objects from Java to Lua.
* Fix websocket compression not working under Forge.
Type "help changelog" to see the full version history.

View File

@@ -6,8 +6,7 @@
Convert between streams of DFPWM audio data and a list of amplitudes.
DFPWM (Dynamic Filter Pulse Width Modulation) is an audio codec designed by GreaseMonkey. It's a relatively compact
format compared to raw PCM data, only using 1 bit per sample, but is simple enough to simple enough to encode and decode
in real time.
format compared to raw PCM data, only using 1 bit per sample, but is simple enough to encode and decode in real time.
Typically DFPWM audio is read from [the filesystem][`fs.ReadHandle`] or a [a web request][`http.Response`] as a string,
and converted a format suitable for [`speaker.playAudio`].

View File

@@ -202,6 +202,14 @@ describe("The os library", function()
expect(xs[1]):eq(xs[2])
end)
it("handles recursive tables", function()
local tbl = {}
tbl[1] = tbl
local xs = roundtrip(tbl)
expect(xs):eq(xs[1])
end)
it("does not preserve references in separate args", function()
-- I'm not sure I like this behaviour, but it is what CC has always done.
local tbl = {}

View File

@@ -296,6 +296,22 @@ describe("The textutils library", function()
textutils.urlEncode("")
expect.error(textutils.urlEncode, nil):eq("bad argument #1 (string expected, got nil)")
end)
it("encodes newlines", function()
expect(textutils.urlEncode("a\nb")):eq("a%0D%0Ab")
end)
it("leaves normal characters as-is", function()
expect(textutils.urlEncode("abcABC0123")):eq("abcABC0123")
end)
it("escapes spaces", function()
expect(textutils.urlEncode("a b c")):eq("a+b+c")
end)
it("escapes special characters", function()
expect(textutils.urlEncode("a%b\0\255")):eq("a%25b%00%C3%BF")
end)
end)
describe("textutils.complete", function()

View File

@@ -7,6 +7,7 @@ package dan200.computercraft.client;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.client.FabricComputerCraftAPIClient;
import dan200.computercraft.client.model.CustomModelLoader;
import dan200.computercraft.client.pocket.PocketClientTooltipComponent;
import dan200.computercraft.impl.Services;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.config.ConfigSpec;
@@ -15,6 +16,7 @@ import dan200.computercraft.shared.network.client.ClientNetworkContext;
import dan200.computercraft.shared.peripheral.modem.wired.CableBlock;
import dan200.computercraft.shared.platform.FabricConfigFile;
import dan200.computercraft.shared.platform.FabricMessageType;
import dan200.computercraft.shared.pocket.items.PocketTooltipComponent;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
@@ -22,6 +24,7 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.TooltipComponentCallback;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
import net.fabricmc.loader.api.FabricLoader;
@@ -74,6 +77,11 @@ public class ComputerCraftClient {
}
});
TooltipComponentCallback.EVENT.register(c -> {
if (c instanceof PocketTooltipComponent p) return new PocketClientTooltipComponent(p);
return null;
});
// Easier to hook in as an event than use BlockPickInteractionAware.
ClientPickBlockGatherCallback.EVENT.register((player, hit) -> {
if (hit.getType() != HitResult.Type.BLOCK) return ItemStack.EMPTY;

View File

@@ -8,6 +8,7 @@ import com.google.auto.service.AutoService;
import com.mojang.blaze3d.vertex.VertexFormat;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
import dan200.computercraft.shared.util.ARGB32;
import net.fabricmc.loader.api.FabricLoader;
import net.irisshaders.iris.api.v0.IrisApi;
import net.irisshaders.iris.api.v0.IrisTextVertexSink;
@@ -54,12 +55,8 @@ public class IrisShaderMod implements ShaderMod.Provider {
}
@Override
public void quad(float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2) {
sink.quad(x1, y1, x2, y2, z, pack(rgba[0], rgba[1], rgba[2], rgba[3]), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP);
}
private static int pack(int r, int g, int b, int a) {
return (a & 255) << 24 | (b & 255) << 16 | (g & 255) << 8 | r & 255;
public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) {
sink.quad(x1, y1, x2, y2, z, ARGB32.toABGR32(colour), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP);
}
}
}

View File

@@ -105,6 +105,10 @@ minecraft {
configurations {
minecraftLibrary { extendsFrom(minecraftEmbed.get()) }
// Move minecraftLibrary/minecraftEmbed out of implementation, and into runtimeOnly.
implementation { setExtendsFrom(extendsFrom - setOf(minecraftLibrary.get(), minecraftEmbed.get())) }
runtimeOnly { extendsFrom(minecraftLibrary.get(), minecraftEmbed.get()) }
val testMinecraftLibrary by registering {
isCanBeResolved = true
isCanBeConsumed = false
@@ -138,18 +142,11 @@ dependencies {
minecraftEmbed(libs.jzlib) {
jarJar.ranged(this, "[${libs.versions.jzlib.get()},)")
}
minecraftEmbed(libs.netty.http) {
jarJar.ranged(this, "[${libs.versions.netty.get()},)")
isTransitive = false
}
minecraftEmbed(libs.netty.socks) {
jarJar.ranged(this, "[${libs.versions.netty.get()},)")
isTransitive = false
}
minecraftEmbed(libs.netty.proxy) {
jarJar.ranged(this, "[${libs.versions.netty.get()},)")
isTransitive = false
}
// We don't jar-in-jar our additional netty dependencies (see the tasks.jarJar configuration), but still want them
// on the legacy classpath.
minecraftLibrary(libs.netty.http) { isTransitive = false }
minecraftLibrary(libs.netty.socks) { isTransitive = false }
minecraftLibrary(libs.netty.proxy) { isTransitive = false }
testFixturesApi(libs.bundles.test)
testFixturesApi(libs.bundles.kotlin)
@@ -195,9 +192,17 @@ tasks.sourcesJar {
tasks.jarJar {
finalizedBy("reobfJarJar")
archiveClassifier.set("")
duplicatesStrategy = DuplicatesStrategy.FAIL
// Include all classes from other projects except core.
val coreSources = project(":core").sourceSets["main"]
for (source in cct.sourceDirectories.get()) {
if (source.classes) from(source.sourceSet.output)
if (source.classes && source.sourceSet != coreSources) from(source.sourceSet.output)
}
// Include core separately, along with the relocated netty classes.
from(zipTree(project(":core").tasks.named("shadowJar", AbstractArchiveTask::class).map { it.archiveFile })) {
exclude("META-INF/**")
}
}

View File

@@ -7,13 +7,12 @@ package dan200.computercraft.client;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.client.turtle.RegisterTurtleModellersEvent;
import dan200.computercraft.client.model.turtle.TurtleModelLoader;
import dan200.computercraft.client.pocket.PocketClientTooltipComponent;
import dan200.computercraft.shared.pocket.items.PocketTooltipComponent;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
import net.minecraftforge.client.event.RegisterShadersEvent;
import net.minecraftforge.client.event.*;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.common.Mod;
@@ -85,4 +84,9 @@ public final class ForgeClientRegistry {
ClientRegistry.register();
event.enqueueWork(() -> ClientRegistry.registerMainThread(ItemProperties::register));
}
@SubscribeEvent
public static void onTooltipComponent(RegisterClientTooltipComponentFactoriesEvent event) {
event.register(PocketTooltipComponent.class, PocketClientTooltipComponent::new);
}
}

View File

@@ -8,6 +8,7 @@ import com.google.auto.service.AutoService;
import com.mojang.blaze3d.vertex.VertexFormat;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
import dan200.computercraft.shared.util.ARGB32;
import net.irisshaders.iris.api.v0.IrisApi;
import net.irisshaders.iris.api.v0.IrisTextVertexSink;
import net.minecraftforge.fml.ModList;
@@ -57,12 +58,8 @@ public class IrisShaderMod implements ShaderMod.Provider {
}
@Override
public void quad(float x1, float y1, float x2, float y2, float z, byte[] rgba, float u1, float v1, float u2, float v2) {
sink.quad(x1, y1, x2, y2, z, pack(rgba[0], rgba[1], rgba[2], rgba[3]), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP);
}
private static int pack(int r, int g, int b, int a) {
return (a & 255) << 24 | (b & 255) << 16 | (g & 255) << 8 | r & 255;
public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) {
sink.quad(x1, y1, x2, y2, z, ARGB32.toABGR32(colour), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP);
}
}
}

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;