1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00

Merge branch 'mc-1.16.x' into mc-1.18.x

This commit is contained in:
Jonathan Coates 2022-06-10 00:00:06 +01:00
commit 557765d8f0
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
92 changed files with 3323 additions and 112 deletions

2
.gitattributes vendored
View File

@ -1,5 +1,5 @@
# Ignore changes in generated files
src/generated/resources/data/** linguist-generated
src/generated/** linguist-generated
src/testMod/server-files/structures linguist-generated
* text=auto

View File

@ -12,7 +12,7 @@ chmod 600 "$HOME/.ssh/key"
# And upload
rsync -avc -e "ssh -i $HOME/.ssh/key -o StrictHostKeyChecking=no -p $SSH_PORT" \
"$GITHUB_WORKSPACE/build/docs/lua/" \
"$GITHUB_WORKSPACE/build/docs/site/" \
"$SSH_USER@$SSH_HOST:/$DEST"
rsync -avc -e "ssh -i $HOME/.ssh/key -o StrictHostKeyChecking=no -p $SSH_PORT" \
"$GITHUB_WORKSPACE/build/docs/javadoc/" \

View File

@ -65,7 +65,7 @@ #### Building documentation
- `./gradlew luaJavadoc` - Generate documentation stubs for Java methods.
- `./gradlew docWebsite` - Generate the whole website (including Javascript pages). The resulting HTML is stored at
`./build/docs/lua/`.
`./build/docs/site/`.
#### Writing documentation
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as

View File

@ -174,7 +174,7 @@ accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
exclude group: "org.jetbrains", module: "annotations"
}
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.5'
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.6'
}
// Compile tasks
@ -313,7 +313,7 @@ commandLine mkCommand('"node_modules/.bin/rollup" --config rollup.config.js')
task illuaminateDocs(type: Exec, dependsOn: [rollup, luaJavadoc]) {
group = "build"
description = "Bundles JS into rollup"
description = "Generates docs using Illuaminate"
inputs.files(fileTree("doc")).withPropertyName("docs")
inputs.files(fileTree("src/main/resources/data/computercraft/lua/rom")).withPropertyName("lua rom")
@ -326,7 +326,21 @@ task illuaminateDocs(type: Exec, dependsOn: [rollup, luaJavadoc]) {
commandLine mkCommand('"bin/illuaminate" doc-gen')
}
task docWebsite(type: Copy, dependsOn: [illuaminateDocs]) {
task jsxDocs(type: Exec, dependsOn: [illuaminateDocs]) {
group = "build"
description = "Post-processes documentation to statically render some dynamic content."
inputs.files(fileTree("src/web")).withPropertyName("sources")
inputs.file("src/generated/export/index.json").withPropertyName("export")
inputs.file("package-lock.json").withPropertyName("package-lock.json")
inputs.file("tsconfig.json").withPropertyName("Typescript config")
inputs.files(fileTree("$buildDir/docs/lua"))
outputs.dir("$buildDir/docs/site")
commandLine mkCommand('"node_modules/.bin/ts-node" --esm src/web/transform.tsx')
}
task docWebsite(type: Copy, dependsOn: [jsxDocs]) {
from('doc') {
include 'logo.png'
include 'images/**'
@ -334,7 +348,14 @@ task docWebsite(type: Copy, dependsOn: [illuaminateDocs]) {
from("$buildDir/rollup") {
exclude 'index.js'
}
into "${project.docsDir}/lua"
from("$buildDir/docs/lua") {
exclude '**/*.html'
}
from("src/generated/export/items") {
into("images/items")
}
into "${project.docsDir}/site"
}
// Check tasks

View File

@ -83,7 +83,9 @@
<module name="JavadocBlockTagLocation" />
<module name="JavadocMethod"/>
<module name="JavadocType"/>
<module name="JavadocStyle" />
<module name="JavadocStyle">
<property name="checkHtml" value="false" />
</module>
<module name="NonEmptyAtclauseDescription" />
<module name="SingleLineJavadoc" />
<module name="SummaryJavadocCheck"/>

View File

@ -1,7 +1,7 @@
org.gradle.jvmargs=-Xmx3G
# Mod properties
mod_version=1.100.5
mod_version=1.100.6
# Minecraft properties (update mods.toml when changing)
mc_version=1.18.2

1719
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
"description": "Website additions for tweaked.cc",
"author": "SquidDev",
"license": "BSD-3-Clause",
"type": "module",
"dependencies": {
"preact": "^10.5.5",
"tslib": "^2.0.3"
@ -11,9 +12,18 @@
"devDependencies": {
"@rollup/plugin-typescript": "^8.2.5",
"@rollup/plugin-url": "^6.1.0",
"@types/glob": "^7.2.0",
"@types/react-dom": "^18.0.5",
"glob": "^8.0.3",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"rehype": "^12.0.1",
"rehype-highlight": "^5.0.2",
"rehype-react": "^7.1.1",
"requirejs": "^2.3.6",
"rollup": "^2.33.1",
"rollup-plugin-terser": "^7.0.2",
"ts-node": "^10.8.0",
"typescript": "^4.0.5"
}
}

760
src/generated/export/index.json generated Normal file
View File

@ -0,0 +1,760 @@
{
"itemNames": {
"computercraft:cable": "Networking Cable",
"computercraft:computer_advanced": "Advanced Computer",
"computercraft:computer_command": "Command Computer",
"computercraft:computer_normal": "Computer",
"computercraft:disk": "Floppy Disk",
"computercraft:disk_drive": "Disk Drive",
"computercraft:monitor_advanced": "Advanced Monitor",
"computercraft:monitor_normal": "Monitor",
"computercraft:pocket_computer_advanced": "Advanced Pocket Computer",
"computercraft:pocket_computer_normal": "Pocket Computer",
"computercraft:printed_book": "Printed Book",
"computercraft:printed_page": "Printed Page",
"computercraft:printed_pages": "Printed Pages",
"computercraft:printer": "Printer",
"computercraft:speaker": "Speaker",
"computercraft:treasure_disk": "Floppy Disk",
"computercraft:turtle_advanced": "Advanced Turtle",
"computercraft:turtle_normal": "Turtle",
"computercraft:wired_modem": "Wired Modem",
"computercraft:wired_modem_full": "Wired Modem",
"computercraft:wireless_modem_advanced": "Ender Modem",
"computercraft:wireless_modem_normal": "Wireless Modem",
"minecraft:black_dye": "Black Dye",
"minecraft:blue_dye": "Blue Dye",
"minecraft:brown_dye": "Brown Dye",
"minecraft:chest": "Chest",
"minecraft:command_block": "Command Block",
"minecraft:cyan_dye": "Cyan Dye",
"minecraft:ender_eye": "Eye of Ender",
"minecraft:ender_pearl": "Ender Pearl",
"minecraft:glass_pane": "Glass Pane",
"minecraft:gold_block": "Block of Gold",
"minecraft:gold_ingot": "Gold Ingot",
"minecraft:golden_apple": "Golden Apple",
"minecraft:gray_dye": "Gray Dye",
"minecraft:green_dye": "Green Dye",
"minecraft:iron_ingot": "Iron Ingot",
"minecraft:leather": "Leather",
"minecraft:light_blue_dye": "Light Blue Dye",
"minecraft:light_gray_dye": "Light Gray Dye",
"minecraft:lime_dye": "Lime Dye",
"minecraft:magenta_dye": "Magenta Dye",
"minecraft:note_block": "Note Block",
"minecraft:orange_dye": "Orange Dye",
"minecraft:pink_dye": "Pink Dye",
"minecraft:purple_dye": "Purple Dye",
"minecraft:red_dye": "Red Dye",
"minecraft:redstone": "Redstone Dust",
"minecraft:stone": "Stone",
"minecraft:string": "String",
"minecraft:white_dye": "White Dye",
"minecraft:yellow_dye": "Yellow Dye"
},
"recipes": {
"computercraft:cable": {
"inputs": [
null,
[
"minecraft:stone"
],
null,
[
"minecraft:stone"
],
[
"minecraft:redstone"
],
[
"minecraft:stone"
],
null,
[
"minecraft:stone"
],
null
],
"output": "computercraft:cable",
"count": 6
},
"computercraft:computer_advanced": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:redstone"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:glass_pane"
],
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:computer_advanced",
"count": 1
},
"computercraft:computer_advanced_upgrade": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"computercraft:computer_normal"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
null,
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:computer_advanced",
"count": 1
},
"computercraft:computer_command": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:command_block"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:glass_pane"
],
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:computer_command",
"count": 1
},
"computercraft:computer_normal": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:redstone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:glass_pane"
],
[
"minecraft:stone"
]
],
"output": "computercraft:computer_normal",
"count": 1
},
"computercraft:disk_drive": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:redstone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:redstone"
],
[
"minecraft:stone"
]
],
"output": "computercraft:disk_drive",
"count": 1
},
"computercraft:monitor_advanced": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:glass_pane"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:monitor_advanced",
"count": 4
},
"computercraft:monitor_normal": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:glass_pane"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
]
],
"output": "computercraft:monitor_normal",
"count": 1
},
"computercraft:pocket_computer_advanced": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:golden_apple"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:glass_pane"
],
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:pocket_computer_advanced",
"count": 1
},
"computercraft:pocket_computer_advanced_upgrade": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"computercraft:pocket_computer_normal"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
null,
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:pocket_computer_advanced",
"count": 1
},
"computercraft:pocket_computer_normal": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:golden_apple"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:glass_pane"
],
[
"minecraft:stone"
]
],
"output": "computercraft:pocket_computer_normal",
"count": 1
},
"computercraft:printed_book": {
"inputs": [
[
"minecraft:leather"
],
[
"computercraft:printed_page"
],
[
"minecraft:string"
],
null,
null,
null,
null,
null,
null
],
"output": "computercraft:printed_book",
"count": 1
},
"computercraft:printed_pages": {
"inputs": [
[
"computercraft:printed_page"
],
[
"computercraft:printed_page"
],
[
"minecraft:string"
],
null,
null,
null,
null,
null,
null
],
"output": "computercraft:printed_pages",
"count": 1
},
"computercraft:printer": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:redstone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:black_dye",
"minecraft:blue_dye",
"minecraft:brown_dye",
"minecraft:cyan_dye",
"minecraft:gray_dye",
"minecraft:green_dye",
"minecraft:light_blue_dye",
"minecraft:light_gray_dye",
"minecraft:lime_dye",
"minecraft:magenta_dye",
"minecraft:orange_dye",
"minecraft:pink_dye",
"minecraft:purple_dye",
"minecraft:red_dye",
"minecraft:white_dye",
"minecraft:yellow_dye"
],
[
"minecraft:stone"
]
],
"output": "computercraft:printer",
"count": 1
},
"computercraft:speaker": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:note_block"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:redstone"
],
[
"minecraft:stone"
]
],
"output": "computercraft:speaker",
"count": 1
},
"computercraft:turtle_advanced": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"computercraft:computer_advanced"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:chest"
],
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:turtle_advanced",
"count": 1
},
"computercraft:turtle_advanced_upgrade": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"computercraft:turtle_normal"
],
[
"minecraft:gold_ingot"
],
null,
[
"minecraft:gold_block"
],
null
],
"output": "computercraft:turtle_advanced",
"count": 1
},
"computercraft:turtle_normal": {
"inputs": [
[
"minecraft:iron_ingot"
],
[
"minecraft:iron_ingot"
],
[
"minecraft:iron_ingot"
],
[
"minecraft:iron_ingot"
],
[
"computercraft:computer_normal"
],
[
"minecraft:iron_ingot"
],
[
"minecraft:iron_ingot"
],
[
"minecraft:chest"
],
[
"minecraft:iron_ingot"
]
],
"output": "computercraft:turtle_normal",
"count": 1
},
"computercraft:wired_modem": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:redstone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
]
],
"output": "computercraft:wired_modem",
"count": 1
},
"computercraft:wired_modem_full_from": {
"inputs": [
[
"computercraft:wired_modem"
],
null,
null,
null,
null,
null,
null,
null,
null
],
"output": "computercraft:wired_modem_full",
"count": 1
},
"computercraft:wired_modem_full_to": {
"inputs": [
[
"computercraft:wired_modem_full"
],
null,
null,
null,
null,
null,
null,
null,
null
],
"output": "computercraft:wired_modem",
"count": 1
},
"computercraft:wireless_modem_advanced": {
"inputs": [
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:ender_eye"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
],
[
"minecraft:gold_ingot"
]
],
"output": "computercraft:wireless_modem_advanced",
"count": 1
},
"computercraft:wireless_modem_normal": {
"inputs": [
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:ender_pearl"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
],
[
"minecraft:stone"
]
],
"output": "computercraft:wireless_modem_normal",
"count": 1
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 977 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

View File

@ -77,7 +77,7 @@ public void renderBg( @Nonnull PoseStack stack, float partialTicks, int mouseX,
{
// Draw a border around the terminal
ComputerBorderRenderer.render(
ComputerBorderRenderer.getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
stack.last().pose(), ComputerBorderRenderer.getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight()
);
ComputerSidebar.renderBackground( stack, leftPos, topPos + sidebarYOffset );

View File

@ -23,13 +23,6 @@ public class ComputerBorderRenderer
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
private static final Matrix4f IDENTITY = new Matrix4f();
static
{
IDENTITY.setIdentity();
}
/**
* The margin between the terminal and its border.
*/
@ -91,10 +84,10 @@ public static RenderType getRenderType( ResourceLocation location )
return RenderType.text( location );
}
public static void render( ResourceLocation location, int x, int y, int z, int light, int width, int height )
public static void render( Matrix4f transform, ResourceLocation location, int x, int y, int z, int light, int width, int height )
{
MultiBufferSource.BufferSource source = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
render( IDENTITY, source.getBuffer( getRenderType( location ) ), x, y, z, light, width, height, false, 1, 1, 1 );
render( transform, source.getBuffer( getRenderType( location ) ), x, y, z, light, width, height, false, 1, 1, 1 );
source.endBatch();
}

View File

@ -324,9 +324,9 @@ public synchronized void write( FriendlyByteBuf buffer )
TextBuffer textColour = this.textColour[y];
TextBuffer backColour = backgroundColour[y];
for( int x = 0; x < width; x++ ) buffer.writeByte( text.charAt( x ) & 0xFF );
for( int x = 0; x < width; x++ )
{
buffer.writeByte( text.charAt( x ) & 0xFF );
buffer.writeByte( getColour(
backColour.charAt( x ), Colour.BLACK ) << 4 |
getColour( textColour.charAt( x ), Colour.WHITE )
@ -353,10 +353,9 @@ public synchronized void read( FriendlyByteBuf buffer )
TextBuffer textColour = this.textColour[y];
TextBuffer backColour = backgroundColour[y];
for( int x = 0; x < width; x++ ) text.setChar( x, (char) (buffer.readByte() & 0xFF) );
for( int x = 0; x < width; x++ )
{
text.setChar( x, (char) (buffer.readByte() & 0xFF) );
byte colour = buffer.readByte();
backColour.setChar( x, base16.charAt( (colour >> 4) & 0xF ) );
textColour.setChar( x, base16.charAt( colour & 0xF ) );

View File

@ -19,9 +19,17 @@
import net.minecraft.world.phys.BlockHitResult;
import javax.annotation.Nonnull;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class TileGeneric extends BlockEntity
{
/**
* Is this block enqueued to be updated next tick? This should only be read/written by the tick scheduler.
*
* @see dan200.computercraft.shared.util.TickScheduler
*/
public final AtomicBoolean scheduled = new AtomicBoolean();
public TileGeneric( BlockEntityType<? extends TileGeneric> type, BlockPos pos, BlockState state )
{
super( type, pos, state );

View File

@ -428,6 +428,7 @@ protected void transferStateFrom( TileComputerBase copy )
label = copy.label;
on = copy.on;
startOn = copy.startOn;
lockCode = copy.lockCode;
updateBlock();
}
copy.instanceID = -1;

View File

@ -23,7 +23,6 @@
import net.minecraftforge.network.simple.SimpleChannel;
import java.util.function.Function;
import java.util.function.Supplier;
public final class NetworkHandler
{
@ -112,10 +111,4 @@ private static <T extends NetworkMessage> void registerMainThread( int id, Netwo
} )
.add();
}
@SuppressWarnings( "unchecked" )
private static <T> Class<T> getType( Supplier<T> supplier )
{
return (Class<T>) supplier.get().getClass();
}
}

View File

@ -30,6 +30,11 @@
* When a disk is inserted, a {@code disk} event is fired, with the side peripheral is on. Likewise, when the disk is
* detached, a {@code disk_eject} event is fired.
*
* ## Recipe
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:disk_drive"></mc-recipe>
* </div>
*
* @cc.module drive
*/
public class DiskDrivePeripheral implements IPeripheral

View File

@ -75,6 +75,15 @@
*
* print("Received a reply: " .. tostring(message))
* }</pre>
*
* ## Recipes
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:wireless_modem_normal"></mc-recipe>
* <mc-recipe recipe="computercraft:wireless_modem_advanced"></mc-recipe>
* <mc-recipe recipe="computercraft:wired_modem"></mc-recipe>
* <mc-recipe recipe="computercraft:cable"></mc-recipe>
* <mc-recipe recipe="computercraft:wired_modem_full_from"></mc-recipe>
* </div>
*/
public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver
{

View File

@ -257,7 +257,7 @@ private void refreshPeripheral()
@Override
public InteractionResult onActivate( Player player, InteractionHand hand, BlockHitResult hit )
{
if( player.isCrouching() ) return InteractionResult.PASS;
if( player.isCrouching() || !player.mayBuild() ) return InteractionResult.PASS;
if( !canAttachPeripheral() ) return InteractionResult.FAIL;
if( getLevel().isClientSide ) return InteractionResult.SUCCESS;

View File

@ -199,6 +199,7 @@ private void refreshPeripheral( @Nonnull Direction facing )
@Override
public InteractionResult onActivate( Player player, InteractionHand hand, BlockHitResult hit )
{
if( player.isCrouching() || !player.mayBuild() ) return InteractionResult.PASS;
if( getLevel().isClientSide ) return InteractionResult.SUCCESS;
// On server, we interacted if a peripheral was found

View File

@ -25,6 +25,12 @@
*
* Like computers, monitors come in both normal (no colour) and advanced (colour) varieties.
*
* ## Recipes
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:monitor_normal"></mc-recipe>
* <mc-recipe recipe="computercraft:monitor_advanced"></mc-recipe>
* </div>
*
* @cc.module monitor
* @cc.usage Write "Hello, world!" to an adjacent monitor:
*

View File

@ -18,6 +18,11 @@
/**
* The printer peripheral allows pages and books to be printed.
*
* ## Recipe
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:printer"></mc-recipe>
* </div>
*
* @cc.module printer
*/
public class PrinterPeripheral implements IPeripheral

View File

@ -41,6 +41,11 @@
* - {@link #playSound} plays any built-in Minecraft sound, such as block sounds or mob noises.
* - {@link #playAudio} can play arbitrary audio.
*
* ## Recipe
* <div class="recipe-container">
* <mc-recipe recipe="computercraft:speaker"></mc-recipe>
* </div>
*
* @cc.module speaker
* @cc.since 1.80pr1
*/

View File

@ -5,21 +5,18 @@
*/
package dan200.computercraft.shared.util;
import com.google.common.collect.MapMaker;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.common.TileGeneric;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
* A thread-safe version of {@link LevelAccessor#scheduleTick(BlockPos, Block, int)}.
@ -33,16 +30,12 @@ private TickScheduler()
{
}
private static final Set<BlockEntity> toTick = Collections.newSetFromMap(
new MapMaker()
.weakKeys()
.makeMap()
);
private static final Queue<TileGeneric> toTick = new ConcurrentLinkedDeque<>();
public static void schedule( TileGeneric tile )
{
Level world = tile.getLevel();
if( world != null && !world.isClientSide ) toTick.add( tile );
if( world != null && !world.isClientSide && !tile.scheduled.getAndSet( true ) ) toTick.add( tile );
}
@SubscribeEvent
@ -50,11 +43,11 @@ public static void tick( TickEvent.ServerTickEvent event )
{
if( event.phase != TickEvent.Phase.START ) return;
Iterator<BlockEntity> iterator = toTick.iterator();
while( iterator.hasNext() )
TileGeneric tile;
while( (tile = toTick.poll()) != null )
{
BlockEntity tile = iterator.next();
iterator.remove();
tile.scheduled.set( false );
if( tile.isRemoved() ) continue;
Level world = tile.getLevel();
BlockPos pos = tile.getBlockPos();

View File

@ -1,4 +1,5 @@
{
"itemGroup.computercraft": "ComputerCraft",
"block.computercraft.computer_normal": "Computer",
"block.computercraft.computer_advanced": "Avanceret Computer",
"block.computercraft.computer_command": "Kommandocomputer",
@ -41,23 +42,22 @@
"gui.computercraft.tooltip.computer_id": "Computer-ID: %s",
"gui.computercraft.tooltip.disk_id": "Disk-ID: %s",
"gui.computercraft.tooltip.turn_on": "Tænd denne computer",
"gui.computercraft.tooltip.turn_on.key": "Hold Ctrl+R nede",
"gui.computercraft.tooltip.turn_off": "Sluk denne computer",
"gui.computercraft.tooltip.terminate.key": "Hold Ctrl+T nede",
"gui.computercraft.tooltip.turn_off.key": "Hold Ctrl+S nede",
"gui.computercraft.tooltip.terminate": "Stop den igangværende kode",
"gui.computercraft.tooltip.turn_on.key": "Hold Ctrl+R nede",
"gui.computercraft.upload.overwrite_button": "Overskriv",
"gui.computercraft.upload.overwrite.detail": "Følgende filer vil blive overskrevet ved upload. Fortsæt?%s",
"gui.computercraft.tooltip.terminate.key": "Hold Ctrl+T nede",
"gui.computercraft.upload.success": "Upload Lykkedes",
"gui.computercraft.upload.overwrite": "Filer ville blive overskrevet",
"gui.computercraft.upload.success.msg": "%d filer uploadet.",
"gui.computercraft.upload.failed": "Upload Fejlede",
"gui.computercraft.upload.failed.out_of_space": "Ikke nok plads på computeren til disse filer.",
"gui.computercraft.upload.failed.computer_off": "Du skal tænde computeren, før du kan uploade filer.",
"gui.computercraft.upload.failed.too_much": "Dine filer er for store til at blive uploadet.",
"gui.computercraft.upload.failed.overwrite_dir": "Kan ikke uploade %s, da der allerede er en mappe med det samme navn.",
"gui.computercraft.upload.success.msg": "%d filer uploadet.",
"gui.computercraft.upload.failed": "Upload Fejlede",
"gui.computercraft.upload.failed.name_too_long": "Filnavne er for lange til at blive uploadet.",
"gui.computercraft.upload.failed.too_many_files": "Kan ikke uploade så mange filer.",
"gui.computercraft.pocket_computer_overlay": "Lommecomputer åben. Tryk ESC for at lukke.",
"itemGroup.computercraft": "ComputerCraft"
"gui.computercraft.upload.failed.overwrite_dir": "Kan ikke uploade %s, da der allerede er en mappe med det samme navn.",
"gui.computercraft.upload.overwrite": "Filer ville blive overskrevet",
"gui.computercraft.upload.overwrite.detail": "Følgende filer vil blive overskrevet ved upload. Fortsæt?%s",
"gui.computercraft.upload.overwrite_button": "Overskriv",
"gui.computercraft.pocket_computer_overlay": "Lommecomputer åben. Tryk ESC for at lukke."
}

View File

@ -0,0 +1,135 @@
{
"itemGroup.computercraft": "ComputerCraft",
"block.computercraft.computer_normal": "Комп'ютер",
"block.computercraft.computer_advanced": "Просунутий комп'ютер",
"block.computercraft.computer_command": "Командний комп'ютер",
"block.computercraft.disk_drive": "Дисковод",
"block.computercraft.printer": "Принтер",
"block.computercraft.speaker": "Колонка",
"block.computercraft.monitor_normal": "Монітор",
"block.computercraft.monitor_advanced": "Просунутий Монітор",
"block.computercraft.wireless_modem_normal": "Бездротовий модем",
"block.computercraft.wireless_modem_advanced": "Ендер модем",
"block.computercraft.wired_modem": "Дротовий модем",
"block.computercraft.cable": "Мережевий кабель",
"block.computercraft.wired_modem_full": "Дротовий модем",
"block.computercraft.turtle_normal": "Черепашка",
"block.computercraft.turtle_normal.upgraded": "%s Черепашка",
"block.computercraft.turtle_normal.upgraded_twice": "%s %s Черепашка",
"block.computercraft.turtle_advanced": "Просунута Черепашка",
"block.computercraft.turtle_advanced.upgraded": "Просунута %s Черепашка",
"block.computercraft.turtle_advanced.upgraded_twice": "Просунута %s %s Черепашка",
"item.computercraft.disk": "Дискета",
"item.computercraft.treasure_disk": "Дискета",
"item.computercraft.printed_page": "Надрукована сторінка",
"item.computercraft.printed_pages": "Надруковані сторінки",
"item.computercraft.printed_book": "Надрукована книжка",
"item.computercraft.pocket_computer_normal": "Кишеньковий комп'ютер",
"item.computercraft.pocket_computer_normal.upgraded": "%s Кишеньковий комп'ютер",
"item.computercraft.pocket_computer_advanced": "Просунутий Кишеньковий комп'ютер",
"item.computercraft.pocket_computer_advanced.upgraded": "Просунутий %s Кишеньковий комп'ютер",
"upgrade.minecraft.diamond_sword.adjective": "Бойова",
"upgrade.minecraft.diamond_shovel.adjective": "Копаюча",
"upgrade.minecraft.diamond_pickaxe.adjective": "Добувна",
"upgrade.minecraft.diamond_axe.adjective": "Рубляча",
"upgrade.minecraft.diamond_hoe.adjective": "Обробна",
"upgrade.minecraft.crafting_table.adjective": "Вміла",
"upgrade.computercraft.wireless_modem_normal.adjective": "Бездротовий",
"upgrade.computercraft.wireless_modem_advanced.adjective": "Ендер",
"upgrade.computercraft.speaker.adjective": "Шумливий",
"chat.computercraft.wired_modem.peripheral_connected": "Периферійний пристрій \\\"%s\\\" підключено до мережі",
"chat.computercraft.wired_modem.peripheral_disconnected": "Периферійний пристрій \\\"%s\\\" відключено від мережі",
"commands.computercraft.synopsis": "Різні команди для керування комп'ютерами.",
"commands.computercraft.desc": "Команда /computercraft надає різні Налагоджувальні та Адміністративні інструменти для управління та взаємодії з комп'ютерами.",
"commands.computercraft.help.synopsis": "Надає допомогу для конкретних команд",
"commands.computercraft.help.desc": "Показує це повідомлення довідки",
"commands.computercraft.help.no_children": "%s не має підкоманд",
"commands.computercraft.help.no_command": "Немає такої команди '%s'",
"commands.computercraft.dump.synopsis": "Відобразити стан комп'ютерів.",
"commands.computercraft.dump.desc": "Відображає стан усіх комп'ютерів або конкретної інформації про один комп'ютер. Ви можете вказати ідентифікатор екземпляра комп'ютера (наприклад 123), ідентифікатор комп'ютера (наприклад #123) або позначку (наприклад, \"@My Computer\").",
"commands.computercraft.dump.action": "Переглянути інформацію про цей комп'ютер",
"commands.computercraft.dump.open_path": "Переглянути файли цього комп'ютера",
"commands.computercraft.shutdown.synopsis": "Віддалено завершити роботу комп'ютерів.",
"commands.computercraft.shutdown.desc": "Завершити роботу перерахованих комп'ютерів або всі, якщо жодного не вказано. Ви можете вказати ідентифікатор екземпляра комп'ютера (наприклад 123), ідентифікатор комп'ютера (наприклад #123) або позначку (наприклад, \"@My Computer\").",
"commands.computercraft.shutdown.done": "У %s/%s комп'ютерів завершено роботу",
"commands.computercraft.turn_on.synopsis": "Увімкнути комп'ютери віддалено.",
"commands.computercraft.turn_on.desc": "Увімкнути перелічені комп'ютери. Ви можете вказати ідентифікатор екземпляра комп'ютера (наприклад 123), ідентифікатор комп'ютера (наприклад #123) або позначку (наприклад, \"@My Computer\").",
"commands.computercraft.turn_on.done": "%s/%s комп'ютерів увімкнено",
"commands.computercraft.tp.synopsis": "Телепортувати до конкретного комп'ютера.",
"commands.computercraft.tp.desc": "Телепортувати до розташування комп'ютера. Ви можете вказати або ідентифікатор екземпляра комп'ютера (наприклад, 123) або ідентифікатор комп'ютера (наприклад, #123).",
"commands.computercraft.tp.action": "Телепортувати до цього комп'ютера",
"commands.computercraft.tp.not_player": "Не можна відкрити термінал для не-гравця",
"commands.computercraft.tp.not_there": "Не можна визначити у світі розташування комп'ютер",
"commands.computercraft.view.synopsis": "Переглянути термінал комп'ютера.",
"commands.computercraft.view.desc": "Відкрити термінал комп'ютера, який дозволяє віддалено керувати комп'ютером. Це не надає доступу до інвентарів черепашок. Ви можете вказати або ідентифікатор екземпляра комп'ютера (наприклад, 123) або ідентифікатор комп'ютера (наприклад, #123).",
"commands.computercraft.view.action": "Переглянути цей комп'ютер",
"commands.computercraft.view.not_player": "Не можна відкрити термінал для не-гравця",
"commands.computercraft.track.synopsis": "Відстеження середовища виконання комп'ютерів.",
"commands.computercraft.track.desc": "Відстежує, як довго комп'ютери виконують, а також те, як багато вони обробляють події. Ця інформація представляється аналогічно /forge track і може бути корисною для діагностики лага.",
"commands.computercraft.track.start.synopsis": "Почати відстеження всіх комп'ютерів",
"commands.computercraft.track.start.desc": "Почати відстеження всіх середовищ виконання комп'ютера та кількість подій. Це скасує результати та попередні запуски.",
"commands.computercraft.track.start.stop": "Запустити %s, щоб зупинити відстеження та переглянути результати",
"commands.computercraft.track.stop.synopsis": "Припинити відстеження всіх комп'ютерів",
"commands.computercraft.track.stop.desc": "Припинити відстеження всіх подій комп'ютера та середовищ виконання",
"commands.computercraft.track.stop.action": "Натисніть, щоб припинити відстеження",
"commands.computercraft.track.stop.not_enabled": "На даний момент немає комп'ютерів, що відстежують.",
"commands.computercraft.track.dump.synopsis": "Вивести останні результати відстеження",
"commands.computercraft.track.dump.desc": "Вивести останні результати відстеження комп'ютера.",
"commands.computercraft.track.dump.no_timings": "Немає доступних розкладів",
"commands.computercraft.track.dump.computer": "Комп'ютер",
"commands.computercraft.reload.synopsis": "Перезавантажити файл конфігурації ComputerCraft'a",
"commands.computercraft.reload.desc": "Перезавантажує файл конфігурації ComputerCraft'a",
"commands.computercraft.reload.done": "Конфігурація перезавантажена",
"commands.computercraft.queue.synopsis": "Надіслати подію computer_command до Командного комп'ютера",
"commands.computercraft.queue.desc": "Надіслати подію computer_command до Командного комп'ютера через додаткові аргументи. В основному це призначено для Картоделів, діє як зручніша для користувача комп'ютерна версія /trigger. Будь-який гравець зможе запустити команду, яка, ймовірно, буде зроблена через події клацання текстового компонента.",
"commands.computercraft.generic.no_position": "<немає позиції>",
"commands.computercraft.generic.position": "%s, %s, %s",
"commands.computercraft.generic.yes": "Y",
"commands.computercraft.generic.no": "N",
"commands.computercraft.generic.exception": "Необроблений виняток (%s)",
"commands.computercraft.generic.additional_rows": "%d додаткових рядків …",
"argument.computercraft.computer.no_matching": "Немає відповідних комп'ютерів з '%s'",
"argument.computercraft.computer.many_matching": "Декілька комп'ютерів відповідають з '%s' (екземпляри %s)",
"argument.computercraft.tracking_field.no_field": "Невідоме поле '%s'",
"argument.computercraft.argument_expected": "Очікується аргумент",
"tracking_field.computercraft.tasks.name": "Завдання",
"tracking_field.computercraft.total.name": "Загальний час",
"tracking_field.computercraft.average.name": "Середній час",
"tracking_field.computercraft.max.name": "Максимальний час",
"tracking_field.computercraft.server_count.name": "Число серверних завдань",
"tracking_field.computercraft.server_time.name": "Час серверних завдань",
"tracking_field.computercraft.peripheral.name": "Виклики периферійних пристроїв",
"tracking_field.computercraft.fs.name": "Операції з файловою системою",
"tracking_field.computercraft.turtle.name": "Операції з черепашкою",
"tracking_field.computercraft.http.name": "HTTP запити",
"tracking_field.computercraft.http_upload.name": "HTTP завантаження",
"tracking_field.computercraft.http_download.name": "HTTP завантаження",
"tracking_field.computercraft.websocket_incoming.name": "Вхідний Websocket",
"tracking_field.computercraft.websocket_outgoing.name": "Вихідний Websocket",
"tracking_field.computercraft.coroutines_created.name": "Співпрограма створена",
"tracking_field.computercraft.coroutines_dead.name": "Співпрограма видалена",
"gui.computercraft.tooltip.copy": "Скопійовано в Буфер обміну",
"gui.computercraft.tooltip.computer_id": "Ідентифікатор комп'ютера: %s",
"gui.computercraft.tooltip.disk_id": "Ідентифікатор диска: %s",
"gui.computercraft.tooltip.turn_on": "Увімкнути цей комп'ютер",
"gui.computercraft.tooltip.turn_on.key": "Утримуй Ctrl+R",
"gui.computercraft.tooltip.turn_off": "Вимкнути цей комп'ютер",
"gui.computercraft.tooltip.turn_off.key": "Утримуй Ctrl+S",
"gui.computercraft.tooltip.terminate": "Припинити поточний запущений код",
"gui.computercraft.tooltip.terminate.key": "Утримуй Ctrl+T",
"gui.computercraft.upload.success": "Завантаження успішне",
"gui.computercraft.upload.success.msg": "%d файлів завантажено.",
"gui.computercraft.upload.failed": "Завантаження не вдалося",
"gui.computercraft.upload.failed.out_of_space": "Недостатньо місця в комп'ютері для цих файлів.",
"gui.computercraft.upload.failed.computer_off": "Ви повинні увімкнути комп'ютер перед завантаженням файлів.",
"gui.computercraft.upload.failed.too_much": "Твої файли надто великі для завантаження.",
"gui.computercraft.upload.failed.name_too_long": "Назви файлів занадто довгі для завантаження.",
"gui.computercraft.upload.failed.too_many_files": "Неможливо завантажити стільки файлів.",
"gui.computercraft.upload.failed.overwrite_dir": "Не можна завантажити %s, оскільки папка з такою самою назвою вже існує.",
"gui.computercraft.upload.failed.generic": "Завантаження файлів не вдалося (%s)",
"gui.computercraft.upload.failed.corrupted": "Файли пошкоджені під час завантаження. Спробуй знову.",
"gui.computercraft.upload.overwrite": "Файли будуть перезаписані",
"gui.computercraft.upload.overwrite.detail": "При завантаженні файли будуть перезаписані. Продовжити?%s",
"gui.computercraft.upload.overwrite_button": "Перезаписати",
"gui.computercraft.pocket_computer_overlay": "Кишеньковий комп'ютер відкритий. Натисніть ESC, щоб закрити."
}

View File

@ -1,3 +1,19 @@
# New features in CC: Tweaked 1.100.6
* Various documentation improvements (MCJack123, FayneAldan).
* Allow CC's blocks to be rotated when used in structure blocks (Seniorendi).
* Several performance improvements to computer execution.
* Add parse_empty_array option to textutils.unserialiseJSON (@ChickChicky).
* Add an API to allow other mods to provide extra item/block details (Lemmmy).
* All blocks with GUIs can now be "locked" (via a command or NBT editing tools) like vanilla inventories. Players can only interact with them with a specific named item.
Several bug fixes:
* Fix printouts being rendered with an offset in item frames (coolsa).
* Reduce position latency when playing audio with a noisy pocket computer.
* Fix total counts in /computercraft turn-on/shutdown commands.
* Fix "Run" command not working in the editor when run from a subdirectory (Wojbie).
* Pocket computers correctly preserve their on state.
# New features in CC: Tweaked 1.100.5
* Generic peripherals now use capabilities on the given side if one isn't provided on the internal side.

View File

@ -1,10 +1,17 @@
New features in CC: Tweaked 1.100.5
New features in CC: Tweaked 1.100.6
* Generic peripherals now use capabilities on the given side if one isn't provided on the internal side.
* Improve performance of monitor rendering.
* Various documentation improvements (MCJack123, FayneAldan).
* Allow CC's blocks to be rotated when used in structure blocks (Seniorendi).
* Several performance improvements to computer execution.
* Add parse_empty_array option to textutils.unserialiseJSON (@ChickChicky).
* Add an API to allow other mods to provide extra item/block details (Lemmmy).
* All blocks with GUIs can now be "locked" (via a command or NBT editing tools) like vanilla inventories. Players can only interact with them with a specific named item.
Several bug fixes:
* Various documentation fixes (bclindner, Hasaabitt)
* Speaker sounds are now correctly positioned on the centre of the speaker block.
* Fix printouts being rendered with an offset in item frames (coolsa).
* Reduce position latency when playing audio with a noisy pocket computer.
* Fix total counts in /computercraft turn-on/shutdown commands.
* Fix "Run" command not working in the editor when run from a subdirectory (Wojbie).
* Pocket computers correctly preserve their on state.
Type "help changelog" to see the full version history.

View File

@ -0,0 +1,38 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.sound;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class DfpwmStreamTest
{
@Test
public void testDecodesBytes()
{
DfpwmStream stream = new DfpwmStream();
ByteBuf input = ByteBufAllocator.DEFAULT.buffer();
input.writeBytes( new byte[] { 43, -31, 33, 44, 30, -16, -85, 23, -3, -55, 46, -70, 68, -67, 74, -96, -68, 16, 94, -87, -5, 87, 11, -16, 19, 92, 85, -71, 126, 5, -84, 64, 17, -6, 85, -11, -1, -87, -12, 1, 85, -56, 33, -80, 82, 104, -93, 17, 126, 23, 91, -30, 37, -32, 117, -72, -58, 11, -76, 19, -108, 86, -65, -10, -1, -68, -25, 10, -46, 85, 124, -54, 15, -24, 43, -94, 117, 63, -36, 15, -6, 88, 87, -26, -83, 106, 41, 13, -28, -113, -10, -66, 119, -87, -113, 68, -55, 40, -107, 62, 20, 72, 3, -96, 114, -87, -2, 39, -104, 30, 20, 42, 84, 24, 47, 64, 43, 61, -35, 95, -65, 42, 61, 42, -50, 4, -9, 81 } );
stream.push( input );
ByteBuffer buffer = stream.read( 1024 + 1 );
assertEquals( 1024, buffer.remaining(), "Must have read 1024 bytes" );
byte[] decoded = new byte[] { 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, -1, -2, -2, -1, 0, 1, 0, -1, -3, -5, -5, -5, -7, -9, -11, -11, -9, -9, -9, -9, -10, -12, -12, -10, -8, -6, -6, -8, -10, -12, -14, -16, -18, -17, -15, -12, -9, -6, -3, -2, -2, -2, -2, -2, -2, 0, 3, 6, 7, 7, 7, 4, 1, 1, 1, 1, 3, 5, 7, 9, 12, 15, 15, 12, 12, 12, 9, 9, 11, 12, 12, 14, 16, 17, 17, 17, 14, 11, 11, 11, 10, 12, 14, 14, 13, 13, 10, 9, 9, 7, 5, 4, 4, 4, 4, 4, 6, 8, 10, 10, 10, 10, 10, 10, 10, 9, 8, 8, 8, 7, 6, 4, 2, 0, 0, 0, 0, 0, -1, -1, 0, 1, 3, 3, 3, 3, 2, 0, -2, -2, -2, -3, -5, -7, -7, -5, -3, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1, 0, 1, 1, 1, 2, 3, 4, 5, 6, 7, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 9, 8, 7, 6, 4, 2, 0, 0, 2, 4, 6, 8, 10, 10, 8, 7, 7, 5, 3, 1, -1, 0, 2, 4, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 4, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 9, 9, 9, 9, 9, 8, 7, 6, 5, 3, 1, 1, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -3, -3, -3, -3, -2, -3, -4, -4, -3, -4, -5, -6, -6, -5, -5, -4, -3, -2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 20, 17, 16, 16, 15, 15, 15, 15, 13, 13, 13, 13, 14, 15, 16, 18, 18, 16, 14, 12, 10, 8, 5, 5, 5, 4, 4, 4, 4, 4, 4, 2, 0, -2, -2, -2, -4, -4, -2, 0, 0, -2, -4, -6, -6, -6, -8, -10, -12, -14, -16, -15, -13, -12, -11, -11, -11, -11, -13, -13, -13, -13, -13, -14, -16, -18, -18, -18, -18, -16, -16, -16, -14, -13, -14, -15, -15, -14, -14, -12, -11, -12, -13, -13, -12, -13, -14, -15, -15, -13, -11, -9, -7, -5, -5, -5, -3, -1, -1, -1, -1, -3, -5, -5, -3, -3, -3, -1, -1, -1, -1, -3, -3, -3, -4, -6, -6, -4, -2, 0, 0, 0, 0, -2, -2, -2, -3, -5, -7, -9, -11, -13, -13, -11, -9, -7, -6, -6, -6, -6, -4, -2, -2, -4, -6, -8, -7, -5, -3, -2, -2, -2, -2, 0, 0, -2, -4, -4, -2, 0, 2, 2, 1, 1, -1, -3, -5, -7, -10, -10, -10, -10, -8, -7, -7, -5, -3, -2, -4, -4, -4, -6, -8, -10, -12, -12, -12, -12, -12, -14, -13, -13, -13, -11, -11, -11, -11, -11, -11, -11, -9, -7, -5, -3, -1, -1, -1, -1, -1, 1, 1, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 22, 19, 18, 20, 22, 24, 23, 22, 24, 26, 28, 27, 24, 23, 25, 28, 28, 28, 27, 26, 26, 23, 20, 17, 14, 14, 14, 11, 11, 11, 11, 13, 15, 16, 16, 16, 15, 15, 14, 14, 12, 10, 9, 11, 13, 15, 17, 17, 14, 13, 13, 12, 12, 10, 9, 11, 13, 15, 17, 19, 19, 16, 13, 10, 7, 4, 1, 1, 2, 2, 4, 7, 10, 13, 13, 13, 12, 12, 12, 9, 6, 6, 6, 3, 0, 0, 0, 0, 2, 3, 3, 3, 3, 5, 7, 7, 7, 9, 11, 13, 15, 18, 18, 15, 12, 9, 8, 10, 13, 13, 13, 15, 18, 21, 24, 27, 27, 23, 19, 15, 11, 10, 9, 9, 12, 16, 19, 22, 23, 19, 14, 13, 16, 16, 15, 15, 14, 17, 20, 20, 19, 19, 18, 17, 14, 13, 15, 15, 12, 11, 13, 16, 19, 19, 18, 20, 20, 19, 18, 18, 17, 17, 16, 16, 16, 15, 17, 17, 16, 16, 13, 12, 12, 11, 11, 9, 9, 9, 9, 11, 11, 9, 7, 5, 3, 1, 1, 1, -1, -1, 1, 3, 5, 7, 9, 11, 12, 9, 6, 6, 6, 6, 8, 8, 7, 9, 11, 13, 13, 12, 14, 16, 18, 20, 20, 20, 22, 24, 26, 25, 25, 27, 29, 28, 27, 26, 23, 22, 22, 21, 21, 20, 22, 24, 26, 28, 27, 24, 21, 21, 21, 18, 17, 17, 14, 11, 11, 11, 10, 10, 7, 6, 6, 4, 3, 5, 5, 3, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 2, 3, 4, 3, 1, -1, -3, -3, -3, -3, -2, -3, -4, -6, -8, -10, -10, -10, -12, -12, -12, -12, -10, -10, -11, -12, -14, -16, -18, -20, -22, -24, -26, -28, -27, -27, -26, -26, -25, -25, -27, -26, -24, -22, -22, -22, -22, -24, -24, -24, -24, -23, -23, -22, -22, -21, -20, -19, -17, -15, -13, -11, -9, -7, -7, -9, -9, -9, -11, -13, -15, -17, -16, -14, -13, -15, -14, -14, -14, -12, -10, -8, -7, -9, -11, -13, -15, -14, -14, -13, -13, -15, -17, -19, -18, -18, -17, -17, -16, -16, -18, -20, -22, -21, -21, -21, -21, -21, -20, -21, -22, -24, -24, -22, -22, -24, -26, -25, -23, -21, -19, -18, -17, -17, -19, -21, -23, -25, -27, -29, -31, -30, -29, -28, -26, -25, -24, -24, -23, -23, -25, -24, -24, -24, -22, -20, -18, -18, -20, -20, -20, -20, -18, -16, -16, -16, -14, -12, -10, -8, -6, -4, -4, -4, -4, -4, -2, 0, 2, 4, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 4, 5, 6, 5, 3, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, -1, -2, -3, -4, -4, -2, 0, 0, 0, 1, 3, 5, 7, 7, 5, 3, 3, 3, 3, 3 };
for( int i = 0; i < 1024; i++ )
{
assertEquals( (byte) (decoded[i] ^ 0x80), buffer.get(), "Bad element at " + i );
}
assertEquals( 0, buffer.remaining(), "Must have read all bytes" );
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,151 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.export;
import com.google.common.io.MoreFiles;
import com.google.common.io.RecursiveDeleteOption;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.ingame.mod.TestMod;
import net.minecraft.client.Minecraft;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.registries.ForgeRegistries;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
/**
* Provides a {@literal /ccexport <path>} command which exports icons and recipes for all ComputerCraft items.
*/
@Mod.EventBusSubscriber( modid = TestMod.MOD_ID, value = Dist.CLIENT )
public class Exporter
{
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
@SubscribeEvent
public static void onClientCommands( ClientChatEvent event )
{
String prefix = "/ccexport";
if( !event.getMessage().startsWith( prefix ) ) return;
event.setCanceled( true );
Path output = new File( event.getMessage().substring( prefix.length() ).trim() ).getAbsoluteFile().toPath();
if( !Files.isDirectory( output ) )
{
Minecraft.getInstance().gui.getChat().addMessage( new TextComponent( "Output path does not exist" ) );
return;
}
RenderSystem.assertOnRenderThread();
try( ImageRenderer renderer = new ImageRenderer() )
{
export( output, renderer );
}
catch( IOException e )
{
throw new UncheckedIOException( e );
}
Minecraft.getInstance().gui.getChat().addMessage( new TextComponent( "Export finished!" ) );
}
private static void export( Path root, ImageRenderer renderer ) throws IOException
{
JsonDump dump = new JsonDump();
Set<Item> items = new HashSet<>();
// First find all CC items
for( Item item : ForgeRegistries.ITEMS.getValues() )
{
if( item.getRegistryName().getNamespace().equals( ComputerCraft.MOD_ID ) ) items.add( item );
}
// Now find all CC recipes.
for( CraftingRecipe recipe : Minecraft.getInstance().level.getRecipeManager().getAllRecipesFor( RecipeType.CRAFTING ) )
{
ItemStack result = recipe.getResultItem();
if( !result.getItem().getRegistryName().getNamespace().equals( ComputerCraft.MOD_ID ) ) continue;
if( result.hasTag() )
{
ComputerCraft.log.warn( "Skipping recipe {} as it has NBT", recipe.getId() );
continue;
}
if( recipe instanceof ShapedRecipe shaped )
{
JsonDump.Recipe converted = new JsonDump.Recipe( result );
for( int x = 0; x < shaped.getWidth(); x++ )
{
for( int y = 0; y < shaped.getHeight(); y++ )
{
Ingredient ingredient = shaped.getIngredients().get( x + y * shaped.getWidth() );
if( ingredient.isEmpty() ) continue;
converted.setInput( x + y * 3, ingredient, items );
}
}
dump.recipes.put( recipe.getId().toString(), converted );
}
else if( recipe instanceof ShapelessRecipe shapeless )
{
JsonDump.Recipe converted = new JsonDump.Recipe( result );
NonNullList<Ingredient> ingredients = shapeless.getIngredients();
for( int i = 0; i < ingredients.size(); i++ )
{
converted.setInput( i, ingredients.get( i ), items );
}
dump.recipes.put( recipe.getId().toString(), converted );
}
else
{
ComputerCraft.log.info( "Don't know how to handle recipe {}", recipe );
}
}
Path itemDir = root.resolve( "items" );
if( Files.exists( itemDir ) ) MoreFiles.deleteRecursively( itemDir, RecursiveDeleteOption.ALLOW_INSECURE );
renderer.setupState();
for( Item item : items )
{
ItemStack stack = new ItemStack( item );
dump.itemNames.put( item.getRegistryName().toString(), stack.getHoverName().getString() );
ResourceLocation location = item.getRegistryName();
renderer.captureRender( itemDir.resolve( location.getNamespace() ).resolve( location.getPath() + ".png" ),
() -> Minecraft.getInstance().getItemRenderer().renderAndDecorateFakeItem( stack, 0, 0 )
);
}
renderer.clearState();
try( Writer writer = Files.newBufferedWriter( root.resolve( "index.json" ) ) )
{
GSON.toJson( dump, writer );
}
}
}

View File

@ -0,0 +1,80 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.export;
import com.mojang.blaze3d.pipeline.TextureTarget;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.math.Matrix4f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.FogRenderer;
import org.lwjgl.opengl.GL12;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Utilities for saving OpenGL output to an image rather than displaying it on the screen.
*/
public class ImageRenderer implements AutoCloseable
{
public static final int WIDTH = 64;
public static final int HEIGHT = 64;
private final TextureTarget framebuffer = new TextureTarget( WIDTH, HEIGHT, true, Minecraft.ON_OSX );
private final NativeImage image = new NativeImage( WIDTH, HEIGHT, Minecraft.ON_OSX );
private Matrix4f projectionMatrix;
public ImageRenderer()
{
framebuffer.setClearColor( 0, 0, 0, 0 );
framebuffer.clear( Minecraft.ON_OSX );
}
public void setupState()
{
projectionMatrix = RenderSystem.getProjectionMatrix();
RenderSystem.setProjectionMatrix( Matrix4f.orthographic( 0, 16, 0, 16, 1000, 3000 ) );
var transform = RenderSystem.getModelViewStack();
transform.setIdentity();
transform.translate( 0.0f, 0.0f, -2000.0f );
FogRenderer.setupNoFog();
}
public void clearState()
{
RenderSystem.setProjectionMatrix( projectionMatrix );
RenderSystem.getModelViewStack().popPose();
}
public void captureRender( Path output, Runnable render ) throws IOException
{
Files.createDirectories( output.getParent() );
framebuffer.bindWrite( true );
RenderSystem.clear( GL12.GL_COLOR_BUFFER_BIT | GL12.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX );
render.run();
framebuffer.unbindWrite();
framebuffer.bindRead();
image.downloadTexture( 0, false );
image.flipY();
framebuffer.unbindRead();
image.writeToFile( output );
}
@Override
public void close()
{
image.close();
framebuffer.destroyBuffers();
}
}

View File

@ -0,0 +1,65 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.export;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import java.util.*;
public class JsonDump
{
public Map<String, String> itemNames = new TreeMap<>();
public Map<String, Recipe> recipes = new TreeMap<>();
public static class Recipe
{
public final String[][] inputs = new String[9][];
public String output;
public int count;
public Recipe( ItemStack output )
{
this.output = output.getItem().getRegistryName().toString();
count = output.getCount();
}
public void setInput( int pos, Ingredient ingredient, Set<Item> trackedItems )
{
if( ingredient.isEmpty() ) return;
ItemStack[] items = ingredient.getItems();
// First try to simplify some tags to something easier.
for( ItemStack stack : items )
{
Item item = stack.getItem();
if( !canonicalItem.contains( item ) ) continue;
trackedItems.add( item );
inputs[pos] = new String[] { item.getRegistryName().toString() };
return;
}
String[] itemIds = new String[items.length];
for( int i = 0; i < items.length; i++ )
{
Item item = items[i].getItem();
trackedItems.add( item );
itemIds[i] = item.getRegistryName().toString();
}
Arrays.sort( itemIds );
inputs[pos] = itemIds;
}
private static final Set<Item> canonicalItem = new HashSet<>( Arrays.asList(
Items.GLASS_PANE, Items.STONE, Items.CHEST
) );
}
}

View File

@ -0,0 +1,46 @@
import type { FunctionComponent } from "react";
import { createElement as h } from "react";
import useExport from "./WithExport.js";
const Item: FunctionComponent<{ item: string }> = ({ item }) => {
const data = useExport();
const itemName = data.itemNames[item];
return <img
src={`/images/items/${item.replace(":", "/")}.png`}
alt={itemName}
title={itemName}
className="recipe-icon"
/>
};
const EmptyItem: FunctionComponent = () => <span className="recipe-icon " />;
const Arrow: FunctionComponent<JSX.IntrinsicElements["svg"]> = (props) => <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 45.513 45.512" {...props}>
<g>
<path d="M44.275,19.739L30.211,5.675c-0.909-0.909-2.275-1.18-3.463-0.687c-1.188,0.493-1.959,1.654-1.956,2.938l0.015,5.903
l-21.64,0.054C1.414,13.887-0.004,15.312,0,17.065l0.028,11.522c0.002,0.842,0.338,1.648,0.935,2.242s1.405,0.927,2.247,0.925
l21.64-0.054l0.014,5.899c0.004,1.286,0.781,2.442,1.971,2.931c1.189,0.487,2.557,0.21,3.46-0.703L44.29,25.694
C45.926,24.043,45.92,21.381,44.275,19.739z" fill="var(--recipe-hover)" />
</g>
</svg>;
const Recipe: FunctionComponent<{ recipe: string }> = ({ recipe }) => {
const data = useExport();
const recipeInfo = data.recipes[recipe];
if (!recipeInfo) throw Error("Cannot find recipe for " + recipe);
return <div className="recipe">
<strong className="recipe-title">{data.itemNames[recipeInfo.output]}</strong>
<div className="recipe-inputs">
{recipeInfo.inputs.map((items, i) => <div className="recipe-item recipe-input" key={i}>{items ? <Item item={items[0]} /> : <EmptyItem />}</div>)}
</div>
<Arrow className="recipe-arrow" />
<div className="recipe-item recipe-output">
<Item item={recipeInfo.output} />
{recipeInfo.count > 1 && <span className="recipe-count">{recipeInfo.count}</span>}
</div>
</div>
};
export default Recipe;

View File

@ -0,0 +1,23 @@
import { createElement as h, useContext, createContext, FunctionComponent, ReactNode } from "react";
export type DataExport = {
readonly itemNames: Record<string, string>,
readonly recipes: Record<string, Recipe>,
};
export type Recipe = {
readonly inputs: Array<Array<string>>,
readonly output: string,
readonly count: number,
};
const DataExport = createContext<DataExport>({
itemNames: {},
recipes: {},
});
export const useExport = () => useContext(DataExport);
export default useExport;
export const WithExport: FunctionComponent<{ data: DataExport, children: ReactNode }> =
({ data, children }) => <DataExport.Provider value={data}> {children}</DataExport.Provider >;

View File

@ -0,0 +1,25 @@
import type { FunctionComponent } from "react";
/**
* Wrap a component and ensure that no children are passed to it.
*
* Our custom tags *must* be explicitly closed, as <foo /> will be parsed as
* <foo>(rest of the document)</foo>. This ensures you've not forgotten to do
* that.
*
* @param component The component to wrap
* @returns A new functional component identical to the previous one
*/
export const noChildren = function <T>(component: FunctionComponent<T>): FunctionComponent<T> {
// I hope that our few remaining friends
// Give up on trying to save us
const name = component.displayName ?? component.name;
const wrapped: FunctionComponent<T> = props => {
if ((props as any).children) throw Error("Unexpected children in " + name);
return component(props);
};
wrapped.displayName = name;
return wrapped;
}

View File

@ -9,8 +9,6 @@ import exampleNft from "./mount/example.nft";
import exampleAudioLicense from "./mount/example.dfpwm.LICENSE";
import exampleAudioUrl from "./mount/example.dfpwm";
import "./prism.js";
const defaultFiles: { [filename: string]: string } = {
".settings": settingsFile,
"startup.lua": startupFile,

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,8 @@ table {
width: 100%;
}
table td, table th {
table td,
table th {
border: 1px solid #cccccc;
padding: 2px 4px;
}
@ -38,7 +39,7 @@ pre.highlight {
position: fixed;
z-index: 200;
top: 0px;
top: 0px;;
top: 0px;
}
/* Behold, the most cursed CSS! copy-cat's resizing algorithm is a weird, in
@ -78,7 +79,9 @@ pre.highlight {
font-size: 15px;
}
.titlebar-close:hover { background: #cc4c4c; }
.titlebar-close:hover {
background: #cc4c4c;
}
@media (max-width: 700px) {
.computer-container {
@ -86,6 +89,89 @@ pre.highlight {
height: calc(179px + 40px);
}
.titlebar { height: 20px; }
.titlebar-close { font-size: 7px; }
.titlebar {
height: 20px;
}
.titlebar-close {
font-size: 7px;
}
}
:root {
--recipe-bg: #ddd;
--recipe-fg: #bbb;
--recipe-hover: #aaa;
--recipe-padding: 4px;
--recipe-size: 32px;
}
.recipe-container {
display: flex;
justify-content: center;
margin: 1em 0;
gap: 1em;
flex-wrap: wrap;
}
.recipe {
display: inline-grid;
padding: var(--recipe-padding);
background: var(--recipe-bg);
column-gap: var(--recipe-padding);
row-gap: var(--recipe-padding);
grid-template-rows: auto auto;
grid-template-columns: max-content 1fr max-content;
}
.recipe-title {
color: #222; /* Same as --foreground in light theme. Ugly, but too lazy to style in dark for now. */
grid-column-start: span 3;
}
.recipe-inputs {
display: inline-grid;
column-gap: var(--recipe-padding);
row-gap: var(--recipe-padding);
align-items: center;
grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
.recipe-item {
padding: var(--recipe-padding);
background-color: var(--recipe-fg);
}
.recipe-item:hover {
background-color: var(--recipe-hover);
}
.recipe-icon {
display: block;
width: var(--recipe-size);
height: var(--recipe-size);
max-width: 10vw;
max-height: 10vw;
}
.recipe-arrow {
width: var(--recipe-size);
max-width: 10vw;
align-self: center;
}
.recipe-output {
align-self: center;
position: relative;
}
.recipe-count {
position: absolute;
bottom: 0;
right: var(--recipe-padding);
color: #fff;
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000
}

53
src/web/transform.tsx Normal file
View File

@ -0,0 +1,53 @@
/**
* Find all HTML files generated by illuaminate and pipe them through a remark.
*
* This performs compile-time syntax highlighting and expands our custom
* components using React SSR.
*
* Yes, this would be so much nicer with next.js.
*/
import * as fs from "fs/promises";
import globModule from "glob";
import * as path from "path";
import { createElement, createElement as h, Fragment } from 'react';
import { renderToStaticMarkup } from "react-dom/server";
import rehypeHighlight from "rehype-highlight";
import rehypeParse from 'rehype-parse';
import rehypeReact from 'rehype-react';
import { unified } from 'unified';
import { promisify } from "util";
// Our components
import Recipe from "./components/Recipe.js";
import { noChildren } from "./components/support.js";
import { DataExport, WithExport } from "./components/WithExport.js";
const glob = promisify(globModule);
(async () => {
const base = "build/docs/lua";
const processor = unified()
.use(rehypeParse, { emitParseErrors: true })
.use(rehypeHighlight, { prefix: "" })
.use(rehypeReact, {
createElement,
Fragment,
passNode: false,
components: {
['mc-recipe']: noChildren(Recipe),
['mcrecipe']: noChildren(Recipe),
} as any
});
const dataExport = JSON.parse(await fs.readFile("src/generated/export/index.json", "utf-8")) as DataExport;
for (const file of await glob(base + "/**/*.html")) {
const contents = await fs.readFile(file, "utf-8");
const { result } = await processor.process(contents);
const outputPath = path.resolve("build/docs/site", path.relative(base, file));
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, "<!doctype HTML>" + renderToStaticMarkup(<WithExport data={dataExport}>{result}</WithExport>));
}
})();

View File

@ -22,6 +22,9 @@
"noFallthroughCasesInSwitch": true,
"importsNotUsedAsValues": "error",
"forceConsistentCasingInFileNames": true,
// Needed for some of our internal stuff.
"allowSyntheticDefaultImports": true,
},
"include": [
"src/web",