add page: differences to other languages
This commit is contained in:
parent
5755dc5adf
commit
4f7be96abe
|
@ -19,7 +19,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout your repository using git
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Install, build, and upload your site output
|
||||
uses: withastro/action@v2
|
||||
with:
|
||||
|
|
|
@ -5,6 +5,7 @@ import shikiConfig from './src/utils/shiki';
|
|||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: "https://shulkerscript.hoelting.dev",
|
||||
integrations: [
|
||||
starlight({
|
||||
title: 'ShulkerScript',
|
||||
|
@ -49,6 +50,13 @@ export default defineConfig({
|
|||
de: 'Anleitungen',
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Differences to other languages',
|
||||
link: '/differences',
|
||||
translations: {
|
||||
de: 'Unterschiede zu anderen Sprachen',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Roadmap',
|
||||
link: '/roadmap',
|
||||
|
|
10
package.json
10
package.json
|
@ -10,11 +10,11 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.5.10",
|
||||
"@astrojs/starlight": "^0.24.2",
|
||||
"astro": "^4.10.2",
|
||||
"sharp": "^0.32.6",
|
||||
"starlight-links-validator": "^0.7.1",
|
||||
"@astrojs/check": "^0.9.3",
|
||||
"@astrojs/starlight": "^0.26.1",
|
||||
"astro": "^4.14.3",
|
||||
"sharp": "^0.33.5",
|
||||
"starlight-links-validator": "^0.10.1",
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
}
|
1924
pnpm-lock.yaml
1924
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
export interface Props {
|
||||
gap: string
|
||||
}
|
||||
const { gap = "0px" } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="split-view" style={`gap: ${gap}`}>
|
||||
<slot name="left" />
|
||||
<slot name="right" />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.split-view {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.split-view > :global(*) {
|
||||
overflow: hidden;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,313 @@
|
|||
---
|
||||
title: Differences to other languages
|
||||
description: See how ShulkerScript compares to similar languages.
|
||||
---
|
||||
|
||||
import { Tabs, TabItem, Aside } from "@astrojs/starlight/components";
|
||||
import SplitView from "@components/SplitView.astro";
|
||||
|
||||
This page will highlight the differences of ShulkerScript and vanilla mcfunction and mcscript.
|
||||
|
||||
:::note[Credits to mcscript]
|
||||
I came into contact with [mcscript](https://mcscript.stevertus.com/) by Stevertus a few years ago. I wrote some datapacks
|
||||
with it myself and it was mostly great, but I came across some of its flaws. This inspired me to write my own
|
||||
language, even if it is years later. This comparison should not be seen as too critical, as it seems to be not
|
||||
under active development anymore. If you are interested, check out his new project [objD](https://objd.stevertus.com).
|
||||
:::
|
||||
|
||||
## Functions
|
||||
|
||||
The first difference you can see is that ShulkerScript takes a much different approach to functions than mcfunction and mcscript.
|
||||
The following example declares two functions and calls them second from the first one.
|
||||
|
||||
<SplitView gap="10px">
|
||||
<Tabs slot="left">
|
||||
<TabItem label="ShulkerScript">
|
||||
```shulkerscript
|
||||
// functions.shu
|
||||
#[load]
|
||||
fn first() {
|
||||
second();
|
||||
}
|
||||
|
||||
fn second() {
|
||||
/say Hello, world!
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs slot="right" syncKey="comparisonLang" style="margin-top: 0">
|
||||
<TabItem label="mcfunction">
|
||||
```mcfunction
|
||||
# functions/first.mcfunction
|
||||
function functions:second
|
||||
```
|
||||
```mcfunction
|
||||
# functions/second.mcfunction
|
||||
say Hello, world!
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="mcscript">
|
||||
```mcscript
|
||||
// functions.mcscript
|
||||
#file: first
|
||||
/function functions:second
|
||||
|
||||
#file: second
|
||||
/say Hello, world!
|
||||
```
|
||||
or alternatively
|
||||
```mcscript
|
||||
// functions.mcscript
|
||||
#file: first
|
||||
run function second {
|
||||
/say Hello, world!
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
</SplitView>
|
||||
|
||||
## Comments
|
||||
|
||||
Comments can be expressed differently in all three languages. ShulkerScript uses `//` for single-line comments and `/* */` for multi-line comments.
|
||||
|
||||
<SplitView gap="10px">
|
||||
<Tabs slot="left">
|
||||
<TabItem label="ShulkerScript">
|
||||
```shulkerscript
|
||||
// comments.shu
|
||||
// this is a comment
|
||||
fn hello() {
|
||||
/// this comment will be included in the compiled output
|
||||
/*
|
||||
this is a
|
||||
multi-line comment
|
||||
*/
|
||||
/say Hello, world!
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs slot="right" syncKey="comparisonLang" style="margin-top: 0">
|
||||
<TabItem label="mcfunction">
|
||||
```mcfunction
|
||||
# comments.mcfunction
|
||||
# this is a comment
|
||||
# multiline comments have to be done manually
|
||||
say Hello, world!
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="mcscript">
|
||||
```mcscript
|
||||
// comments.mcscript
|
||||
// this is a regular comment
|
||||
# this comment will be included in the compiled output
|
||||
/*
|
||||
this is a
|
||||
multi-line comment
|
||||
*/
|
||||
/say Hello, world!
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
</SplitView>
|
||||
|
||||
## Execute Command
|
||||
|
||||
Both ShulkerScript and mcfunction offer an easier way for using execute commands, as they are common when building datapacks.
|
||||
|
||||
<SplitView gap="10px">
|
||||
<Tabs slot="left">
|
||||
<TabItem label="ShulkerScript">
|
||||
```shulkerscript
|
||||
// execute.shu
|
||||
fn execute() {
|
||||
as("@a"), at("@s") {
|
||||
/setblock ~ ~-1 ~ minecraft:stone
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs slot="right" syncKey="comparisonLang" style="margin-top: 0">
|
||||
<TabItem label="mcfunction">
|
||||
```mcfunction
|
||||
# execute.mcfunction
|
||||
execute as @a at @s run setblock ~ ~-1 ~ minecraft:stone
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="mcscript">
|
||||
```mcscript
|
||||
// execute.mcscript
|
||||
as(@a), at(@s) {
|
||||
/setblock ~ ~-1 ~ minecraft:stone
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
</SplitView>
|
||||
|
||||
:::tip
|
||||
ShulkerScript and mcscript each offer a shortcut for `as(...), at("@s")`, which is `asat(@a)`.
|
||||
:::
|
||||
|
||||
## If-Else Statements
|
||||
|
||||
ShulkerScript and mcscript offer a more convenient way to write if-else statements.
|
||||
|
||||
<SplitView gap="10px">
|
||||
<Tabs slot="left">
|
||||
<TabItem label="ShulkerScript">
|
||||
```shulkerscript
|
||||
// conditionals.shu
|
||||
fn conditional() {
|
||||
if("entity @p[distance=..5]") {
|
||||
/say You are close!
|
||||
} else {
|
||||
/say You are far away!
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<div slot="right">
|
||||
<Tabs syncKey="comparisonLang" style="margin-top: 0">
|
||||
<TabItem label="mcfunction">
|
||||
```mcfunction
|
||||
# conditionals.mcfunction
|
||||
execute if entity @p[distance=..5] run say You are close!
|
||||
execute unless entity @p[distance=..5] run say You are far away!
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="mcscript">
|
||||
```mcscript
|
||||
// conditionals.mcscript
|
||||
if('entity @p[distance=..5]') {
|
||||
/say You are close!
|
||||
} else {
|
||||
/say You are far away!
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Aside type="caution" title="This does not always work!">
|
||||
When working with else statements and/or commands that could affect the condition,
|
||||
both the mcfunction and mcscript approach could lead to unexpected results as explained [here](#interfering-with-conditions).
|
||||
</Aside>
|
||||
</div>
|
||||
</SplitView>
|
||||
|
||||
### Logical operators
|
||||
|
||||
Both in ShulkerScript and mcscript, logical operators can be used to combine multiple conditions.
|
||||
In the following code examples, the conditions are represented by `A`, `B`, etc. as placeholders for real conditions.
|
||||
|
||||
<SplitView gap="10px">
|
||||
<div slot="left">
|
||||
<Tabs>
|
||||
<TabItem label="ShulkerScript">
|
||||
```shulkerscript
|
||||
// logical-operators.shu
|
||||
fn logical() {
|
||||
if("A" && "B" || "C") {
|
||||
/say A and B or C
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
The AND operator takes precedence over the OR operator, so the above code is equivalent to `A && (B || C)`.
|
||||
The code is compiled in such a way, that regardless in which way the expression is true, the command will only run once.
|
||||
</div>
|
||||
<div slot="right">
|
||||
<Tabs syncKey="comparisonLang" style="margin-top: 0">
|
||||
<TabItem label="mcfunction">
|
||||
```mcfunction
|
||||
# logical-operators.mcfunction
|
||||
execute if A if B run say A and B or C
|
||||
execute if C run say A and B or C
|
||||
```
|
||||
<Aside>
|
||||
This leads to a lot of repetition, especially when combining AND and OR operators.
|
||||
</Aside>
|
||||
</TabItem>
|
||||
<TabItem label="mcscript">
|
||||
```mcscript
|
||||
// logical-operators.mcscript
|
||||
if(('A' && 'B') || 'C') {
|
||||
/say A and B or C
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Aside type="caution" title="">
|
||||
If both `A && B` and `C` are true, the command will run two times!
|
||||
</Aside>
|
||||
</div>
|
||||
</SplitView>
|
||||
|
||||
### Interfering with conditions
|
||||
|
||||
The difference between ShulkerScript and the other two languages is that ShulkerScript compiles to a version
|
||||
where it is not possible to trigger both the if and the else statement at the same time.
|
||||
This could be possible when using the trivial approach to translate the following to mcfunction:
|
||||
|
||||
```shulkerscript
|
||||
// this-works.shu
|
||||
fn thisWorks() {
|
||||
if("block ~ ~-1 ~ minecraft:stone") {
|
||||
/setblock ~ ~-1 ~ minecraft:cobblestone
|
||||
} else {
|
||||
/say Not on stone
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here the second command will always be executed, because if the condition is true, the command runs and falsifies the condition.
|
||||
When the inverted condition is checked in the second command, it will always be true.
|
||||
ShulkerScript fixes this by using a mix of anonymous functions and data stores.
|
||||
|
||||
```mcfunction
|
||||
# this-is-incorrect.mcfunction
|
||||
execute if block ~ ~-1 ~ minecraft:stone run setblock ~ ~-1 ~ minecraft:cobblestone
|
||||
# this will always execute because after the first command the block cannot be stone
|
||||
execute unless block ~ ~-1 ~ minecraft:stone run say Not on stone
|
||||
```
|
||||
|
||||
## Embedded Programming Language
|
||||
|
||||
ShulkerScript allows running Lua code during compilation and running the returned output in Minecraft, mcscript offers JavaScript modals._createMdxContent
|
||||
|
||||
<SplitView gap="10px">
|
||||
<Tabs slot="left">
|
||||
<TabItem label="ShulkerScript">
|
||||
```shulkerscript
|
||||
// lua.shu
|
||||
fn execute() {
|
||||
run lua() {
|
||||
return "say hi";
|
||||
};
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
<Tabs slot="right" syncKey="comparisonLang" style="margin-top: 0">
|
||||
<TabItem label="mcfunction">
|
||||
<Aside>
|
||||
Vanilla mcfunction does not support embedded programming languages.
|
||||
</Aside>
|
||||
</TabItem>
|
||||
<TabItem label="mcscript">
|
||||
```mcscript
|
||||
// javascript.mcscript
|
||||
modaljs newModal(){
|
||||
return "say hi";
|
||||
}
|
||||
|
||||
newModal()
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
</SplitView>
|
|
@ -1,3 +1,12 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@*": ["src/*"]
|
||||
},
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
},
|
||||
"exclude": ["dist", "node_modules"]
|
||||
}
|
Loading…
Reference in New Issue