Merge branch 'mc-1.20.x' into mc-1.20.y
3
.github/workflows/make-doc.yml
vendored
@ -3,8 +3,7 @@ name: Build documentation
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- mc-1.19.x
|
||||
- mc-1.20.x
|
||||
- mc-*
|
||||
|
||||
jobs:
|
||||
make_doc:
|
||||
|
@ -94,9 +94,8 @@ sourceSets.all {
|
||||
check("InlineMeSuggester", CheckSeverity.OFF) // Minecraft uses @Deprecated liberally
|
||||
// Too many false positives right now. Maybe we need an indirection for it later on.
|
||||
check("ReferenceEquality", CheckSeverity.OFF)
|
||||
check("UnusedVariable", CheckSeverity.OFF) // Too many false positives with records.
|
||||
check("EnumOrdinal", CheckSeverity.OFF) // For now. We could replace most of these with EnumMap.
|
||||
check("OperatorPrecedence", CheckSeverity.OFF) // For now.
|
||||
check("AlreadyChecked", CheckSeverity.OFF) // Seems to be broken?
|
||||
check("NonOverridingEquals", CheckSeverity.OFF) // Peripheral.equals makes this hard to avoid
|
||||
check("FutureReturnValueIgnored", CheckSeverity.OFF) // Too many false positives with Netty
|
||||
|
||||
|
@ -225,12 +225,12 @@ abstract class CCTweakedExtension(
|
||||
* where possible.
|
||||
*/
|
||||
fun downloadFile(label: String, url: String): File {
|
||||
val url = URI(url)
|
||||
val path = File(url.path)
|
||||
val uri = URI(url)
|
||||
val path = File(uri.path)
|
||||
|
||||
project.repositories.ivy {
|
||||
name = label
|
||||
setUrl(URI(url.scheme, url.userInfo, url.host, url.port, path.parent, null, null))
|
||||
setUrl(URI(uri.scheme, uri.userInfo, uri.host, uri.port, path.parent, null, null))
|
||||
patternLayout {
|
||||
artifact("[artifact].[ext]")
|
||||
}
|
||||
|
@ -98,7 +98,6 @@ abstract class MergeTrees : DefaultTask() {
|
||||
}
|
||||
|
||||
val sharedFiles = files.entries.asSequence().filter { (_, v) -> v.found == sources.size }.map { (k, _) -> k }.toList()
|
||||
println(sharedFiles)
|
||||
|
||||
// Copy shared files to the common directory
|
||||
fsOperations.sync {
|
||||
|
@ -10,7 +10,7 @@ kotlin.jvm.target.validation.mode=error
|
||||
|
||||
# Mod properties
|
||||
isUnstable=true
|
||||
modVersion=1.110.3
|
||||
modVersion=1.111.0
|
||||
|
||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||
mcVersion=1.20.6
|
||||
|
@ -58,7 +58,7 @@ jmh = "1.37"
|
||||
cctJavadoc = "1.8.2"
|
||||
checkstyle = "10.14.1"
|
||||
curseForgeGradle = "1.1.18"
|
||||
errorProne-core = "2.23.0"
|
||||
errorProne-core = "2.27.0"
|
||||
errorProne-plugin = "3.1.0"
|
||||
fabric-loom = "1.6.7"
|
||||
githubRelease = "2.5.2"
|
||||
|
@ -129,3 +129,5 @@ val runData by tasks.registering(MergeTrees::class) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(GenerateModuleMetadata::class).configureEach { isEnabled = false }
|
||||
|
@ -27,7 +27,6 @@ import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
@ -48,8 +47,6 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
||||
*/
|
||||
private static final float MARGIN = (float) (MonitorBlockEntity.RENDER_MARGIN * 1.1);
|
||||
|
||||
private static final Matrix3f IDENTITY_NORMAL = new Matrix3f().identity();
|
||||
|
||||
private static @Nullable ByteBuffer backingBuffer;
|
||||
|
||||
private static long lastFrame = -1;
|
||||
|
@ -1 +1,12 @@
|
||||
{"parent": "computercraft:block/turtle_base", "textures": {"texture": "computercraft:block/turtle_advanced"}}
|
||||
{
|
||||
"parent": "computercraft:block/turtle_base",
|
||||
"textures": {
|
||||
"back": "computercraft:block/turtle_advanced_back",
|
||||
"backpack": "computercraft:block/turtle_advanced_backpack",
|
||||
"bottom": "computercraft:block/turtle_advanced_bottom",
|
||||
"front": "computercraft:block/turtle_advanced_front",
|
||||
"left": "computercraft:block/turtle_advanced_left",
|
||||
"right": "computercraft:block/turtle_advanced_right",
|
||||
"top": "computercraft:block/turtle_advanced_top"
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,12 @@
|
||||
{"parent": "computercraft:block/turtle_base", "textures": {"texture": "computercraft:block/turtle_normal"}}
|
||||
{
|
||||
"parent": "computercraft:block/turtle_base",
|
||||
"textures": {
|
||||
"back": "computercraft:block/turtle_normal_back",
|
||||
"backpack": "computercraft:block/turtle_normal_backpack",
|
||||
"bottom": "computercraft:block/turtle_normal_bottom",
|
||||
"front": "computercraft:block/turtle_normal_front",
|
||||
"left": "computercraft:block/turtle_normal_left",
|
||||
"right": "computercraft:block/turtle_normal_right",
|
||||
"top": "computercraft:block/turtle_normal_top"
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,9 @@ import static net.minecraft.data.models.model.TextureMapping.getBlockTexture;
|
||||
|
||||
class BlockModelProvider {
|
||||
private static final TextureSlot CURSOR = TextureSlot.create("cursor");
|
||||
private static final TextureSlot LEFT = TextureSlot.create("left");
|
||||
private static final TextureSlot RIGHT = TextureSlot.create("right");
|
||||
private static final TextureSlot BACKPACK = TextureSlot.create("backpack");
|
||||
|
||||
private static final ModelTemplate COMPUTER_ON = new ModelTemplate(
|
||||
Optional.of(new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/computer_on")),
|
||||
@ -58,7 +61,7 @@ class BlockModelProvider {
|
||||
private static final ModelTemplate TURTLE = new ModelTemplate(
|
||||
Optional.of(new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_base")),
|
||||
Optional.empty(),
|
||||
TextureSlot.TEXTURE
|
||||
TextureSlot.FRONT, TextureSlot.BACK, TextureSlot.TOP, TextureSlot.BOTTOM, LEFT, RIGHT, BACKPACK
|
||||
);
|
||||
private static final ModelTemplate TURTLE_UPGRADE_LEFT = new ModelTemplate(
|
||||
Optional.of(new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_upgrade_base_left")),
|
||||
@ -167,7 +170,16 @@ class BlockModelProvider {
|
||||
}
|
||||
|
||||
private static void registerTurtle(BlockModelGenerators generators, TurtleBlock block) {
|
||||
var model = TURTLE.create(block, TextureMapping.defaultTexture(block), generators.modelOutput);
|
||||
var model = TURTLE.create(block, new TextureMapping()
|
||||
.put(TextureSlot.FRONT, getBlockTexture(block, "_front"))
|
||||
.put(TextureSlot.BACK, getBlockTexture(block, "_back"))
|
||||
.put(TextureSlot.TOP, getBlockTexture(block, "_top"))
|
||||
.put(TextureSlot.BOTTOM, getBlockTexture(block, "_bottom"))
|
||||
.put(LEFT, getBlockTexture(block, "_left"))
|
||||
.put(RIGHT, getBlockTexture(block, "_right"))
|
||||
.put(BACKPACK, getBlockTexture(block, "_backpack")),
|
||||
generators.modelOutput
|
||||
);
|
||||
generators.blockStateOutput.accept(
|
||||
MultiVariantGenerator.multiVariant(block, Variant.variant().with(VariantProperties.MODEL, model))
|
||||
.with(createHorizontalFacingDispatch())
|
||||
|
@ -253,7 +253,6 @@ public record ComputerSelector(
|
||||
}
|
||||
|
||||
private static final class Builder {
|
||||
private OptionalInt instanceId = OptionalInt.empty();
|
||||
private @Nullable UUID instanceUuid = null;
|
||||
private OptionalInt computerId = OptionalInt.empty();
|
||||
private @Nullable String label;
|
||||
|
@ -5,16 +5,13 @@
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.annotations.ForgeOverride;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.common.IBundledRedstoneBlock;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import dan200.computercraft.shared.platform.RegistryEntry;
|
||||
import dan200.computercraft.shared.util.BlockEntityHelpers;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
@ -34,8 +31,6 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntity> extends HorizontalDirectionalBlock implements IBundledRedstoneBlock, EntityBlock {
|
||||
private static final ResourceLocation DROP = new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer");
|
||||
|
||||
protected final RegistryEntry<BlockEntityType<T>> type;
|
||||
private final BlockEntityTicker<T> serverTicker = (level, pos, state, computer) -> computer.serverTick();
|
||||
|
||||
@ -154,12 +149,6 @@ public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntit
|
||||
return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) {
|
||||
return level.getBlockEntity(pos) instanceof AbstractComputerBlockEntity computer ? computer : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <U extends BlockEntity> BlockEntityTicker<U> getTicker(Level level, BlockState state, BlockEntityType<U> type) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
package dan200.computercraft.shared.media.items;
|
||||
|
||||
import dan200.computercraft.api.media.IMedia;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.RecordItem;
|
||||
@ -13,7 +12,7 @@ import net.minecraft.world.item.RecordItem;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* An implementation of IMedia for ItemRecords.
|
||||
* An implementation of {@link IMedia} for {@link RecordItem}.
|
||||
*/
|
||||
public final class RecordMedia implements IMedia {
|
||||
public static final RecordMedia INSTANCE = new RecordMedia();
|
||||
@ -29,16 +28,12 @@ public final class RecordMedia implements IMedia {
|
||||
@Override
|
||||
public @Nullable String getAudioTitle(ItemStack stack) {
|
||||
var item = stack.getItem();
|
||||
if (!(item instanceof RecordItem)) return null;
|
||||
|
||||
return Component.translatable(item.getDescriptionId() + ".desc").getString();
|
||||
return item instanceof RecordItem record ? record.getDisplayName().getString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SoundEvent getAudio(ItemStack stack) {
|
||||
var item = stack.getItem();
|
||||
if (!(item instanceof RecordItem)) return null;
|
||||
|
||||
return ((RecordItem) item).getSound();
|
||||
return item instanceof RecordItem record ? record.getSound() : null;
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ public final class IDAssigner {
|
||||
|
||||
private final Path idFile;
|
||||
private final Path newIdFile;
|
||||
private boolean atomicMove = true;
|
||||
private @Nullable Map<String, Integer> ids;
|
||||
|
||||
public IDAssigner(Path path) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import com.google.errorprone.annotations.Keep;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ChunkLevel;
|
||||
@ -132,6 +133,7 @@ public final class TickScheduler {
|
||||
/**
|
||||
* The current state of this token.
|
||||
*/
|
||||
@Keep
|
||||
private volatile State $state = State.IDLE;
|
||||
|
||||
public Token(BlockEntity owner) {
|
||||
|
@ -218,5 +218,18 @@
|
||||
"upgrade.minecraft.diamond_hoe.adjective": "Contadina",
|
||||
"upgrade.minecraft.diamond_pickaxe.adjective": "Minatrice",
|
||||
"upgrade.minecraft.diamond_shovel.adjective": "Scavatrice",
|
||||
"upgrade.minecraft.diamond_sword.adjective": "Da Combattimento"
|
||||
"upgrade.minecraft.diamond_sword.adjective": "Da Combattimento",
|
||||
"tag.item.computercraft.computer": "Computer",
|
||||
"tag.item.computercraft.wired_modem": "Modem cablati",
|
||||
"argument.computercraft.computer.distance": "Distanza dall'entità",
|
||||
"argument.computercraft.computer.family": "Famiglia computer",
|
||||
"argument.computercraft.computer.id": "ID computer",
|
||||
"argument.computercraft.computer.instance": "ID istanza unica",
|
||||
"argument.computercraft.computer.label": "Etichetta computer",
|
||||
"argument.computercraft.unknown_computer_family": "Famiglia computer '%s' sconosciuta",
|
||||
"gui.computercraft.config.disabled_generic_methods": "Metodi generici disattivati",
|
||||
"gui.computercraft.config.disabled_generic_methods.tooltip": "Una lista di metodi generici o sorgenti di metodi da disattivare. I metodi generici sono\nmetodi aggiunti a blocchi/entità blocchi quando non c'è un provider della periferica esplicito.\nQuesto include metodi dell'inventario (ad es. inventory.getItemDetail, inventory.pushItems) e,\nse su Forge, i metodi fluid_storage e energy_storage.\nI metodi in questa lista possono essere sia un gruppo intero di metodi (computer:inventory)\no un singolo metodo (computer:inventory#pushItems).\n",
|
||||
"tag.item.computercraft.monitor": "Monitor",
|
||||
"tag.item.computercraft.turtle": "Tartarughe",
|
||||
"tracking_field.computercraft.java_allocation.name": "Allocazioni Java"
|
||||
}
|
||||
|
@ -2,30 +2,30 @@
|
||||
"parent": "block/block",
|
||||
"render_type": "translucent",
|
||||
"textures": {
|
||||
"particle": "#texture"
|
||||
"particle": "#front"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [ 2, 2, 2 ],
|
||||
"to": [ 14, 14, 13 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 5.75, 2.75, 2.75, 0 ], "texture": "#texture" },
|
||||
"up": { "uv": [ 8.75, 0, 5.75, 2.75 ], "texture": "#texture" },
|
||||
"north": { "uv": [ 11.5, 5.75, 8.5, 2.75 ], "texture": "#texture" },
|
||||
"south": { "uv": [ 5.75, 5.75, 2.75, 2.75 ], "texture": "#texture" },
|
||||
"west": { "uv": [ 8.5, 5.75, 5.75, 2.75 ], "texture": "#texture" },
|
||||
"east": { "uv": [ 2.75, 5.75, 0, 2.75 ], "texture": "#texture" }
|
||||
"down": { "uv": [ 0, 0, 12, 11 ], "texture": "#bottom" },
|
||||
"up": { "uv": [ 0, 0, 12, 11 ], "texture": "#top" },
|
||||
"north": { "uv": [ 0, 0, 12, 12 ], "texture": "#front" },
|
||||
"south": { "uv": [ 0, 0, 12, 12 ], "texture": "#back" },
|
||||
"west": { "uv": [ 0, 0, 11, 12 ], "texture": "#left" },
|
||||
"east": { "uv": [ 0, 0, 11, 12 ], "texture": "#right" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [ 3, 6, 13 ],
|
||||
"to": [ 13, 13, 15 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 11.75, 0.5, 9.25, 0 ], "texture": "#texture" },
|
||||
"up": { "uv": [ 14.25, 0, 11.75, 0.5 ], "texture": "#texture" },
|
||||
"south": { "uv": [ 11.75, 2.25, 9.25, 0.5 ], "texture": "#texture" },
|
||||
"west": { "uv": [ 12.25, 2.25, 11.75, 0.5 ], "texture": "#texture" },
|
||||
"east": { "uv": [ 9.25, 2.25, 8.75, 0.5 ], "texture": "#texture" }
|
||||
"down": { "uv": [ 2, 9, 12, 11 ], "texture": "#backpack" },
|
||||
"up": { "uv": [ 2, 0, 12, 2 ], "texture": "#backpack" },
|
||||
"south": { "uv": [ 2, 2, 12, 9 ], "texture": "#backpack" },
|
||||
"west": { "uv": [ 0, 2, 2, 9 ], "texture": "#backpack" },
|
||||
"east": { "uv": [ 12, 2, 14, 9 ], "texture": "#backpack" }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1,53 +1,67 @@
|
||||
{
|
||||
"parent": "computercraft:block/turtle_base",
|
||||
"textures": {
|
||||
"texture": "computercraft:block/turtle_colour"
|
||||
"texture": "computercraft:block/turtle_colour",
|
||||
"body_back": "computercraft:block/turtle_colour_body_back",
|
||||
"body_backpack": "computercraft:block/turtle_colour_body_backpack",
|
||||
"body_bottom": "computercraft:block/turtle_colour_body_bottom",
|
||||
"body_front": "computercraft:block/turtle_colour_body_front",
|
||||
"body_left": "computercraft:block/turtle_colour_body_left",
|
||||
"body_right": "computercraft:block/turtle_colour_body_right",
|
||||
"body_top": "computercraft:block/turtle_colour_body_top",
|
||||
"frame_back": "computercraft:block/turtle_colour_frame_back",
|
||||
"frame_backpack": "computercraft:block/turtle_colour_frame_backpack",
|
||||
"frame_bottom": "computercraft:block/turtle_colour_frame_bottom",
|
||||
"frame_front": "computercraft:block/turtle_colour_frame_front",
|
||||
"frame_left": "computercraft:block/turtle_colour_frame_left",
|
||||
"frame_right": "computercraft:block/turtle_colour_frame_right",
|
||||
"frame_top": "computercraft:block/turtle_colour_frame_top"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [ 2, 2, 2 ],
|
||||
"to": [ 14, 14, 13 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 5.75, 8.5, 2.75, 5.75 ], "texture": "#texture", "tintindex": 0 },
|
||||
"up": { "uv": [ 8.75, 5.75, 5.75, 8.5 ], "texture": "#texture", "tintindex": 0 },
|
||||
"north": { "uv": [ 11.5, 11.5, 8.5, 8.5 ], "texture": "#texture", "tintindex": 0 },
|
||||
"south": { "uv": [ 5.75, 11.5, 2.75, 8.5 ], "texture": "#texture", "tintindex": 0 },
|
||||
"west": { "uv": [ 8.5, 11.5, 5.75, 8.555 ], "texture": "#texture", "tintindex": 0 },
|
||||
"east": { "uv": [ 2.75, 11.5, 0, 8.5 ], "texture": "#texture", "tintindex": 0 }
|
||||
"down": { "uv": [ 0, 0, 12, 11 ], "texture": "#body_bottom", "tintindex": 0 },
|
||||
"up": { "uv": [ 0, 0, 12, 11 ], "texture": "#body_top", "tintindex": 0 },
|
||||
"north": { "uv": [ 0, 0, 12, 12 ], "texture": "#body_front", "tintindex": 0 },
|
||||
"south": { "uv": [ 0, 0, 12, 12 ], "texture": "#body_back", "tintindex": 0 },
|
||||
"west": { "uv": [ 0, 0, 11, 12 ], "texture": "#body_left", "tintindex": 0 },
|
||||
"east": { "uv": [ 0, 0, 11, 12 ], "texture": "#body_right", "tintindex": 0 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [ 3, 6, 13 ],
|
||||
"to": [ 13, 13, 15 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 11.75, 6.25, 9.25, 5.75 ], "texture": "#texture", "tintindex": 0 },
|
||||
"up": { "uv": [ 14.25, 5.75, 11.75, 6.25 ], "texture": "#texture", "tintindex": 0 },
|
||||
"south": { "uv": [ 11.75, 8, 9.25, 6.25 ], "texture": "#texture", "tintindex": 0 },
|
||||
"west": { "uv": [ 12.25, 8, 11.75, 6.25 ], "texture": "#texture", "tintindex": 0 },
|
||||
"east": { "uv": [ 9.25, 8, 8.75, 6.25 ], "texture": "#texture", "tintindex": 0 }
|
||||
"down": { "uv": [ 2, 9, 12, 11 ], "texture": "#body_backpack", "tintindex": 0 },
|
||||
"up": { "uv": [ 2, 0, 12, 2 ], "texture": "#body_backpack", "tintindex": 0 },
|
||||
"south": { "uv": [ 2, 2, 12, 9 ], "texture": "#body_backpack", "tintindex": 0 },
|
||||
"west": { "uv": [ 0, 2, 2, 9 ], "texture": "#body_backpack", "tintindex": 0 },
|
||||
"east": { "uv": [ 12, 2, 14, 9 ], "texture": "#body_backpack", "tintindex": 0 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [ 2, 2, 2 ],
|
||||
"to": [ 14, 14, 13 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 5.75, 2.75, 2.75, 0 ], "texture": "#texture" },
|
||||
"up": { "uv": [ 8.75, 0, 5.75, 2.75 ], "texture": "#texture" },
|
||||
"north": { "uv": [ 11.5, 5.75, 8.5, 2.75 ], "texture": "#texture" },
|
||||
"south": { "uv": [ 5.75, 5.75, 2.75, 2.75 ], "texture": "#texture" },
|
||||
"west": { "uv": [ 8.5, 5.75, 5.75, 2.75 ], "texture": "#texture" },
|
||||
"east": { "uv": [ 2.75, 5.75, 0, 2.75 ], "texture": "#texture" }
|
||||
"down": { "uv": [ 0, 0, 12, 11 ], "texture": "#frame_bottom" },
|
||||
"up": { "uv": [ 0, 0, 12, 11 ], "texture": "#frame_top" },
|
||||
"north": { "uv": [ 0, 0, 12, 12 ], "texture": "#frame_front" },
|
||||
"south": { "uv": [ 0, 0, 12, 12 ], "texture": "#frame_back" },
|
||||
"west": { "uv": [ 0, 0, 11, 12 ], "texture": "#frame_left" },
|
||||
"east": { "uv": [ 0, 0, 11, 12 ], "texture": "#frame_right" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [ 3, 6, 13 ],
|
||||
"to": [ 13, 13, 15 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 11.75, 0.5, 9.25, 0 ], "texture": "#texture" },
|
||||
"up": { "uv": [ 14.25, 0, 11.75, 0.5 ], "texture": "#texture" },
|
||||
"south": { "uv": [ 11.75, 2.25, 9.25, 0.5 ], "texture": "#texture" },
|
||||
"west": { "uv": [ 12.25, 2.25, 11.75, 0.5 ], "texture": "#texture" },
|
||||
"east": { "uv": [ 9.25, 2.25, 8.75, 0.5 ], "texture": "#texture" }
|
||||
"down": { "uv": [ 2, 9, 12, 11 ], "texture": "#frame_backpack" },
|
||||
"up": { "uv": [ 2, 0, 12, 2 ], "texture": "#frame_backpack" },
|
||||
"south": { "uv": [ 2, 2, 12, 9 ], "texture": "#frame_backpack" },
|
||||
"west": { "uv": [ 0, 2, 2, 9 ], "texture": "#frame_backpack" },
|
||||
"east": { "uv": [ 12, 2, 14, 9 ], "texture": "#frame_backpack" }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1,6 +1,35 @@
|
||||
{
|
||||
"parent": "computercraft:block/turtle_overlay",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"texture": "computercraft:block/turtle_elf_overlay"
|
||||
}
|
||||
}
|
||||
"back": "computercraft:block/turtle_elf_overlay_back",
|
||||
"backpack": "computercraft:block/turtle_elf_overlay_backpack",
|
||||
"front": "computercraft:block/turtle_elf_overlay_front",
|
||||
"left": "computercraft:block/turtle_elf_overlay_left",
|
||||
"right": "computercraft:block/turtle_elf_overlay_right",
|
||||
"top": "computercraft:block/turtle_elf_overlay_top"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [ 2, 2, 2 ],
|
||||
"to": [ 14, 14, 13 ],
|
||||
"faces": {
|
||||
"up": { "uv": [ 0, 0, 12, 11 ], "texture": "#top" },
|
||||
"north": { "uv": [ 0, 0, 12, 12 ], "texture": "#front" },
|
||||
"south": { "uv": [ 0, 0, 12, 12 ], "texture": "#back" },
|
||||
"west": { "uv": [ 0, 0, 11, 12 ], "texture": "#left" },
|
||||
"east": { "uv": [ 0, 0, 11, 12 ], "texture": "#right" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [ 3, 6, 13 ],
|
||||
"to": [ 13, 13, 15 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 2, 9, 12, 11 ], "texture": "#backpack" },
|
||||
"up": { "uv": [ 2, 0, 12, 2 ], "texture": "#backpack" },
|
||||
"south": { "uv": [ 2, 2, 12, 9 ], "texture": "#backpack" },
|
||||
"west": { "uv": [ 0, 2, 2, 9 ], "texture": "#backpack" },
|
||||
"east": { "uv": [ 12, 2, 14, 9 ], "texture": "#backpack" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
{
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "#texture"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [ 2, 2, 2 ],
|
||||
"to": [ 14, 14, 13 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 2.75, 0, 5.75, 2.75 ], "texture": "#texture" },
|
||||
"up": { "uv": [ 5.75, 0, 8.75, 2.75 ], "texture": "#texture" },
|
||||
"north": { "uv": [ 8.5, 5.75, 11.5, 2.75 ], "texture": "#texture" },
|
||||
"south": { "uv": [ 2.75, 5.75, 5.75, 2.75 ], "texture": "#texture" },
|
||||
"west": { "uv": [ 0, 5.75, 2.75, 2.75 ], "texture": "#texture" },
|
||||
"east": { "uv": [ 5.75, 5.75, 8.5, 2.75 ], "texture": "#texture" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [ 3, 6, 13 ],
|
||||
"to": [ 13, 13, 15 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 9.25, 0, 11.75, 0.5 ], "texture": "#texture" },
|
||||
"up": { "uv": [ 11.75, 0, 14.25, 0.5 ], "texture": "#texture" },
|
||||
"south": { "uv": [ 9.25, 2.25, 11.75, 0.5 ], "texture": "#texture" },
|
||||
"west": { "uv": [ 8.75, 2.25, 9.25, 0.5 ], "texture": "#texture" },
|
||||
"east": { "uv": [ 11.75, 2.25, 12.25, 0.5 ], "texture": "#texture" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [ 1.5, 1.5, 1.5 ],
|
||||
"to": [ 14.5, 14.5, 13.5 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 2.75, 8, 5.75, 10.75 ], "texture": "#texture" },
|
||||
"up": { "uv": [ 5.75, 8, 8.75, 10.75 ], "texture": "#texture" },
|
||||
"north": { "uv": [ 8.5, 13.75, 11.5, 10.75 ], "texture": "#texture" },
|
||||
"south": { "uv": [ 2.75, 13.75, 5.75, 10.75 ], "texture": "#texture" },
|
||||
"west": { "uv": [ 0, 13.75, 2.75, 10.75 ], "texture": "#texture" },
|
||||
"east": { "uv": [ 5.75, 13.75, 8.5, 10.75 ], "texture": "#texture" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Before Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 533 B |
After Width: | Height: | Size: 489 B |
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 502 B |
After Width: | Height: | Size: 517 B |
After Width: | Height: | Size: 490 B |
Before Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 258 B |
After Width: | Height: | Size: 229 B |
After Width: | Height: | Size: 361 B |
After Width: | Height: | Size: 247 B |
After Width: | Height: | Size: 292 B |
After Width: | Height: | Size: 253 B |
After Width: | Height: | Size: 168 B |
After Width: | Height: | Size: 235 B |
After Width: | Height: | Size: 191 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 203 B |
After Width: | Height: | Size: 225 B |
After Width: | Height: | Size: 184 B |
After Width: | Height: | Size: 185 B |
Before Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 338 B |
After Width: | Height: | Size: 483 B |
After Width: | Height: | Size: 234 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 272 B |
After Width: | Height: | Size: 590 B |
Before Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 397 B |
After Width: | Height: | Size: 287 B |
After Width: | Height: | Size: 350 B |
After Width: | Height: | Size: 410 B |
After Width: | Height: | Size: 408 B |
After Width: | Height: | Size: 393 B |
After Width: | Height: | Size: 340 B |
Before Width: | Height: | Size: 596 B After Width: | Height: | Size: 186 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 154 B |
@ -42,6 +42,7 @@ class GameTestSequenceMixin {
|
||||
}
|
||||
|
||||
@Shadow
|
||||
@SuppressWarnings("unused")
|
||||
private void tick(long tick) {
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class MinecraftMixin implements MinecraftExtensions {
|
||||
private final AtomicBoolean isStable = new AtomicBoolean(false);
|
||||
|
||||
@Inject(method = "runTick", at = @At("TAIL"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void updateStable(boolean render, CallbackInfo ci) {
|
||||
isStable.set(
|
||||
level != null && player != null &&
|
||||
|
@ -22,7 +22,7 @@ public class WorldOpenFlowsMixin {
|
||||
* @reason Makes it easier to run tests. We can switch to an @Inject if this becomes a problem.
|
||||
*/
|
||||
@Overwrite
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void askForBackup(LevelStorageSource.LevelStorageAccess access, boolean customised, Runnable load, Runnable cancel) {
|
||||
load.run();
|
||||
}
|
||||
|
@ -309,10 +309,10 @@ public class FSAPI implements ILuaAPI {
|
||||
* <p>
|
||||
* The {@code mode} string can be any of the following:
|
||||
* <ul>
|
||||
* <li><strong>"r"</strong>: Read mode</li>
|
||||
* <li><strong>"w"</strong>: Write mode</li>
|
||||
* <li><strong>"a"</strong>: Append mode</li>
|
||||
* <li><strong>"r+"</strong>: Update mode (allows reading and writing), all data is preserved</li>
|
||||
* <li><strong>"r"</strong>: Read mode.</li>
|
||||
* <li><strong>"w"</strong>: Write mode.</li>
|
||||
* <li><strong>"a"</strong>: Append mode.</li>
|
||||
* <li><strong>"r+"</strong>: Update mode (allows reading and writing), all data is preserved.</li>
|
||||
* <li><strong>"w+"</strong>: Update mode, all data is erased.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
|
@ -365,24 +365,26 @@ end
|
||||
-- or [`nil`], plus an error message.
|
||||
--
|
||||
-- The `mode` string can be any of the following:
|
||||
-- - **"r"**: Read mode
|
||||
-- - **"w"**: Write mode
|
||||
-- - **"a"**: Append mode
|
||||
-- - **"r"**: Read mode.
|
||||
-- - **"w"**: Write mode.
|
||||
-- - **"a"**: Append mode.
|
||||
-- - **"r+"**: Update mode (allows reading and writing), all data is preserved.
|
||||
-- - **"w+"**: Update mode, all data is erased.
|
||||
--
|
||||
-- The mode may also have a `b` at the end, which opens the file in "binary
|
||||
-- mode". This allows you to read binary files, as well as seek within a file.
|
||||
-- mode". This has no impact on functionality.
|
||||
--
|
||||
-- @tparam string filename The name of the file to open.
|
||||
-- @tparam[opt] string mode The mode to open the file with. This defaults to `rb`.
|
||||
-- @tparam[opt] string mode The mode to open the file with. This defaults to `r`.
|
||||
-- @treturn[1] Handle The opened file.
|
||||
-- @treturn[2] nil In case of an error.
|
||||
-- @treturn[2] string The reason the file could not be opened.
|
||||
-- @changed 1.111.0 Add support for `r+` and `w+`.
|
||||
function open(filename, mode)
|
||||
expect(1, filename, "string")
|
||||
expect(2, mode, "string", "nil")
|
||||
|
||||
local sMode = mode and mode:gsub("%+", "") or "r"
|
||||
local file, err = fs.open(filename, sMode)
|
||||
local file, err = fs.open(filename, mode or "r")
|
||||
if not file then return nil, err end
|
||||
|
||||
return make_file(file)
|
||||
|
@ -149,7 +149,7 @@ function isOpen(modem)
|
||||
end
|
||||
|
||||
--[[- Allows a computer or turtle with an attached modem to send a message
|
||||
intended for a sycomputer with a specific ID. At least one such modem must first
|
||||
intended for a computer with a specific ID. At least one such modem must first
|
||||
be [opened][`rednet.open`] before sending is possible.
|
||||
|
||||
Assuming the target was in range and also had a correctly opened modem, the
|
||||
|
@ -19,7 +19,7 @@ When a computer starts, it reads the current value of settings from the
|
||||
settings.define("my.setting", {
|
||||
description = "An example setting",
|
||||
default = 123,
|
||||
type = number,
|
||||
type = "number",
|
||||
})
|
||||
print("my.setting = " .. settings.get("my.setting")) -- 123
|
||||
|
||||
|
@ -1,3 +1,15 @@
|
||||
# New features in CC: Tweaked 1.111.0
|
||||
|
||||
* Update several translations (Ale32bit).
|
||||
* Split up turtle textures into individual textures.
|
||||
* Add `r+`/`w+` support to the `io` library.
|
||||
* Warn when capabilities are not registered and Optifine is installed.
|
||||
|
||||
Several bug fixes:
|
||||
* Allow planks to be used for building in "adventure" (dan200).
|
||||
* Fix `disk.getAudioTitle()` returning untranslated strings for some modded discs.
|
||||
* Fix crash when right clicking turtles in spectator.
|
||||
|
||||
# New features in CC: Tweaked 1.110.3
|
||||
|
||||
* Update several translations (PatriikPlays).
|
||||
|
@ -1,9 +1,13 @@
|
||||
New features in CC: Tweaked 1.110.3
|
||||
New features in CC: Tweaked 1.111.0
|
||||
|
||||
* Update several translations (PatriikPlays).
|
||||
* Update several translations (Ale32bit).
|
||||
* Split up turtle textures into individual textures.
|
||||
* Add `r+`/`w+` support to the `io` library.
|
||||
* Warn when capabilities are not registered and Optifine is installed.
|
||||
|
||||
Several bug fixes:
|
||||
* Fix some errors missing source positions.
|
||||
* Correctly handle multiple threads sending websocket messages at once.
|
||||
* Allow planks to be used for building in "adventure" (dan200).
|
||||
* Fix `disk.getAudioTitle()` returning untranslated strings for some modded discs.
|
||||
* Fix crash when right clicking turtles in spectator.
|
||||
|
||||
Type "help changelog" to see the full version history.
|
||||
|
@ -108,6 +108,7 @@ local items = {
|
||||
},
|
||||
["some planks"] = {
|
||||
aliases = { "planks", "wooden planks", "wood planks" },
|
||||
material = true,
|
||||
desc = "You could easily craft these planks into sticks.",
|
||||
},
|
||||
["some sticks"] = {
|
||||
|
@ -329,4 +329,19 @@ describe("The io library", function()
|
||||
expect(read_all(file)):eq("alo\n " .. t .. " ;end of file\n")
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("read/write handles", function()
|
||||
it("can read and write to a file", function()
|
||||
write_file(file, "an example file")
|
||||
|
||||
local handle = io.open(file, "r+")
|
||||
expect(handle:read(3)):eq("an ")
|
||||
|
||||
handle:write("exciting file")
|
||||
expect(handle:seek("cur")):eq(16)
|
||||
|
||||
handle:seek("set", 0)
|
||||
expect(handle:read("*a")):eq("an exciting file")
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -27,7 +27,7 @@ class GameRendererMixin {
|
||||
private Map<String, ShaderInstance> shaders;
|
||||
|
||||
@Inject(method = "reloadShaders", at = @At(value = "TAIL"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void onReloadShaders(ResourceProvider resourceManager, CallbackInfo ci) {
|
||||
try {
|
||||
ClientRegistry.registerShaders(resourceManager, (shader, callback) -> {
|
||||
|
@ -22,7 +22,7 @@ class ItemFrameRendererMixin {
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 2, shift = At.Shift.AFTER),
|
||||
cancellable = true
|
||||
)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void render(ItemFrame entity, float yaw, float partialTicks, PoseStack pose, MultiBufferSource buffers, int light, CallbackInfo ci) {
|
||||
if (ClientHooks.onRenderItemFrame(pose, buffers, entity, entity.getItem(), light)) {
|
||||
ci.cancel();
|
||||
|
@ -19,7 +19,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(ItemInHandRenderer.class)
|
||||
class ItemInHandRendererMixin {
|
||||
@Inject(method = "renderArmWithItem", at = @At("HEAD"), cancellable = true)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void onRenderItem(
|
||||
AbstractClientPlayer player, float partialTicks, float pitch, InteractionHand hand, float swingProgress, ItemStack stack,
|
||||
float equippedProgress, PoseStack transform, MultiBufferSource buffer, int combinedLight, CallbackInfo ci
|
||||
|
@ -24,7 +24,7 @@ class MinecraftMixin {
|
||||
private ReloadableResourceManager resourceManager;
|
||||
|
||||
@Inject(method = "updateLevelInEngines", at = @At("HEAD"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void updateLevelInEngines(ClientLevel screen, CallbackInfo ci) {
|
||||
ClientHooks.onWorldUnload();
|
||||
}
|
||||
@ -37,7 +37,7 @@ class MinecraftMixin {
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void beforeInitialResourceReload(GameConfig gameConfig, CallbackInfo ci) {
|
||||
ClientRegistry.registerReloadListeners(resourceManager::registerReloadListener, (Minecraft) (Object) this);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class MultiPlayerGameModeMixin {
|
||||
cancellable = true,
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void onBlockBreak(BlockPos pos, CallbackInfoReturnable<Boolean> cir, Level level, BlockState state, Block block) {
|
||||
if (!FabricCommonHooks.onBlockDestroy(level, minecraft.player, pos, state, null)) cir.setReturnValue(true);
|
||||
}
|
||||
|
@ -26,13 +26,13 @@ class SoundEngineMixin {
|
||||
private static SoundEngine self;
|
||||
|
||||
@Inject(method = "play", at = @At(value = "HEAD"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void playSound(SoundInstance sound, CallbackInfo ci) {
|
||||
self = (SoundEngine) (Object) this;
|
||||
}
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "method_19755")
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private static void onStream(AudioStream stream, Channel channel, CallbackInfo ci) {
|
||||
SpeakerManager.onPlayStreaming(assertNonNull(self), channel, stream);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class ChunkMapMixin {
|
||||
ServerLevel level;
|
||||
|
||||
@Inject(method = "updateChunkScheduling", at = @At("HEAD"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void onUpdateChunkScheduling(long chunkPos, int newLevel, @Nullable ChunkHolder holder, int oldLevel, CallbackInfoReturnable<ChunkHolder> callback) {
|
||||
CommonHooks.onChunkTicketLevelChanged(level, chunkPos, oldLevel, newLevel);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class EntityMixin {
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"),
|
||||
cancellable = true
|
||||
)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void spawnAtLocation(ItemStack stack, float yOffset, CallbackInfoReturnable<ItemEntity> cb) {
|
||||
if (CommonHooks.onLivingDrop((Entity) (Object) this, stack)) cb.setReturnValue(null);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(ItemEntity.class)
|
||||
abstract class ItemEntityMixin {
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private void onTick(CallbackInfo ci) {
|
||||
var stack = getItem();
|
||||
if (stack.getItem() instanceof PocketComputerItem pocket) {
|
||||
|
@ -21,7 +21,7 @@ import java.util.function.Predicate;
|
||||
@Mixin(TagsProvider.class)
|
||||
class TagsProviderMixin {
|
||||
@Inject(at = @At("HEAD"), method = "method_49658", cancellable = true)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
@SuppressWarnings("unused")
|
||||
private static void onVerifyPresent(Predicate<?> predicate1, Predicate<?> predicate2, TagEntry tag, CallbackInfoReturnable<Boolean> cir) {
|
||||
var element = ((TagEntryAccessor) tag).computercraft$elementOrTag();
|
||||
if (element.tag() && element.id().getNamespace().equals("minecraft")) cir.setReturnValue(false);
|
||||
|
51
tools/update-resources.py
Normal file → Executable file
@ -76,6 +76,45 @@ def unstitch_corners(input_file: pathlib.Path, family: str):
|
||||
sidebar.save(output_dir / f"sidebar_{family}.png")
|
||||
|
||||
|
||||
def unstitch_turtle(input_file: pathlib.Path, family: str, *, dy: int = 0):
|
||||
input = Image.open(input_file)
|
||||
output_dir = input_file.parent
|
||||
|
||||
fragments = [
|
||||
("bottom", 22, 0, 24, 22, Image.Transpose.ROTATE_180),
|
||||
("top", 46, 0, 24, 22, Image.Transpose.FLIP_LEFT_RIGHT),
|
||||
("right", 0, 22, 22, 24, Image.Transpose.ROTATE_180),
|
||||
("back", 22, 22, 24, 24, Image.Transpose.ROTATE_180),
|
||||
("left", 46, 22, 22, 24, Image.Transpose.ROTATE_180),
|
||||
("front", 68, 22, 24, 24, Image.Transpose.ROTATE_180),
|
||||
]
|
||||
|
||||
for suffix, x, y, w, h, transform in fragments:
|
||||
if family == "elf_overlay" and suffix == "bottom":
|
||||
continue
|
||||
|
||||
slice = input.crop(box(x, dy + y, w, h)).transpose(transform)
|
||||
|
||||
fragment = Image.new("RGBA", (32, 32))
|
||||
fragment.paste(slice)
|
||||
fragment.save(output_dir / f"turtle_{family}_{suffix}.png")
|
||||
|
||||
backpack = Image.new("RGBA", (32, 32))
|
||||
backpack.paste(
|
||||
input.crop(box(70, dy + 4, 28, 14)).transpose(Image.Transpose.ROTATE_180),
|
||||
(0, 4),
|
||||
)
|
||||
backpack.paste(
|
||||
input.crop(box(74, dy + 0, 20, 4)).transpose(Image.Transpose.ROTATE_180),
|
||||
(4, 18),
|
||||
)
|
||||
backpack.paste(
|
||||
input.crop(box(94, dy + 0, 20, 4)).transpose(Image.Transpose.FLIP_LEFT_RIGHT),
|
||||
(4, 0),
|
||||
)
|
||||
backpack.save(output_dir / f"turtle_{family}_backpack.png")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
spec = argparse.ArgumentParser()
|
||||
spec.add_argument("dir", type=pathlib.Path)
|
||||
@ -97,6 +136,18 @@ def main() -> None:
|
||||
unstitch_corners(path, family)
|
||||
transformed.append(path)
|
||||
|
||||
for family in ("normal", "advanced", "elf_overlay"):
|
||||
path = texture_path / "block" / f"turtle_{family}.png"
|
||||
if path.exists():
|
||||
unstitch_turtle(path, family)
|
||||
transformed.append(path)
|
||||
|
||||
path = texture_path / "block" / f"turtle_colour.png"
|
||||
if path.exists():
|
||||
unstitch_turtle(path, "colour_frame")
|
||||
unstitch_turtle(path, "colour_body", dy=46)
|
||||
transformed.append(path)
|
||||
|
||||
if len(transformed) == 0:
|
||||
print("No files were transformed")
|
||||
return
|
||||
|