This commit is contained in:
zongor 2025-04-19 13:51:32 -04:00
parent 33dd1cb809
commit 9c1d79812d
17 changed files with 795 additions and 214 deletions

View File

@ -18,14 +18,10 @@ tfff xxxx yyyy zzzz
0rgb xxxx yyyy zzzz
mmrr rggg bbbx xxx xxxy yyyy yyzz zzzzz
mmrr rrrg ggb0 0000 {xxxx xxxx yyyy yyyy zzzz zzzz} {xxxx xxxx yyyy yyyy zzzz zzzz} vz{xxxx xxxx yyyy yyyy zzzz zzzz}
rrrx gggy bbbz xxxx yyyy zzzz
#### 3 bit rgb
rgba xxxx xxyy yyyy
#### 3-3-2 bit rgb
rrrg ggbb xxxx yyyy

View File

@ -2,19 +2,12 @@
## What is _ztl_?
_ztl_ is an language transpiler with C/Zig/Rust style syntax. The transpiler bootstrap is written in Lua which should make it easy to port to other systems. _ztl_ also can "run" standalone inside of a lua vm for debugging purposes, it could be used for small scripting tasks or the like.
_ztl_ is an language transpiler with C/Lua style syntax. The transpiler bootstrap is written in Lua which should make it easy to port to other systems. _ztl_ also can "run" standalone inside of a lua vm for debugging purposes, it could be used for small scripting tasks or the like.
# _ztl_ Grammar and Specification
## Types
- Types can be either structs, enums, or unions.
- struct
- holds data
- union
- holds different kinds of data
- enum
- holds a key to integer map of data
- there are also a list of "substantial types" which come with the language which are the building blocks for more complex types. If you are coming from object oriented languages you can think of self as "primitive types"
```
@ -81,29 +74,29 @@ Also follows the style boolean 'c' rules of nonzero / zero, but the compiler wil
error is a type which describes an error that occurred, it is similar to the Go programming language and is returned as a monad like the maybe monad above and is unwrapped in a similar way. You could also think of it as every variable being able to have "the type" and also "error" as a possible value.
```
let error = %"something borked"
let some_var = error ?? 0;
let some_var = error ?? panic(error)
set error to %"something borked";
set some_var to error ?? 0;
set some_var to error ?? panic(error);
```
## datastructure
Much like Lua, zwl only has tables. Lua's tables are amazing and very unique. Why have five different datastructures to do things when you can just have one that does everything?
Types that can be indexes are numbers and strings (no objects);
### table
syntax (yes I was nice and kept the syntax the same as most C like langs)
```
let «variable»: «type»[] ! same as a map of int->«type»
! array same as a map of int->«type»
!or as an array
let «variable» = [val1, val2, ...]
set «variable» to [val1, val2, ...] as «type»[];
! or as a map
let «variable»: «type»->«type» = {key1: val1, key2: val2, ...}
set «variable» to {key1: val1, key2: val2, ...} as «type»->«type»;
```
### tunnel
@ -118,8 +111,6 @@ The following is a list of global operators and their effect:
- comment
- `!!`
- block comment (looks for another !! to close)
- `=`
- set operator
- `??`
- unwrap or
- `+`
@ -200,40 +191,60 @@ The following is a list of global operators and their effect:
### keywords
`to`
set operator
```
set «token» to 0;
```
`is`
checks if a object is of that type
```
if («token» is i32) {
stdout.print("hello yes self is i32?")
stdout.print("hello yes self is i32?");
}
```
also used for setting constants
```
const purple is Color(255, 255, 0);
```
`as`
coerces a type as another type if possible
```
let «token» = 0
some_functon_that_needs_a_i32(«token» as i32)
set «token» to 0; ! default is i32
some_functon_that_needs_a_i8(«token» as i8);
```
`impls`
`in`
checks if a object's type, or a type impls another type
checks if a object's type, or a type impls another type
```
if («token» impls Tunnel) {
stdout.print("im tunnel-able")
if («token» in Tunnel) {
stdout.print("im tunnel-able");
}
```
also used inside of the for loops
```
for («token» in «collection») { «body» }
```
## Object
An object is an invoked type.
```
let «variable» = «type»(«fields», …)
set «variable» to «type»(«fields», …);
```
## Tunnel
@ -246,6 +257,8 @@ tunnels are invoked like objects, but have scope like control flow end scope clo
note the type must always be of a type which is "tunnel-able" i.e. Files, sockets, etc
Tunnels have almost the same interface as 9p since they are closely based on 9p.
### transtypes for tunnels
`tunnel? : attach(tunnel_object)` -> open communication
@ -271,12 +284,12 @@ note the type must always be of a type which is "tunnel-able" i.e. Files, socket
`success? : tunnel_object.walk(path_or_endpoint)` -> moves around the filesystem or through the graph
```
let endpoint = «tunnel-able type»(endpoint_str)
let tunnel = endpoint.attach(user, auth)
let data = tunnel.?open("\some\resource").?read()
stdout.write(data)
data.flush()
endpoint.clunk()
set endpoint to 9p(endpoint_str);
set tunnel to endpoint.attach(user, auth);
set data to tunnel.open("\some\resource").read();
stdout.write(data);
data.flush();
endpoint.clunk();
```
in "terminal mode" the default tunnel is stdout
@ -285,8 +298,10 @@ in "web mode" the default tunnels are log, info, trace, warn, error, but note th
## Functions
Functions are all typechecked statically at compile time. Since we always have a "default type" for all constant values or a developer can use the `as` keyword we do not have to define all values like in C, while keeping the same type safety as a more strongly typed language.
```
fn «token» («parameter»: «type», ...): «return_type» {
fn «token» («type» «parameter», ...) «return_type» {
«instructions»
}
```
@ -308,12 +323,6 @@ for («token» in «collection») { «body» }
```
iterates through each object in the collection setting it to token
```
each («token» in «collection») { «body» }
```
iterates through each key in the collection setting it to token
```
while («boolean expression») { «body» }
```
@ -326,6 +335,12 @@ loop { «body» }
loops infinitely until break or return
```
loop { «body» } until(«boolean expression»);
```
always loops first and then until the expression is false
### branching
```
@ -344,9 +359,9 @@ match «token» {
take a look at error's, but you can panic on an error like self:
```
panic(#"error message")
panic(#3)
panic(«some_error_token»)
panic(#"error message");
panic(#3);
panic(«some_error_token»);
```
## Localization
@ -376,26 +391,15 @@ The other way to do self would be to just specifically “name” the paths usin
Since everything is lazily compiled jit anyways it (in theory) doesn't hurt pertypeance much
```
use `https://code.example.com/some_library/some_file.ztl`
use "https://code.example.com/some_library/some_file.ztl"
```
```
use `./some_local_file.ztl`
use "./some_local_file.ztl"
```
## Testing
Tests are done inside of a `test` block
```
test some_test {
someFunction() => true
}
```
### assertion
```
@ -431,4 +435,4 @@ assert(«expression», «expected output») ! returns «error or none»
- mol (mol)
- luminous intensity
- unit
- candela (candela)
- candela (candela)

View File

@ -0,0 +1,69 @@
-- mod-version:1
local syntax = require "core.syntax"
syntax.add {
name = "Zongor's Transpiler Language",
files = { "%.ztl$" },
comment = "//",
block_comment = { '/*', '*/' },
patterns = {
{ pattern = { "/%*", "%*/" }, type = "comment" },
{ pattern = "//.-\n", type = "comment" },
{ pattern = "\\\\.-\n", type = "string" },
{ pattern = { '"', '"', '\\' }, type = "string" },
{ pattern = { "'", "'", '\\' }, type = "string" },
{ pattern = "[iuv][%d_]+", type = "keyword2" },
{ pattern = "[9][%w_]*", type = "keyword2" },
{ pattern = "%d[%d_]*%.[%d_]*", type = "number" },
{ pattern = "%d[%d_]*", type = "number" },
{ pattern = "[%+%-=/%*%^%%<>!~|&%.%?]", type = "operator" },
{ pattern = "[%a_][%w_]*()%s*%(", type = {"function", "normal"} },
{ pattern = "[A-Z][%w_]*", type = "keyword2" },
{ pattern = "[%a_][%w_]*", type = "symbol" },
{ pattern = "@()[%a_][%w_]*", type = {"operator", "function"} },
{ regex = [[(?:[^"\\]|\\.)*()\s*:]], type = { "number" } }, -- key
},
symbols = {
["continue"] = "keyword",
["break"] = "keyword",
["switch"] = "keyword",
["for"] = "keyword",
["in"] = "keyword",
["while"] = "keyword",
["const"] = "keyword",
["test"] = "keyword",
["export"] = "keyword",
["if"] = "keyword",
["else"] = "keyword",
["return"] = "keyword",
["and"] = "keyword",
["or"] = "keyword",
["not"] = "keyword",
["interface"] = "keyword",
["struct"] = "keyword",
["enum"] = "keyword",
["union"] = "keyword",
["inline"] = "keyword",
["use"] = "keyword",
-- types
["str"] = "keyword2",
["f16"] = "keyword2",
["f32"] = "keyword2",
["f64"] = "keyword2",
["f128"] = "keyword2",
["err"] = "keyword2",
["rgb"] = "keyword2",
["hsv"] = "keyword2",
["rgba"] = "keyword2",
["void"] = "keyword2",
["bool"] = "keyword2",
["true"] = "literal",
["false"] = "literal",
["null"] = "literal",
["undefined"] = "literal",
},
}

View File

@ -0,0 +1,47 @@
void build (ProjectConfig c) {
c.name("MMO Project");
c.client([
LanguageSettings {
lang: "c",
file: "src/client.ztl",
outpath: "client/",
ffi: [
FFISetting {
name:"raylib",
library:"$RAYLIB_PATH/libraylib.a",
path:"./",
build: "make build",
}
]
}
])
c.server([
{
lang: "javascript",
file: "src/server.ztl",
outpath: "server/"
}
]);
c.common([
LanguageSettings {
"c",
"src/common.ztl",
"client/"
},
{
lang: "javascript",
file: "src/common.ztl",
outpath: "server/"
},
{
lang: "sqlite",
file: "src/common.ztl",
outpath: "db/"
}
]);
c.build();
}

View File

@ -0,0 +1,91 @@
use "common.ztl";
Player[] login (9pc s Player p str password) {
s.auth(p.username, password);
return s.read("players");
};
i32 main (i32 argc str[] argv) {
const i32 screen_width = 800;
const i32 screen_height = 450;
str username = argv[0];
str password = argv[1];
Player me = {
username: username,
pos: {0.0 1.0 2.0},
apperance: purple,
};
Player[] players = me.login(password);
Camera3D camera = {
up: {0.0 1.0 0.0},
fov: 45.0,
type: CAMERA_PERSPECTIVE,
pos: {
me.pos.x + 10.0,
me.pos.y + 10.0,
me.pos.z,
},
target: me.pos,
};
init_window("zwl client : raylib", screen_width, screen_height);
set_target_fps(60);
/* Main game loop */
while ( not window_should_close ) {
if (is_key_down(KEY_RIGHT)) {
me.pos.x += 0.2;
player_updated = true;
};
if (is_key_down(KEY_LEFT)) {
me.pos.x -= 0.2;
player_updated = true;
};
if (is_key_down(KEY_DOWN)) {
me.pos.z += 0.2;
player_updated = true;
};
if (is_key_down(KEY_UP)) {
me.pos.z -= 0.2;
player_updated = true;
};
me.sync_camera(camera);
if (player_updated) {
players = me.move();
} else {
players = me.ping();
};
begin_drawing();
clear_background(RAYWHITE);
begin_mode_3d(camera);
/* Draw floor */
draw_grid(30, 1.0);
draw_cube(me.pos, 0.5, 0.5, 0.5, me.apperance);
for player in players {
draw_cube(player.pos, 0.5, 0.5, 0.5, player.apperance);
}
end_mode_3d();
end_drawing();
}
/* Detect window close button or ESC key */
players = logout(me);
close_window(); /* Close window and OpenGL context */
return 0;
};

View File

@ -0,0 +1,7 @@
struct Player {
str username,
v3 pos,
rgb color,
};
const rgb purple = {255 255 0};

View File

@ -0,0 +1,21 @@
use "common.ztl"
i32 main (i32 argc, []str argv) {
9ps s = {
version: "9P2000",
auth:
error:
flush:
attach:
walk:
open:
create:
read:
write:
clunk:
remove:
stat:
};
s.host("0.0.0.0:25565");
};

View File

@ -0,0 +1,45 @@
--mod-version:3
local syntax = require 'core.syntax'
syntax.add {
name = "Zongor's Transpiler Language",
files = { "%.ztl$" },
block_comment = { '/*', '*/' },
patterns = {
{ pattern = { "/%*", "%*/" }, type = "comment" },
{ pattern = { '"', '"', '\\' }, type = "string" },
{ pattern = { "'", "'", '\\' }, type = "string" },
{ pattern = ";", type = "operator" },
{ pattern = "[%a_][%w_]*()%s*%(", type = {"function", "normal"} },
{ pattern = "[viu][%d_]+", type = "keyword2" },
{ pattern = "[A-Z][%w_]*", type = "keyword2" },
{ pattern = "[9][%w_]*", type = "keyword2" },
{ pattern = ":[%w_]*", type = "literal" },
{ pattern = "-?%.?%d+f?", type = "number" },
},
symbols = {
["fn"] = "keyword",
["to"] = "keyword",
["in"] = "keyword",
["use"] = "keyword",
["set"] = "keyword",
["if"] = "keyword",
["else"] = "keyword",
["for"] = "keyword",
["while"] = "keyword",
["push"] = "keyword",
["pop"] = "keyword",
["return"] = "keyword",
["immutable"] = "keyword",
["type"] = "keyword",
["char"] = "keyword2",
["str"] = "keyword2",
["f16"] = "keyword2",
["f32"] = "keyword2",
["f64"] = "keyword2",
["f128"] = "keyword2",
["true"] = "literal",
["false"] = "literal",
}}

View File

@ -1,48 +1,47 @@
fn :build (ProjectConfig) {
set c to pop;
fn build(ProjectConfig c) {
c.name("MMO Project");
c.mode("dev");
c.client([
LanguageSettings {
"lang": "c",
"file": "src/client.ztl",
"outpath": "client/",
"ffi": [
LanguageSettings(
"c", ! lang
"src/client.ztl", ! file
"client/", ! out path
[ ! ffi settings
FFISetting {
"name":"raylib",
"library":"$RAYLIB_PATH/libraylib.a",
"path":"./",
"build": "make build",
"raylib", ! libary name
"$RAYLIB_PATH/libraylib.a", ! path
"./", ! local path
"make build", ! build command
}
]
}
])
)
]);
c.server([
LanguageSettings {
"lang": "javascript",
"file": "src/server.ztl",
"outpath": "server/"
}
LanguageSettings(
"javascript",
"src/server.ztl",
"server/"
)
]);
c.common([
LanguageSettings {
"lang": "c",
"file": "src/common.ztl",
"outpath": "client/"
LanguageSettings(
"c",
"src/common.ztl",
"client/"
},
LanguageSettings {
"lang": "javascript",
"file": "src/common.ztl",
"outpath": "server/"
},
LanguageSettings {
"lang": "sqlite",
"file": "src/common.ztl",
"outpath": "db/"
}
LanguageSettings(
"javascript",
"src/common.ztl",
"server/"
),
LanguageSettings(
"sqlite",
"src/common.ztl",
"db/"
)
]);
c.build();

View File

@ -1,101 +1,93 @@
use "common.ztl"
use "common.ztl";
use "raylib" as rl;
fn :login (9p Player str -> []Player) {
set s to pop;
set p to pop;
set password to pop;
fn main (i32 argc, str[] argv) i32 {
set screen_width to 800 as i32;
set screen_height to 450 as i32;
s.auth(p.username, password);
return s.read("players");
};
set username to argv[0];
set password to argv[1];
set server to 9p("localhost:25565");
fn :main (i32 str[i32] -> i32) { /* str[i32] is the same as Map<number, string> in JS*/
set :argc to pop;
set :argv to pop;
set :screen_width to i32 800;
set :screen_height to i32 450;
set :username to argv[0];
set :password to argv[1];
set :me to Player {
set me to Player(
server,
username,
vec {0.0 1.0 2.0},
purple,
};
Vec(0.0 1.0 2.0),
purple
);
set :players to Player[] { login me password; };
set players to me.login(password);
set :camera to Camera3D {
vec {0.0 1.0 0.0},
i32 45.0,
atom :CAMERA_PERSPECTIVE,
vec {
add me.pos.x 10.0,
add me.pos.y 10.0,
me.pos.z,
},
me.pos,
};
set camera to rl.Camera3D(
Vec(0.0, 1.0, 0.0),
45.0,
CAMERA_PERSPECTIVE,
Vec(me.pos.x + 10.0,
me.pos.y + 10.0,
me.pos.z),
me.pos
);
init_window "zwl client : raylib" screen_width screen_height;
set_target_fps 60;
rl.init_window("zwl client : raylib", screen_width, screen_height);
rl.set_target_fps(60);
/* Main game loop */
while ( not window_should_close ) {
!!
Main game loop
!!
while ( not rl.window_should_close() ) { ! Detect window close button or ESC key
if (is_key_down :KEY_RIGHT) {
set me.pos.x to {add me.pos.x 0.2};
set :player_updated true;
set player_updated to false;
if (rl.is_key_down(KEY_RIGHT)) {
set me.pos.x to (me.pos.x + 0.2);
set player_updated to true;
}
if (is_key_down :KEY_LEFT) {
set me.pos.x to {sub me.pos.x 0.2};
set :player_updated true;
if (rl.is_key_down(KEY_LEFT)) {
set me.pos.x to (me.pos.x + 0.2);
set player_updated to true;
}
if (is_key_down :KEY_DOWN) {
set me.pos.z to {add me.pos.z 0.2};
set :player_updated true;
if (rl.is_key_down(KEY_DOWN)) {
set me.pos.z to (me.pos.z + 0.2);
set player_updated to true;
}
if (is_key_down :KEY_UP) {
set me.pos.z to {sub me.pos.z 0.2};
set :player_updated true;
if (rl.is_key_down(KEY_UP)) {
set me.pos.z to (me.pos.z - 0.2);
set player_updated to true;
}
sync_camera camera me;
me.sync_camera(camera);
if (player_updated) {
set :players move me;
set players to me.move();
} else {
set :players ping me;
set players to me.ping();
}
begin_drawing;
clear_background RAYWHITE;
rl.begin_drawing();
rl.clear_background(RAYWHITE);
begin_mode_3d camera;
rl.begin_mode_3d(camera);
/* Draw floor */
draw_grid 30 1.0;
! Draw floor
rl.draw_grid(30, 1.0);
draw_cube me.pos 0.5 0.5 0.5 me.apperance;
rl.draw_cube(me.pos, 0.5, 0.5, 0.5, me.apperance);
map :player players {
draw_cube player.pos 0.5 0.5 0.5 player.apperance;
for (player in players) {
rl.draw_cube(player.pos, 0.5, 0.5, 0.5, player.apperance);
}
end_mode_3d;
rl.end_mode_3d();
end_drawing;
rl.end_drawing();
}
/* Detect window close button or ESC key */
set :players to logout me;
close_window; /*Close window and OpenGL context */
};
me.logout();
close_window(); ! Close window and OpenGL context
return 0;
}
main;

View File

@ -1,19 +1,37 @@
set :Vec to type {
f32 :x,
f32 :y,
f32 :z,
};
type Vec {
init(f32 x, f32 y, f32 z) {
set this.x to x;
set this.y to y;
set this.z to z;
}
}
set :Color to type {
i8 :r,
i8 :g,
i8 :b,
};
type Color {
init(i8 r, i8 g, i8 b) {
set this.r to r;
set this.g to g;
set this.b to b;
}
}
set :Player to type {
str :username,
Vec :pos,
Color :color,
};
type Player {
init (9p server, str username, Vec pos, Color color) {
set this.server to server;
set this.username to username;
set this.pos to pos;
set this.color to color;
}
set immutable :purple to Color {255 255 0};
login (str password) Player[] {
this.server.auth(this.username, password);
set this.players to server.open("players");
return players.read();
}
logout() {
this.players.flush();
this.server.clunk();
}
}
const purple is Color(255, 255, 0);

View File

@ -1,63 +1,75 @@
use "common.ztl"
use "common.ztl";
fn :main(i32, []str -> i32) {
set :argc to pop;
set :argv to pop;
fn main (i32 argc, str[] argv) i32 {
set s to 9p (
version,
auth,
error,
flush,
attach,
walk,
open,
create,
read,
write,
clunk,
remove,
stat,
);
s.host("0.0.0.0:25565");
set s to tunnel "0.0.0.0:25565";
s.host (
version,
auth,
error,
flush,
attach,
walk,
open,
create,
read,
write,
clunk,
remove,
stat,
);
return 0;
}
fn :version(9pmsg) {
}
fn :auth(9pmsg) {
fn version(9pmsg m) {
}
fn :error(9pmsg) {
fn auth(9pmsg m) {
}
fn :flush(9pmsg) {
fn error(9pmsg m) {
}
fn :attach(9pmsg) {
fn flush(9pmsg m) {
}
fn :walk(9pmsg) {
fn attach(9pmsg m) {
}
fn :open(9pmsg) {
fn walk(9pmsg m) {
}
fn :create(9pmsg) {
fn open(9pmsg m) {
}
fn :read(9pmsg) {
fn create(9pmsg m) {
}
fn :write(9pmsg) {
fn read(9pmsg m) {
}
fn :clunk(9pmsg) {
fn write(9pmsg m) {
}
fn :remove(9pmsg) {
fn clunk(9pmsg m) {
}
fn :stat(9pmsg) {
}
fn remove(9pmsg m) {
}
fn stat(9pmsg m) {
}

View File

@ -0,0 +1,45 @@
--mod-version:3
local syntax = require 'core.syntax'
syntax.add {
name = "Zongor's Transpiler Language",
files = { "%.ztl$" },
block_comment = { '/*', '*/' },
patterns = {
{ pattern = { "/%*", "%*/" }, type = "comment" },
{ pattern = { '"', '"', '\\' }, type = "string" },
{ pattern = { "'", "'", '\\' }, type = "string" },
{ pattern = ";", type = "operator" },
{ pattern = "[%a_][%w_]*()%s*%(", type = {"function", "normal"} },
{ pattern = "[viu][%d_]+", type = "keyword2" },
{ pattern = "[A-Z][%w_]*", type = "keyword2" },
{ pattern = "[9][%w_]*", type = "keyword2" },
{ pattern = ":[%w_]*", type = "literal" },
{ pattern = "-?%.?%d+f?", type = "number" },
},
symbols = {
["fn"] = "keyword",
["to"] = "keyword",
["in"] = "keyword",
["use"] = "keyword",
["set"] = "keyword",
["if"] = "keyword",
["else"] = "keyword",
["for"] = "keyword",
["while"] = "keyword",
["push"] = "keyword",
["pop"] = "keyword",
["return"] = "keyword",
["immutable"] = "keyword",
["type"] = "keyword",
["char"] = "keyword2",
["str"] = "keyword2",
["f16"] = "keyword2",
["f32"] = "keyword2",
["f64"] = "keyword2",
["f128"] = "keyword2",
["true"] = "literal",
["false"] = "literal",
}}

View File

@ -0,0 +1,49 @@
fn :build (ProjectConfig) {
set c to pop;
c.name("MMO Project");
c.client([
LanguageSettings {
"c", /* lang */
"src/client.ztl", /* file */
"client/", /* out path */
[ /* ffi */
FFISetting {
"raylib",
"$RAYLIB_PATH/libraylib.a",
"./",
"make build",
}
]
}
])
c.server([
LanguageSettings {
"javascript",
"src/server.ztl",
"server/"
}
]);
c.common([
LanguageSettings {
"c",
"src/common.ztl",
"client/"
},
LanguageSettings {
"javascript",
"src/common.ztl",
"server/"
},
LanguageSettings {
"sqlite",
"src/common.ztl",
"db/"
}
]);
c.build();
}

View File

@ -0,0 +1,94 @@
use "common.ztl"
fn :login (9p :s Player :p str :password) Player[] {
s.auth(p.username, password);
return s.read("players");
}
fn :main (i32 :argc str[] :argv) i32 {
set :screen_width to i32 800;
set :screen_height to i32 450;
set :username to argv[0];
set :password to argv[1];
set :me to Player
username
0.0 1.0 2.0
purple
;
set :players to Player[] login(password);
set :camera to Camera3D
0.0 1.0 0.0
45.0
:CAMERA_PERSPECTIVE
add me.pos.x 10.0
add me.pos.y 10.0
me.pos.z
me.pos
;
init_window( "zwl client : raylib" screen_width screen_height);
set_target_fps( 60);
/* Main game loop */
while ( not window_should_close ) {
set :player_updated to false;
if (is_key_down(:KEY_RIGHT)) {
set me.pos.x to {add me.pos.x 0.2};
set :player_updated true;
}
if (is_key_down(:KEY_LEFT)) {
set me.pos.x to {sub me.pos.x 0.2};
set :player_updated true;
}
if (is_key_down(:KEY_DOWN)) {
set me.pos.z to {add me.pos.z 0.2};
set :player_updated true;
}
if (is_key_down(:KEY_UP)) {
set me.pos.z to {sub me.pos.z 0.2};
set :player_updated true;
}
me.sync_camera(camera);
if (player_updated) {
set :players me.move();
} else {
set :players me.ping();
}
begin_drawing();
clear_background(RAYWHITE);
begin_mode_3d(camera);
/* Draw floor */
draw_grid(30 1.0);
draw_cube(me.pos 0.5 0.5 0.5 me.apperance);
for :player in players {
draw_cube(player.pos 0.5 0.5 0.5 player.apperance);
}
end_mode_3d();
end_drawing();
}
/* Detect window close button or ESC key */
me.logout();
close_window(); /*Close window and OpenGL context */
return 0;
}

View File

@ -0,0 +1,19 @@
set :Vec to type {
f32 :x,
f32 :y,
f32 :z,
};
set :Color to type {
i8 :r,
i8 :g,
i8 :b,
};
set :Player to type {
str :username,
Vec :pos,
Color :color,
};
set immutable :purple to Color {255 255 0};

View File

@ -0,0 +1,73 @@
use "common.ztl"
fn :main (i32 :argc []str :argv) i32 {
set s to 9p {
version,
auth,
error,
flush,
attach,
walk,
open,
create,
read,
write,
clunk,
remove,
stat,
};
s.host("0.0.0.0:25565")
};
fn :version(9pmsg :m) {
};
fn :auth(9pmsg :m) {
};
fn :error(9pmsg :m) {
};
fn :flush(9pmsg :m) {
};
fn :attach(9pmsg :m) {
};
fn :walk(9pmsg :m) {
};
fn :open(9pmsg :m) {
};
fn :create(9pmsg :m) {
};
fn :read(9pmsg :m) {
};
fn :write(9pmsg :m) {
};
fn :clunk(9pmsg :m) {
};
fn :remove(9pmsg :m) {
};
fn :stat(9pmsg :m) {
};