Merge branch 'mc-1.20.x' into mc-1.21.x
| @@ -6,7 +6,7 @@ | |||||||
| # See https://pre-commit.com/hooks.html for more hooks | # See https://pre-commit.com/hooks.html for more hooks | ||||||
| repos: | repos: | ||||||
| - repo: https://github.com/pre-commit/pre-commit-hooks | - repo: https://github.com/pre-commit/pre-commit-hooks | ||||||
|   rev: v4.4.0 |   rev: v5.0.0 | ||||||
|   hooks: |   hooks: | ||||||
|   - id: trailing-whitespace |   - id: trailing-whitespace | ||||||
|   - id: end-of-file-fixer |   - id: end-of-file-fixer | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ neogradle.subsystems.conventions.runs.enabled=false | |||||||
|  |  | ||||||
| # Mod properties | # Mod properties | ||||||
| isUnstable=true | isUnstable=true | ||||||
| modVersion=1.115.0 | modVersion=1.115.1 | ||||||
|  |  | ||||||
| # Minecraft properties: We want to configure this here so we can read it in settings.gradle | # Minecraft properties: We want to configure this here so we can read it in settings.gradle | ||||||
| mcVersion=1.21.1 | mcVersion=1.21.1 | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ rei = "16.0.729" | |||||||
| sodium-fabric = "mc1.21-0.6.0-beta.1-fabric" | sodium-fabric = "mc1.21-0.6.0-beta.1-fabric" | ||||||
| sodium-forge = "mc1.21-0.6.0-beta.1-neoforge" | sodium-forge = "mc1.21-0.6.0-beta.1-neoforge" | ||||||
| mixinExtra = "0.3.5" | mixinExtra = "0.3.5" | ||||||
| create-forge = "0.5.1.f-33" | create-forge = "6.0.0-6" | ||||||
| create-fabric = "0.5.1-f-build.1467+mc1.20.1" | create-fabric = "0.5.1-f-build.1467+mc1.20.1" | ||||||
|  |  | ||||||
| # Testing | # Testing | ||||||
| @@ -105,7 +105,7 @@ slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } | |||||||
|  |  | ||||||
| # Minecraft mods | # Minecraft mods | ||||||
| create-fabric = { module = "com.simibubi.create:create-fabric-1.20.1", version.ref = "create-fabric" } | create-fabric = { module = "com.simibubi.create:create-fabric-1.20.1", version.ref = "create-fabric" } | ||||||
| create-forge = { module = "com.simibubi.create:create-1.20.1", version.ref = "create-forge" } | create-forge = { module = "com.simibubi.create:create-1.21.1", version.ref = "create-forge" } | ||||||
| emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" } | emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" } | ||||||
| fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" } | fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" } | ||||||
| fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fabric-loader" } | fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fabric-loader" } | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ import java.util.Map; | |||||||
|  * |  * | ||||||
|  * @param <T> The type of object that this provider can provide details for. |  * @param <T> The type of object that this provider can provide details for. | ||||||
|  * @see DetailRegistry |  * @see DetailRegistry | ||||||
|  |  * @see dan200.computercraft.api.detail An overview of the detail system. | ||||||
|  */ |  */ | ||||||
| @FunctionalInterface | @FunctionalInterface | ||||||
| public interface DetailProvider<T> { | public interface DetailProvider<T> { | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ import java.util.Map; | |||||||
|  * also in this package. |  * also in this package. | ||||||
|  * |  * | ||||||
|  * @param <T> The type of object that this registry provides details for. |  * @param <T> The type of object that this registry provides details for. | ||||||
|  |  * @see dan200.computercraft.api.detail An overview of the detail system. | ||||||
|  */ |  */ | ||||||
| @ApiStatus.NonExtendable | @ApiStatus.NonExtendable | ||||||
| public interface DetailRegistry<T> { | public interface DetailRegistry<T> { | ||||||
|   | |||||||
| @@ -17,6 +17,9 @@ public class VanillaDetailRegistries { | |||||||
|      * <p> |      * <p> | ||||||
|      * This instance's {@link DetailRegistry#getBasicDetails(Object)} is thread safe (assuming the stack is immutable) |      * This instance's {@link DetailRegistry#getBasicDetails(Object)} is thread safe (assuming the stack is immutable) | ||||||
|      * and may be called from the computer thread. |      * and may be called from the computer thread. | ||||||
|  |      * <p> | ||||||
|  |      * This does not have special handling for {@linkplain ItemStack#isEmpty() empty item stacks}, and so the returned | ||||||
|  |      * details will be an empty stack of air. Callers should generally check for empty stacks before calling this. | ||||||
|      */ |      */ | ||||||
|     public static final DetailRegistry<ItemStack> ITEM_STACK = ComputerCraftAPIService.get().getItemStackDetailRegistry(); |     public static final DetailRegistry<ItemStack> ITEM_STACK = ComputerCraftAPIService.get().getItemStackDetailRegistry(); | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | // SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers | ||||||
|  | // | ||||||
|  | // SPDX-License-Identifier: MPL-2.0 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * The detail system provides a standard way for mods to return descriptions of common game objects, such as blocks or | ||||||
|  |  * items, as well as registering additional detail to be included in those descriptions. | ||||||
|  |  * <p> | ||||||
|  |  * For instance, the built-in {@code turtle.getItemDetail()} method uses | ||||||
|  |  * {@linkplain dan200.computercraft.api.detail.VanillaDetailRegistries#ITEM_STACK in order to provide information about} | ||||||
|  |  * the selected item: | ||||||
|  |  * | ||||||
|  |  * <pre class="language language-lua">{@code | ||||||
|  |  * local item = turtle.getItemDetail(nil, true) | ||||||
|  |  * --[[ | ||||||
|  |  * item = { | ||||||
|  |  *   name = "minecraft:wheat", | ||||||
|  |  *   displayName = "Wheat", | ||||||
|  |  *   count = 1, | ||||||
|  |  *   maxCount = 64, | ||||||
|  |  *   tags = {}, | ||||||
|  |  * } | ||||||
|  |  * ]] | ||||||
|  |  * }</pre> | ||||||
|  |  * | ||||||
|  |  * <h2>Built-in detail providers</h2> | ||||||
|  |  * While you can define your own detail providers (perhaps for types from your own mod), CC comes with several built-in | ||||||
|  |  * detail registries for vanilla and mod-loader objects: | ||||||
|  |  * | ||||||
|  |  * <ul> | ||||||
|  |  *     <li>{@link dan200.computercraft.api.detail.VanillaDetailRegistries}, for vanilla objects</li> | ||||||
|  |  *     <li>{@code dan200.computercraft.api.detail.ForgeDetailRegistries} for Forge-specific objects</li> | ||||||
|  |  *     <li>{@code dan200.computercraft.api.detail.FabricDetailRegistries} for Fabric-specific objects</li> | ||||||
|  |  * </ul> | ||||||
|  |  * | ||||||
|  |  * <h2>Example: Returning details from methods</h2> | ||||||
|  |  * Here we define a {@code getHeldItem()} method for pocket computers which finds the currently held item of the player | ||||||
|  |  * and returns it to the user using {@link dan200.computercraft.api.detail.VanillaDetailRegistries#ITEM_STACK} and | ||||||
|  |  * {@link dan200.computercraft.api.detail.DetailRegistry#getDetails(java.lang.Object)}. | ||||||
|  |  * | ||||||
|  |  * {@snippet class=com.example.examplemod.ExamplePocketPeripheral region=details} | ||||||
|  |  * | ||||||
|  |  * <h2>Example: Registering custom detail registries</h2> | ||||||
|  |  * Here we define a new detail provider for items that includes the nutrition and saturation values in the returned object. | ||||||
|  |  * | ||||||
|  |  * {@snippet class=com.example.examplemod.ExampleMod region=details} | ||||||
|  |  */ | ||||||
|  | package dan200.computercraft.api.detail; | ||||||
| @@ -39,7 +39,6 @@ dependencies { | |||||||
|     compileOnly(libs.mixin) |     compileOnly(libs.mixin) | ||||||
|     compileOnly(libs.mixinExtra) |     compileOnly(libs.mixinExtra) | ||||||
|     compileOnly(libs.bundles.externalMods.common) |     compileOnly(libs.bundles.externalMods.common) | ||||||
|     compileOnly(variantOf(libs.create.forge) { classifier("slim") }) { isTransitive = false } |  | ||||||
|     clientCompileOnly(variantOf(libs.emi) { classifier("api") }) |     clientCompileOnly(variantOf(libs.emi) { classifier("api") }) | ||||||
| 
 | 
 | ||||||
|     annotationProcessorEverywhere(libs.autoService) |     annotationProcessorEverywhere(libs.autoService) | ||||||
|   | |||||||
| @@ -45,8 +45,8 @@ public class LecternPocketModel { | |||||||
|     public static final float TERM_HEIGHT = 14.0f / 32.0f; |     public static final float TERM_HEIGHT = 14.0f / 32.0f; | ||||||
| 
 | 
 | ||||||
|     // The size of the texture. The texture is 36x36, but is at 2x resolution. |     // The size of the texture. The texture is 36x36, but is at 2x resolution. | ||||||
|     private static final int TEXTURE_WIDTH = 36 / 2; |     private static final int TEXTURE_WIDTH = 48 / 2; | ||||||
|     private static final int TEXTURE_HEIGHT = 36 / 2; |     private static final int TEXTURE_HEIGHT = 48 / 2; | ||||||
| 
 | 
 | ||||||
|     private final ModelPart root; |     private final ModelPart root; | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ public class SpeakerInstance { | |||||||
|     SpeakerInstance() { |     SpeakerInstance() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void pushAudio(EncodedAudio buffer) { |     private void pushAudio(EncodedAudio buffer, float volume) { | ||||||
|         var sound = this.sound; |         var sound = this.sound; | ||||||
| 
 | 
 | ||||||
|         var stream = currentStream; |         var stream = currentStream; | ||||||
| @@ -32,18 +32,30 @@ public class SpeakerInstance { | |||||||
|         var exhausted = stream.isEmpty(); |         var exhausted = stream.isEmpty(); | ||||||
|         stream.push(buffer); |         stream.push(buffer); | ||||||
| 
 | 
 | ||||||
|         // If we've got nothing left in the buffer, enqueue an additional one just in case. |         if (sound == null) return; | ||||||
|         if (exhausted && sound != null && sound.stream == stream && stream.channel != null && stream.executor != null) { | 
 | ||||||
|  |         var volumeChanged = sound.setVolume(volume); | ||||||
|  | 
 | ||||||
|  |         if ((exhausted || volumeChanged) && sound.stream == stream && stream.channel != null && stream.executor != null) { | ||||||
|             var actualStream = sound.stream; |             var actualStream = sound.stream; | ||||||
|             stream.executor.execute(() -> { |             stream.executor.execute(() -> { | ||||||
|                 var channel = Nullability.assertNonNull(actualStream.channel); |                 var channel = Nullability.assertNonNull(actualStream.channel); | ||||||
|                 if (!channel.stopped()) channel.pumpBuffers(1); |                 if (channel.stopped()) return; | ||||||
|  | 
 | ||||||
|  |                 // If we've got nothing left in the buffer, enqueue an additional one just in case. | ||||||
|  |                 if (exhausted) channel.pumpBuffers(1); | ||||||
|  | 
 | ||||||
|  |                 // Update the attenuation if the volume has changed: SoundEngine.tickNonPaused updates the volume | ||||||
|  |                 // itself, but leaves the attenuation unchanged. We mirror the logic of SoundEngine.play here. | ||||||
|  |                 if (volumeChanged) { | ||||||
|  |                     channel.linearAttenuation(Math.max(volume, 1) * sound.getSound().getAttenuationDistance()); | ||||||
|  |                 } | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void playAudio(SpeakerPosition position, float volume, EncodedAudio buffer) { |     public void playAudio(SpeakerPosition position, float volume, EncodedAudio buffer) { | ||||||
|         pushAudio(buffer); |         pushAudio(buffer, volume); | ||||||
| 
 | 
 | ||||||
|         var soundManager = Minecraft.getInstance().getSoundManager(); |         var soundManager = Minecraft.getInstance().getSoundManager(); | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -83,4 +83,10 @@ public class SpeakerSound extends AbstractSoundInstance implements TickableSound | |||||||
|     public @Nullable AudioStream getStream() { |     public @Nullable AudioStream getStream() { | ||||||
|         return stream; |         return stream; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     boolean setVolume(float volume) { | ||||||
|  |         if (volume == this.volume) return false; | ||||||
|  |         this.volume = volume; | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,7 +3,9 @@ package com.example.examplemod; | |||||||
| import com.example.examplemod.data.TurtleUpgradeProvider; | import com.example.examplemod.data.TurtleUpgradeProvider; | ||||||
| import com.example.examplemod.peripheral.FurnacePeripheral; | import com.example.examplemod.peripheral.FurnacePeripheral; | ||||||
| import dan200.computercraft.api.ComputerCraftAPI; | import dan200.computercraft.api.ComputerCraftAPI; | ||||||
|  | import dan200.computercraft.api.detail.VanillaDetailRegistries; | ||||||
| import dan200.computercraft.api.upgrades.UpgradeType; | import dan200.computercraft.api.upgrades.UpgradeType; | ||||||
|  | import net.minecraft.core.component.DataComponents; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Our example mod, containing the various things we register. |  * Our example mod, containing the various things we register. | ||||||
| @@ -34,6 +36,16 @@ public final class ExampleMod { | |||||||
|         ComputerCraftAPI.registerGenericSource(new FurnacePeripheral()); |         ComputerCraftAPI.registerGenericSource(new FurnacePeripheral()); | ||||||
|         // @end region=generic_source |         // @end region=generic_source | ||||||
| 
 | 
 | ||||||
|  |         // @start region=details | ||||||
|  |         VanillaDetailRegistries.ITEM_STACK.addProvider((out, stack) -> { | ||||||
|  |             var food = stack.get(DataComponents.FOOD); | ||||||
|  |             if (food == null) return; | ||||||
|  | 
 | ||||||
|  |             out.put("saturation", food.saturation()); | ||||||
|  |             out.put("nutrition", food.nutrition()); | ||||||
|  |         }); | ||||||
|  |         // @end region=details | ||||||
|  | 
 | ||||||
|         ExampleAPI.register(); |         ExampleAPI.register(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,49 @@ | |||||||
|  | package com.example.examplemod; | ||||||
|  | 
 | ||||||
|  | import dan200.computercraft.api.detail.DetailRegistry; | ||||||
|  | import dan200.computercraft.api.detail.VanillaDetailRegistries; | ||||||
|  | import dan200.computercraft.api.lua.LuaFunction; | ||||||
|  | import dan200.computercraft.api.peripheral.IPeripheral; | ||||||
|  | import dan200.computercraft.api.pocket.IPocketAccess; | ||||||
|  | import net.minecraft.world.InteractionHand; | ||||||
|  | import net.minecraft.world.entity.LivingEntity; | ||||||
|  | import org.jspecify.annotations.Nullable; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An example peripheral for pocket computers. This currently doesn't have an associated upgrade — it mostly exists to | ||||||
|  |  * demonstrate other functionality. | ||||||
|  |  */ | ||||||
|  | public class ExamplePocketPeripheral implements IPeripheral { | ||||||
|  |     private final IPocketAccess pocket; | ||||||
|  | 
 | ||||||
|  |     public ExamplePocketPeripheral(IPocketAccess pocket) { | ||||||
|  |         this.pocket = pocket; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getType() { | ||||||
|  |         return "example"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * An example of using {@linkplain DetailRegistry detail registries} to get the current player's held item. | ||||||
|  |      * | ||||||
|  |      * @return The item details, or {@code null} if the player is not holding an item. | ||||||
|  |      */ | ||||||
|  |     // @start region=details | ||||||
|  |     @LuaFunction(mainThread = true) | ||||||
|  |     public final @Nullable Map<String, ?> getHeldItem() { | ||||||
|  |         if (!(pocket.getEntity() instanceof LivingEntity entity)) return null; | ||||||
|  | 
 | ||||||
|  |         var heldItem = entity.getItemInHand(InteractionHand.MAIN_HAND); | ||||||
|  |         return heldItem.isEmpty() ? null : VanillaDetailRegistries.ITEM_STACK.getDetails(heldItem); | ||||||
|  |     } | ||||||
|  |     // @end region=details | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(@Nullable IPeripheral other) { | ||||||
|  |         return other instanceof ExamplePocketPeripheral o && pocket == o.pocket; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -27,9 +27,9 @@ public final class ExternalModTags { | |||||||
|         /** |         /** | ||||||
|          * Create's "brittle" tag, used to determine if this block needs to be moved before its neighbours. |          * Create's "brittle" tag, used to determine if this block needs to be moved before its neighbours. | ||||||
|          * |          * | ||||||
|          * @see com.simibubi.create.content.contraptions.BlockMovementChecks#isBrittle(BlockState) |          * @see com.simibubi.create.api.contraption.BlockMovementChecks#isBrittle(BlockState) | ||||||
|          */ |          */ | ||||||
|         public static final TagKey<Block> CREATE_BRITTLE = make(CreateIntegration.ID, "brittle"); |         public static final TagKey<Block> CREATE_BRITTLE = make("create", "brittle"); | ||||||
| 
 | 
 | ||||||
|         private static TagKey<Block> make(String mod, String name) { |         private static TagKey<Block> make(String mod, String name) { | ||||||
|             return TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(mod, name)); |             return TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(mod, name)); | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| { | { | ||||||
|     "argument.computercraft.argument_expected": "Parameter erwartet", |     "argument.computercraft.argument_expected": "Parameter erwartet", | ||||||
|  |     "argument.computercraft.computer.distance": "Entfernung zur Entität", | ||||||
|     "argument.computercraft.computer.family": "Computer familie", |     "argument.computercraft.computer.family": "Computer familie", | ||||||
|     "argument.computercraft.computer.id": "Computer ID", |     "argument.computercraft.computer.id": "Computer ID", | ||||||
|     "argument.computercraft.computer.instance": "einzigartige Instanz ID", |     "argument.computercraft.computer.instance": "einzigartige Instanz ID", | ||||||
| @@ -98,6 +99,7 @@ | |||||||
|     "gui.computercraft.config.http.bandwidth.tooltip": "Limitiert die Bandbreite der Computer.", |     "gui.computercraft.config.http.bandwidth.tooltip": "Limitiert die Bandbreite der Computer.", | ||||||
|     "gui.computercraft.config.http.enabled": "HTTP-API aktivieren", |     "gui.computercraft.config.http.enabled": "HTTP-API aktivieren", | ||||||
|     "gui.computercraft.config.http.max_requests": "Maximale Anzahl gleichzeitiger Anfragen", |     "gui.computercraft.config.http.max_requests": "Maximale Anzahl gleichzeitiger Anfragen", | ||||||
|  |     "gui.computercraft.config.http.max_requests.tooltip": "Die Anzahl der http Anfragen, die ein Computer gleichzeitig machen kann. Zusätzliche Anfragen werden der Warteschlange hinzugefügt und nach den laufenden Anfragen gesendet. Für unendlich auf 0 setzen.", | ||||||
|     "gui.computercraft.config.http.max_websockets": "Maximale Anzahl gleichzeitiger Websockets", |     "gui.computercraft.config.http.max_websockets": "Maximale Anzahl gleichzeitiger Websockets", | ||||||
|     "gui.computercraft.config.http.max_websockets.tooltip": "Die Anzahl der Websockets die ein Computer gleichzeitig öffnen kann.", |     "gui.computercraft.config.http.max_websockets.tooltip": "Die Anzahl der Websockets die ein Computer gleichzeitig öffnen kann.", | ||||||
|     "gui.computercraft.config.http.proxy": "Proxy", |     "gui.computercraft.config.http.proxy": "Proxy", | ||||||
| @@ -114,6 +116,7 @@ | |||||||
|     "gui.computercraft.config.log_computer_errors": "Computerfehler loggen", |     "gui.computercraft.config.log_computer_errors": "Computerfehler loggen", | ||||||
|     "gui.computercraft.config.maximum_open_files": "Maximalanzahl an gleichzeitig offenen Dateien je Computer", |     "gui.computercraft.config.maximum_open_files": "Maximalanzahl an gleichzeitig offenen Dateien je Computer", | ||||||
|     "gui.computercraft.config.maximum_open_files.tooltip": "Legen Sie fest, wie viele Dateien gleichzeitig geöffnet werden können. Setzen Sie auf 0 für unbegrenzt.", |     "gui.computercraft.config.maximum_open_files.tooltip": "Legen Sie fest, wie viele Dateien gleichzeitig geöffnet werden können. Setzen Sie auf 0 für unbegrenzt.", | ||||||
|  |     "gui.computercraft.config.monitor_distance": "Monitordistanz", | ||||||
|     "gui.computercraft.config.peripheral": "Peripheriegeräte", |     "gui.computercraft.config.peripheral": "Peripheriegeräte", | ||||||
|     "gui.computercraft.config.peripheral.command_block_enabled": "Befehlsblöcke als Peripheriegerät erlauben", |     "gui.computercraft.config.peripheral.command_block_enabled": "Befehlsblöcke als Peripheriegerät erlauben", | ||||||
|     "gui.computercraft.config.peripheral.command_block_enabled.tooltip": "Befehlsblock Peripherie Unterstützung aktivieren", |     "gui.computercraft.config.peripheral.command_block_enabled.tooltip": "Befehlsblock Peripherie Unterstützung aktivieren", | ||||||
|   | |||||||
| @@ -1,8 +1,14 @@ | |||||||
| { | { | ||||||
|     "argument.computercraft.argument_expected": "Argument attendu", |     "argument.computercraft.argument_expected": "Argument attendu", | ||||||
|  |     "argument.computercraft.computer.distance": "Distance jusqu'à l'entité", | ||||||
|  |     "argument.computercraft.computer.family": "Famille d'ordinateurs", | ||||||
|  |     "argument.computercraft.computer.id": "ID de l'ordinateur", | ||||||
|  |     "argument.computercraft.computer.instance": "ID unique de l'instance", | ||||||
|  |     "argument.computercraft.computer.label": "Étiquette de l'ordinateur", | ||||||
|     "argument.computercraft.computer.many_matching": "Plusieurs ordinateurs correspondent à '%s' (instances %s)", |     "argument.computercraft.computer.many_matching": "Plusieurs ordinateurs correspondent à '%s' (instances %s)", | ||||||
|     "argument.computercraft.computer.no_matching": "Pas d'ordinateurs correspondant à '%s'", |     "argument.computercraft.computer.no_matching": "Pas d'ordinateurs correspondant à '%s'", | ||||||
|     "argument.computercraft.tracking_field.no_field": "Champ '%s' inconnu", |     "argument.computercraft.tracking_field.no_field": "Champ '%s' inconnu", | ||||||
|  |     "argument.computercraft.unknown_computer_family": "Famille d'ordinateur '%s ' inconnue", | ||||||
|     "block.computercraft.cable": "Câble réseau", |     "block.computercraft.cable": "Câble réseau", | ||||||
|     "block.computercraft.computer_advanced": "Ordinateur Avancé", |     "block.computercraft.computer_advanced": "Ordinateur Avancé", | ||||||
|     "block.computercraft.computer_command": "Ordinateur de commande", |     "block.computercraft.computer_command": "Ordinateur de commande", | ||||||
| @@ -11,6 +17,7 @@ | |||||||
|     "block.computercraft.monitor_advanced": "Moniteur Avancé", |     "block.computercraft.monitor_advanced": "Moniteur Avancé", | ||||||
|     "block.computercraft.monitor_normal": "Moniteur", |     "block.computercraft.monitor_normal": "Moniteur", | ||||||
|     "block.computercraft.printer": "Imprimante", |     "block.computercraft.printer": "Imprimante", | ||||||
|  |     "block.computercraft.redstone_relay": "Relais de Redstone", | ||||||
|     "block.computercraft.speaker": "Haut-parleur", |     "block.computercraft.speaker": "Haut-parleur", | ||||||
|     "block.computercraft.turtle_advanced": "Tortue Avancée", |     "block.computercraft.turtle_advanced": "Tortue Avancée", | ||||||
|     "block.computercraft.turtle_advanced.upgraded": "Tortue %s Avancée", |     "block.computercraft.turtle_advanced.upgraded": "Tortue %s Avancée", | ||||||
| @@ -137,16 +144,22 @@ | |||||||
|     "gui.computercraft.config.term_sizes": "Tailles de terminal", |     "gui.computercraft.config.term_sizes": "Tailles de terminal", | ||||||
|     "gui.computercraft.config.term_sizes.computer": "Ordinateur", |     "gui.computercraft.config.term_sizes.computer": "Ordinateur", | ||||||
|     "gui.computercraft.config.term_sizes.computer.height": "Hauteur du terminal", |     "gui.computercraft.config.term_sizes.computer.height": "Hauteur du terminal", | ||||||
|  |     "gui.computercraft.config.term_sizes.computer.height.tooltip": "Hauteur du terminal de l'ordinateur", | ||||||
|     "gui.computercraft.config.term_sizes.computer.tooltip": "Taille du terminal des ordinateurs.", |     "gui.computercraft.config.term_sizes.computer.tooltip": "Taille du terminal des ordinateurs.", | ||||||
|     "gui.computercraft.config.term_sizes.computer.width": "Largeur du terminal", |     "gui.computercraft.config.term_sizes.computer.width": "Largeur du terminal", | ||||||
|  |     "gui.computercraft.config.term_sizes.computer.width.tooltip": "Largeur du terminal de l'ordinateur", | ||||||
|     "gui.computercraft.config.term_sizes.monitor": "Moniteur", |     "gui.computercraft.config.term_sizes.monitor": "Moniteur", | ||||||
|     "gui.computercraft.config.term_sizes.monitor.height": "Hauteur maximale du moniteur", |     "gui.computercraft.config.term_sizes.monitor.height": "Hauteur maximale du moniteur", | ||||||
|  |     "gui.computercraft.config.term_sizes.monitor.height.tooltip": "Hauteur maximale des moniteurs", | ||||||
|     "gui.computercraft.config.term_sizes.monitor.tooltip": "Taille maximale des moniteurs (en blocs).", |     "gui.computercraft.config.term_sizes.monitor.tooltip": "Taille maximale des moniteurs (en blocs).", | ||||||
|     "gui.computercraft.config.term_sizes.monitor.width": "Largeur maximale du moniteur", |     "gui.computercraft.config.term_sizes.monitor.width": "Largeur maximale du moniteur", | ||||||
|  |     "gui.computercraft.config.term_sizes.monitor.width.tooltip": "Largeur maximale des moniteurs", | ||||||
|     "gui.computercraft.config.term_sizes.pocket_computer": "Ordinateur de poche", |     "gui.computercraft.config.term_sizes.pocket_computer": "Ordinateur de poche", | ||||||
|     "gui.computercraft.config.term_sizes.pocket_computer.height": "Hauteur du terminal", |     "gui.computercraft.config.term_sizes.pocket_computer.height": "Hauteur du terminal", | ||||||
|  |     "gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "Hauteur du terminal de l'ordinateur de poche", | ||||||
|     "gui.computercraft.config.term_sizes.pocket_computer.tooltip": "Taille du terminal des ordinateurs de poche.", |     "gui.computercraft.config.term_sizes.pocket_computer.tooltip": "Taille du terminal des ordinateurs de poche.", | ||||||
|     "gui.computercraft.config.term_sizes.pocket_computer.width": "Largeur du terminal", |     "gui.computercraft.config.term_sizes.pocket_computer.width": "Largeur du terminal", | ||||||
|  |     "gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "Largeur du terminal de l'ordinateur de poche", | ||||||
|     "gui.computercraft.config.term_sizes.tooltip": "Configure la taille des différents terminaux de l'ordinateur.\nLes terminaux plus grands nécessitent plus de bande passante, réglez donc avec précaution.", |     "gui.computercraft.config.term_sizes.tooltip": "Configure la taille des différents terminaux de l'ordinateur.\nLes terminaux plus grands nécessitent plus de bande passante, réglez donc avec précaution.", | ||||||
|     "gui.computercraft.config.turtle": "Tortues", |     "gui.computercraft.config.turtle": "Tortues", | ||||||
|     "gui.computercraft.config.turtle.advanced_fuel_limit": "Limite de carburant par Tortue Avancée", |     "gui.computercraft.config.turtle.advanced_fuel_limit": "Limite de carburant par Tortue Avancée", | ||||||
| @@ -192,6 +205,8 @@ | |||||||
|     "item.computercraft.treasure_disk": "Disquette", |     "item.computercraft.treasure_disk": "Disquette", | ||||||
|     "itemGroup.computercraft": "ComputerCraft", |     "itemGroup.computercraft": "ComputerCraft", | ||||||
|     "tag.item.computercraft.computer": "Ordinateurs", |     "tag.item.computercraft.computer": "Ordinateurs", | ||||||
|  |     "tag.item.computercraft.monitor": "Moniteurs", | ||||||
|  |     "tag.item.computercraft.turtle": "Tortues", | ||||||
|     "tag.item.computercraft.wired_modem": "Modems câblés", |     "tag.item.computercraft.wired_modem": "Modems câblés", | ||||||
|     "tracking_field.computercraft.avg": "%s (moyenne)", |     "tracking_field.computercraft.avg": "%s (moyenne)", | ||||||
|     "tracking_field.computercraft.computer_tasks.name": "Tâches", |     "tracking_field.computercraft.computer_tasks.name": "Tâches", | ||||||
| @@ -200,6 +215,7 @@ | |||||||
|     "tracking_field.computercraft.http_download.name": "Téléchargement HTTP", |     "tracking_field.computercraft.http_download.name": "Téléchargement HTTP", | ||||||
|     "tracking_field.computercraft.http_requests.name": "Requêtes HTTP", |     "tracking_field.computercraft.http_requests.name": "Requêtes HTTP", | ||||||
|     "tracking_field.computercraft.http_upload.name": "Publication HTTP", |     "tracking_field.computercraft.http_upload.name": "Publication HTTP", | ||||||
|  |     "tracking_field.computercraft.java_allocation.name": "Allocations Java", | ||||||
|     "tracking_field.computercraft.max": "%s (max)", |     "tracking_field.computercraft.max": "%s (max)", | ||||||
|     "tracking_field.computercraft.peripheral.name": "Appels aux périphériques", |     "tracking_field.computercraft.peripheral.name": "Appels aux périphériques", | ||||||
|     "tracking_field.computercraft.server_tasks.name": "Tâches du serveur", |     "tracking_field.computercraft.server_tasks.name": "Tâches du serveur", | ||||||
|   | |||||||
| Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 155 B | 
| Before Width: | Height: | Size: 179 B After Width: | Height: | Size: 140 B | 
| Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 120 B | 
| Before Width: | Height: | Size: 92 B After Width: | Height: | Size: 96 B | 
| Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 155 B | 
| @@ -1,3 +1,13 @@ | |||||||
|  | # New features in CC: Tweaked 1.115.1 | ||||||
|  | 
 | ||||||
|  | * Update various translations (cyb3r, kevk2156, teamer337, yakku). | ||||||
|  | * Support Fabric's item lookup API for registering media providers. | ||||||
|  | 
 | ||||||
|  | Several bug fixes: | ||||||
|  | * Fix crashes on Create 6.0 (ellellie). | ||||||
|  | * Fix `speaker.playAudio` not updating speaker volume. | ||||||
|  | * Resize pocket lectern textures to fix issues with generating mipmaps. | ||||||
|  | 
 | ||||||
| # New features in CC: Tweaked 1.115.0 | # New features in CC: Tweaked 1.115.0 | ||||||
| 
 | 
 | ||||||
| * Support placing pocket computers on lecterns. | * Support placing pocket computers on lecterns. | ||||||
|   | |||||||
| @@ -1,12 +1,11 @@ | |||||||
| New features in CC: Tweaked 1.115.0 | New features in CC: Tweaked 1.115.1 | ||||||
| 
 | 
 | ||||||
| * Support placing pocket computers on lecterns. | * Update various translations (cyb3r, kevk2156, teamer337, yakku). | ||||||
| * Suggest alternative table keys on `nil` errors. | * Support Fabric's item lookup API for registering media providers. | ||||||
| * Errors from inside `parallel` functions now have source information attached. |  | ||||||
| * Expose printout contents to the Java API. |  | ||||||
| * Add support for MoreRed bundled cables. |  | ||||||
| 
 | 
 | ||||||
| Several bug fixes: | Several bug fixes: | ||||||
| * Ignore unrepresentable characters in `char`/`paste` events. | * Fix crashes on Create 6.0 (ellellie). | ||||||
|  | * Fix `speaker.playAudio` not updating speaker volume. | ||||||
|  | * Resize pocket lectern textures to fix issues with generating mipmaps. | ||||||
| 
 | 
 | ||||||
| Type "help changelog" to see the full version history. | Type "help changelog" to see the full version history. | ||||||
|   | |||||||
| @@ -160,7 +160,7 @@ dependencies { | |||||||
|     clientCompileOnly(variantOf(libs.emi) { classifier("api") }) |     clientCompileOnly(variantOf(libs.emi) { classifier("api") }) | ||||||
|     compileOnly(libs.bundles.externalMods.forge.compile) |     compileOnly(libs.bundles.externalMods.forge.compile) | ||||||
|     clientRuntimeOnly(libs.bundles.externalMods.forge.runtime) |     clientRuntimeOnly(libs.bundles.externalMods.forge.runtime) | ||||||
|     compileOnly(variantOf(libs.create.forge) { classifier("slim") }) { isTransitive = false } |     compileOnly(libs.create.forge) { isTransitive = false } | ||||||
| 
 | 
 | ||||||
|     // Depend on our other projects. |     // Depend on our other projects. | ||||||
|     "localImplementation"(project(":core")) |     "localImplementation"(project(":core")) | ||||||
|   | |||||||
| @@ -0,0 +1,34 @@ | |||||||
|  | // SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers | ||||||
|  | // | ||||||
|  | // SPDX-License-Identifier: MPL-2.0 | ||||||
|  | 
 | ||||||
|  | package dan200.computercraft.shared.integration; | ||||||
|  | 
 | ||||||
|  | import com.simibubi.create.api.contraption.BlockMovementChecks; | ||||||
|  | import com.simibubi.create.api.contraption.BlockMovementChecks.CheckResult; | ||||||
|  | import dan200.computercraft.shared.peripheral.modem.wired.CableBlock; | ||||||
|  | import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemBlock; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Integration with Create. | ||||||
|  |  */ | ||||||
|  | public final class CreateIntegration { | ||||||
|  |     public static final String ID = "create"; | ||||||
|  | 
 | ||||||
|  |     private CreateIntegration() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void setup() { | ||||||
|  |         // Allow modems to be treated as "attached" to their adjacent block. | ||||||
|  |         BlockMovementChecks.registerAttachedCheck((state, world, pos, direction) -> { | ||||||
|  |             var block = state.getBlock(); | ||||||
|  |             if (block instanceof WirelessModemBlock) { | ||||||
|  |                 return CheckResult.of(state.getValue(WirelessModemBlock.FACING) == direction); | ||||||
|  |             } else if (block instanceof CableBlock) { | ||||||
|  |                 return CheckResult.of(state.getValue(CableBlock.MODEM).getFacing() == direction); | ||||||
|  |             } else { | ||||||
|  |                 return CheckResult.PASS; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
 Jonathan Coates
					Jonathan Coates