diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java
index cd02173b..d8dfbd35 100644
--- a/src/main/java/carpet/script/CarpetScriptServer.java
+++ b/src/main/java/carpet/script/CarpetScriptServer.java
@@ -94,6 +94,7 @@ public class CarpetScriptServer
registerBuiltInScript(BundledModule.carpetNative("chunk_display", false));
registerBuiltInScript(BundledModule.carpetNative("ai_tracker", false));
registerBuiltInScript(BundledModule.carpetNative("draw_beta", false));
+ registerBuiltInScript(BundledModule.carpetNative("shapes", true));
registerBuiltInScript(BundledModule.carpetNative("distance_beta", false));
}
diff --git a/src/main/resources/assets/carpet/scripts/draw_beta.sc b/src/main/resources/assets/carpet/scripts/draw_beta.sc
index c88739d1..0b8ba312 100644
--- a/src/main/resources/assets/carpet/scripts/draw_beta.sc
+++ b/src/main/resources/assets/carpet/scripts/draw_beta.sc
@@ -1,21 +1,23 @@
-import('math','_euclidean_sq','_vec_length');
+import('shapes','draw_sphere', 'draw_diamond', 'draw_filled_diamond', 'draw_pyramid', 'draw_prism'); //importing all the shape funcs from the other app
__config() -> {
'commands'->{
- 'sphere
'->['draw_sphere',null,true],
- 'sphere replace '->['draw_sphere',true],
- 'ball '->['draw_sphere',null,false],
- 'ball replace '->['draw_sphere',false],
- 'diamond '->['draw_diamond',null],
- 'diamond replace '->'draw_diamond',
- 'pyramid '->['draw_pyramid',null, true],
- 'pyramid replace '->['draw_pyramid', true],
- 'cone '->['draw_pyramid',null, false],
- 'cone replace '->['draw_pyramid', false],
- 'cuboid '->['draw_prism', null, true],
- 'cuboid replace '->['draw_prism', true],
- 'cylinder '->['draw_prism', null, false],
- 'cylinder replace '->['draw_prism', false]
+ 'sphere '->_(c,r,b)->draw('draw_sphere',[c,r, true],b,null),
+ 'sphere replace '->_(c,r,b,rp)->draw('draw_sphere',[c,r,true],b,rp),
+ 'ball '->_(c,r,b)->draw('draw_sphere',[c,r,false],b,null),
+ 'ball replace '->_(c,r,b,rp)->draw('draw_sphere',[c,r,false],b,rp),
+ 'diamond hollow' -> _(c,r,b)->draw('draw_diamond',[c,r],b,null),
+ 'diamond hollow replace '->_(c,r,b,rp)->draw('draw_diamond',[c, r], b, rp),
+ 'diamond ' -> _(c,r,b)->draw('draw_filled_diamond',[c,r],b,null),
+ 'diamond replace '->_(c,r,b,rp)->draw('draw_filled_diamond',[c, r], b, rp),
+ 'pyramid '->_(c,r,h,p,o,b,ho)->draw('draw_pyramid',[c,r,h,p,o,ho, true],b,null),
+ 'pyramid replace '->_(c,r,h,p,o,b,ho,rp)->draw('draw_pyramid', [c,r,h,p,o,ho,true],b,rp),
+ 'cone '->_(c,r,h,p,o,b,ho)->draw('draw_pyramid',[c,r,h,p,o,ho, false],b,null),
+ 'cone replace '->_(c,r,h,p,o,b,ho,rp)->draw('draw_pyramid', [c,r,h,p,o,ho,false],b,rp),
+ 'cuboid '->_(c,r,h,o,b,ho)->draw('draw_prism',[c,r,h,p,o,ho, true],b,null),
+ 'cuboid replace '->_(c,r,h,o,b,ho,rp)->draw('draw_prism', [c,r,h,o,ho,true],b,rp),
+ 'cylinder '->_(c,r,h,o,b,ho)->draw('draw_prism',[c,r,h,p,o,ho, false],b,null),
+ 'cylinder replace '->_(c,r,h,o,b,ho,rp)->draw('draw_prism', [c,r,h,o,ho,false],b,rp),
},
'arguments'->{
'center'->{'type'->'pos', 'loaded'->'true'},
@@ -26,12 +28,9 @@ __config() -> {
'pointing'->{'type'->'term','suggest'->['up','down']},
'hollow'->{'type'->'term','suggest'->['hollow','solid']},
},
- 'scope'->'global'
+ 'scope'->'global'//todo decide whether it rly needs to be global or not...
};
-
-//"Boilerplate" code
-
_block_matches(existing, block_predicate) ->
(
[name, block_tag, properties, nbt] = block_predicate;
@@ -42,112 +41,16 @@ _block_matches(existing, block_predicate) ->
(!tag || tag_matches(block_data(existing), tag))
);
-set_block(x, y, z, block, replacement)-> (
- existing = block(x, y, z);
- if(block != existing && (replacement && _block_matches(existing, replacement) ),
- without_updates( if (set(existing,block),
- global_affected += [x, y, z];
- ));
+draw(what, args, block, replacement)->(//custom setter cos it's easier
+ positions = call(what,args); //returning blocks to be set
+
+ affected = 0
+
+ for(positions,
+ existing = block(_);
+ if(block != existing && (!replacement || _block_matches(existing, replacement)),
+ affected += bool(set(existing,block))
+ )
);
-);
-
-global_affected = [];
-
-affected(player) -> (
- affected = length(global_affected);
print(player,format('gi Filled ' + affected + ' blocks'));
-
- if(system_info('world_carpet_rules'):'fillUpdates',
- for(global_affected,update(_));//updating if fillUpdates is true
- );
-
- global_affected = [];
- affected
-);
-
-length_sq(vec) -> reduce(vec, _a + _*_, 0);
-
-fill_flat(pos, offset, dr, rectangle, orientation, block, hollow, replacement)->(
- r = floor(dr);
- drsq = dr^2;
- if(orientation=='x',
- scan(pos,0,-r,-r,
- if((!hollow && (rectangle || _y^2 + _z^2 <= drsq))||//if not hollow, vry simple
- (hollow && ((rectangle && (abs(_y) == r || abs(_z) ==r)) || //If hollow and it's a rectangle
- (!rectangle && (_y^2 + _z^2 <= drsq && (abs(_y)+1)^ 2 + (abs(_z)+1)^2 >= drsq)))),//If hollow and not rectangle
- set_block(_x+offset,_y,_z,block, replacement)
- )
- ),
- orientation == 'y',
- scan(pos,-r,0,-r,
- if((!hollow && (rectangle || _x^2 + _z^2 <= drsq))||//if not hollow, vry simple
- (hollow && ((rectangle && (abs(_x) == r || abs(_z) ==r)) || //If hollow and it's a rectangle
- (!rectangle && (_x^2 + _z^2 <= drsq && (abs(_x)+1)^ 2 + (abs(_z)+1)^2 >= drsq)))),//If hollow and not rectangle
- set_block(_x,_y+offset,_z,block, replacement)
- )
- ),
- orientation == 'z',
- scan(pos,-r,-r,0,
- if((!hollow && (rectangle || _y^2 + _x^2 <= drsq))||//if not hollow, vry simple
- (hollow && ((rectangle && (abs(_y) == r || abs(_x) ==r)) || //If hollow and it's a rectangle
- (!rectangle && (_y^2 + _x^2 <= drsq && (abs(_y)+1)^ 2 + (abs(_x)+1)^2 >= drsq)))),//If hollow and not rectangle
- set_block(_x,_y,_z+offset,block, replacement)
- )
- ),
- print(player(),format('r Error while running command: orientation can only be "x", "y" or "z", '+orientation+' is invalid.'));
- global_affected = [];
- );
-);
-
-//drawing commands
-
-draw_sphere(centre, radius, block, replacement, hollow)->(
- scan(centre,[radius,radius,radius],
- l = length_sq([_x,_y,_z]-centre);
- if((l<=radius^2+radius) && (!hollow || l>=radius^2-radius),
- set_block(_x, _y, _z, block, replacement)
- )
- );
-
- affected(player());
-);
-
-draw_diamond(pos, radius, block, replacement)->(
-
- c_for(r=0, r(
-
- hollow = fill_type=='hollow';
- pointup = pointing=='up';
-
- for(range(height),
- r = if(pointup, radius - radius * _ / height -1, radius * _ / height);
- fill_flat(pos, _, r, is_square, orientation, block, if((pointup&&_==0)||(!pointup && _==height-1),false,hollow),replacement)//Always close bottom off
- );
- affected(player())
-);
-
-draw_prism(pos, rad, height, orientation, block, fill_type, replacement, is_square)->(
-
- hollow = fill_type =='hollow';
- radius = rad+0.5;
-
- for(range(height),
- fill_flat(pos, _, radius, is_square, orientation, block, if(_==0 || _==height-1,false,hollow), replacement)//Always close ends off
- );
- affected(player())
);
diff --git a/src/main/resources/assets/carpet/scripts/shapes.scl b/src/main/resources/assets/carpet/scripts/shapes.scl
new file mode 100644
index 00000000..adad5bcb
--- /dev/null
+++ b/src/main/resources/assets/carpet/scripts/shapes.scl
@@ -0,0 +1,233 @@
+//This is a library app, mostly for the draw command, which allows to import these shape-drawing functions into your own app.
+//Arguments for each are to be given as a singleton list, for ease of use. This is with the exception of the fill_flat functions, with
+//the assumption that they're unlikely to be used outside of internal calls, but it is still available to be called if necessary.
+//Make sure you read the arguments and input them in the correct order, or it will mess up.
+//these functions return a set of all the positions in the shape, given the parameters, without repeating a position.
+//This way, you can efficiently iterate over the positions once having generated them. See draw_beta.sc for an example. todo change to draw once renamed
+
+
+draw_sphere(args)->(
+ [centre, radius, hollow] = args;
+ positions = {};
+ [cx,cy,cz]=centre;
+ for(range(-90, 90, 45/radius),
+ cpitch = cos(_);
+ spitch = sin(_);
+ for(range(0, 180, 45/radius),
+ cyaw = cos(_)*cpitch*radius;
+ syaw = sin(_)*cpitch*radius;
+ if(hollow,
+ positions += [cx+cyaw,cy+spitch*radius,cz+syaw];
+ positions += [cx+cos(_+180)*cpitch*radius,cy+spitch*radius,cz+sin(_+180)*cpitch*radius],
+ for(range(-syaw,syaw+1),
+ positions += [cx+cyaw*cpitch,cy+spitch*radius,cz+_]
+ )
+ )
+ )
+ );
+ positions
+);
+
+draw_diamond(args)->(
+ [pos, radius] = args;
+ positions = {};
+ c_for(r=0, r(
+ [pos, radius] = args;
+ positions = {};
+ for(diamond(pos,radius,radius),
+ positions += pos(_)
+ );
+ positions
+);
+
+draw_pyramid(args)->(
+ [pos, radius, height, pointing, orientation, fill_type, is_square] = args;//todo change to hollow boolean arg
+ positions = {};
+ hollow = fill_type=='hollow';
+ pointup = pointing=='up';
+ for(range(height),
+ r = if(pointup, radius * ( 1- _ / height) -1, radius * _ / height);
+ positions += fill_flat(pos, _, r, is_square, orientation, !((pointup&&_==0)||(!pointup && _==height-1)) && hollow)//Always close bottom off
+ );
+ positions
+);
+
+draw_prism(args)->(
+ [pos, rad, height, orientation, fill_type, is_square]=args;//todo change to hollow boolean arg
+ positions = {};
+ hollow = fill_type =='hollow';
+ radius = rad+0.5;
+ filled_circle_points = fill_flat(pos, 0, radius, is_square, orientation, false); //I dont actually need to generate all the points lol
+ offset_vector = if(orientation=='x', [1,0,0], orientation=='y', [0,1,0],[0,0,1]);
+ if(hollow,
+ hollow_circle_points = fill_flat(pos, 0, radius, is_square, orientation, true);
+
+ for(filled_circle_points,//Always close ends off
+ positions+=_;
+ positions+=_+offset_vector*(height-1)
+ );
+
+ for(range(1, height-1),//cos Im adding ends as filled anyways
+ offset=_;
+ for(hollow_circle_points,
+ positions+= _ + offset_vector * offset
+ )
+ ),
+
+ for(range(height),
+ offset = _;
+ for(filled_circle_points,
+ positions += _ + offset_vector * offset
+ )
+ );
+ )
+ positions
+);
+
+fill_flat(pos, offset, dr, rectangle, orientation, hollow)->
+ if(rectangle,
+ fill_flat_rectangle(pos, offset, dr, orientation, hollow),
+ fill_flat_circle(pos, offset, dr, orientation, hollow)
+ );
+
+fill_flat_circle(pos, offset, dr, orientation, hollow) ->( //Bresenham circle algorithm to be super efficient
+ r = floor(dr);
+ a=0;
+ b=r;
+ d=3-(2*r);
+
+ positions = {};
+
+ positions += fill_flat_circle_points(pos, orientation, offset, hollow, a, b);
+
+ while(a<=b, 10^10,
+ if(d<=0,
+ d += (4*a)+6,
+ d += (4*a)-(4*b)+10;
+ b=b-1
+ );
+ a+=1;
+ positions += fill_flat_circle_points(pos, orientation, offset, hollow, a, b)
+ );
+ positions
+);
+
+fill_flat_circle_points(pos, orientation, offset, hollow, a, b) ->(
+ [x, y, z] = pos;
+ positions = {};
+ if(orientation == 'x',
+ if(hollow,
+ positions += [x + offset, a+y, b+z];
+ positions += [x + offset, a+y,-b+z];
+ positions += [x + offset,-a+y,-b+z];
+ positions += [x + offset,-a+y, b+z];
+ positions += [x + offset, b+y, a+z];
+ positions += [x + offset, b+y,-a+z];
+ positions += [x + offset,-b+y,-a+z];
+ positions += [x + offset,-b+y, a+z],
+ c_for(c = -a, c<=a, c+=1,
+ positions += [x + offset,c+y, b + z];
+ positions += [x + offset,c+y,-b + z]
+ );
+ c_for(c = -b, c<=b, c+=1,
+ positions += [x + offset, a+y,c + z];
+ positions += [x + offset,-a+y,c + z]
+ )
+ ),
+ orientation=='y',
+ if(hollow,
+ positions += [ a+x, y + offset, b+z];
+ positions += [ a+x, y + offset,-b+z];
+ positions += [-a+x, y + offset,-b+z];
+ positions += [-a+x, y + offset, b+z];
+ positions += [ b+x, y + offset, a+z];
+ positions += [ b+x, y + offset,-a+z];
+ positions += [-b+x, y + offset,-a+z];
+ positions += [-b+x, y + offset, a+z],
+ c_for(c = -a, c<=a, c+=1,
+ positions += [c+x,y + offset, b + z];
+ positions += [c+x,y + offset,-b + z]
+ );
+ c_for(c = -b, c<=b, c+=1,
+ positions += [ a+x,y + offset,c + z];
+ positions += [-a+x,y + offset,c + z]
+ )
+ ),
+ orientation=='z',
+ if(hollow,
+ positions += [ a+x, b+y, z + offset];
+ positions += [ a+x,-b+y, z + offset];
+ positions += [-a+x,-b+y, z + offset];
+ positions += [-a+x, b+y, z + offset];
+ positions += [ b+x, a+y, z + offset];
+ positions += [ b+x,-a+y, z + offset];
+ positions += [-b+x,-a+y, z + offset];
+ positions += [-b+x, a+y, z + offset],
+ c_for(c = -a, c<=a, c+=1,
+ positions += [c+x, b + y,z + offset];
+ positions += [c+x,-b + y,z + offset]
+ );
+ c_for(c = -b, c<=b, c+=1,
+ positions += [ a+x,c + y,z + offset];
+ positions += [-a+x,c + y,z + offset]
+ )
+ )
+ )
+);
+
+fill_flat_rectangle(pos, offset, dr, orientation, hollow) -> (
+ r = floor(dr);
+ drsq = dr^2;
+ positions = {};
+ if(orientation == 'x',
+ c_for(a = -r, a <=r, a +=1,
+ if(hollow,
+ positions += [r + offset, a, r];
+ positions += [r + offset, a,-r];
+ positions += [r + offset, r, a];
+ positions += [r + offset,-r, a],
+ c_for(b = -r, b <=r, b +=1,
+ positions += [r + offset, a, b]
+ )
+ )
+ ),
+ orientation == 'y',
+ c_for(a = -r, a <=r, a +=1,
+ if(hollow,
+ positions += [ r, r + offset,a];
+ positions += [-r, r + offset,a];
+ positions += [a, r + offset, r];
+ positions += [a, r + offset,-r],
+ c_for(b = -r, b <=r, b +=1,
+ positions += [a, r + offset, b]
+ )
+ )
+ ),
+ orientation == 'z',
+ c_for(a = -r, a <=r, a +=1,
+ if(hollow,
+ positions += [ r, a,r + offset];
+ positions += [-r, a,r + offset];
+ positions += [a, r, r + offset];
+ positions += [a,-r, r + offset],
+ c_for(b = -r, b <=r, b +=1,
+ positions += [b, a, r + offset]
+ )
+ )
+ ),
+ );
+ positions
+);