Schematics experimental support
Some checks failed
/ Auto-Build-App (push) Failing after 14m33s

This commit is contained in:
pietru 2025-04-28 23:58:30 +02:00
parent 807ffa76a1
commit 032d553038
7 changed files with 392 additions and 1 deletions

View file

@ -4,7 +4,7 @@ org.gradle.parallel=true
org.gradle.caching=false
# Project Info
version=1.0.10
version=1.0.11
group=net.pietru
id=cookie_utils

View file

@ -42,6 +42,7 @@ public class TextCommands {
commands.put("vis_claim",new vis_area_claim_command());
commands.put("my_claims",new my_claims_command());
commands.put("setup",new setup_command());
commands.put("schem_paste",new schematic_command());
commands.put("region",new region_command());
commands.put("kit",new kit_command());

View file

@ -0,0 +1,62 @@
package net.pietru.cookie_utils.commands;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Json;
import finalforeach.cosmicreach.entities.player.Player;
import finalforeach.cosmicreach.io.SaveLocation;
import finalforeach.cosmicreach.networking.NetworkIdentity;
import finalforeach.cosmicreach.networking.packets.MessagePacket;
import finalforeach.cosmicreach.world.Zone;
import io.netty.channel.ChannelHandlerContext;
import net.pietru.cookie_utils.utils.Schematic;
import net.pietru.cookie_utils.utils.block_util;
import java.io.File;
import java.util.Arrays;
import static net.pietru.cookie_utils.utils.directory_utils.get_path_string;
public class schematic_command extends BaseCommand {
@Override
public String get_command_key() {
return "schem_paste";
}
@Override
public void accept(String[] args, NetworkIdentity networkIdentity, ChannelHandlerContext ctx) {
Player player = networkIdentity.getPlayer();
MessagePacket packet = new MessagePacket("");
if (args.length<=1){
packet.message="[Server] Invalid arguments...";
packet.setupAndSend(ctx);
return;
}
System.out.println(Arrays.toString(args));
Zone zone = player.getZone();
boolean ignored = new File(SaveLocation.getSaveFolderLocation() + "/schematics").mkdirs();
File file_path = new File(get_path_string(SaveLocation.getSaveFolder().getPath(),"schematics",args[1]+".json"));
if (!file_path.exists()) {
packet.message="File no exists " + args[1] + ".json";
return;
}
try {
FileHandle file = new FileHandle(file_path);
Json json = new Json();
Schematic data = json.fromJson(Schematic.class,file);
data.paste_blocks(block_util.getBlockPositionFromGlobalXYZ(zone,player.getPosition()),zone);
System.out.println("Successfully pasted schematic.");
packet.message="Loaded schematic from "+args[1]+".json";
} catch (Exception e) {
System.out.println("An error occurred while loading schematic.");
packet.message="Error occured when loading from "+args[1]+".json";
e.printStackTrace();
}
packet.setupAndSend(ctx);
}
public String getDescription() {
return "save [name] | load [name] | near | Allows to save schematics made with anchors";
}
}

View file

@ -0,0 +1,146 @@
package net.pietru.cookie_utils.setups;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import finalforeach.cosmicreach.blocks.BlockPosition;
import finalforeach.cosmicreach.blocks.BlockState;
import finalforeach.cosmicreach.entities.player.Player;
import finalforeach.cosmicreach.io.SaveLocation;
import finalforeach.cosmicreach.networking.packets.MessagePacket;
import finalforeach.cosmicreach.networking.server.ServerIdentity;
import finalforeach.cosmicreach.networking.server.ServerSingletons;
import finalforeach.cosmicreach.world.Zone;
import net.pietru.cookie_utils.api.Area;
import net.pietru.cookie_utils.api.Region;
import net.pietru.cookie_utils.permissions.ObjectPermList;
import net.pietru.cookie_utils.permissions.PlayerAreaPerm;
import net.pietru.cookie_utils.utils.Schematic;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import static net.pietru.cookie_utils.utils.directory_utils.get_path_string;
import static net.pietru.cookie_utils.utils.player_utils.*;
public class schemSave extends Setup {
BlockPosition p1;
BlockPosition p2;
BlockPosition p3;
String name="";
Zone zone;
String ownerId="";
Schematic data;
public schemSave() {
steps.add(()->{});
steps.add(()->{});
steps.add(()->{});
steps.add(()->{
if (zone==null) {
Setup.cancel(creatorId);
return;
}
data = new Schematic();
Vector3 a = new Vector3(p1.getGlobalX(),p1.getGlobalY(),p1.getGlobalZ());
Vector3 b = new Vector3(p2.getGlobalX(),p2.getGlobalY(),p2.getGlobalZ());
BoundingBox bb = new BoundingBox(a,b);
bb.update();
data.store_blocks(p1,p2,zone,new Vector3(
p3.getGlobalX()-bb.min.x,
p3.getGlobalY()-bb.min.y,
p3.getGlobalZ()-bb.min.z
));
step_hints.add("Schematic saved...");
run_setup_finish();
});
step_hints.add("Please select first position...");
step_hints.add("Please select second position...");
step_hints.add("Please select offset position...");
step_hints.add("Please enter schematic name (single word)...");
}
public static void register() {
setupCreator.registerSetupCreator("schemSave", schemSave::new);
}
@Override
public String get_setup_perm() {
return "setup.schemSave";
}
@Override
public void run_setup_finish() {
isActive=false;
File schem_file = new File(get_path_string(SaveLocation.getSaveFolder().getPath(),"schematics",name));
if (!schem_file.getParentFile().exists())
schem_file.getParentFile().mkdirs();
MessagePacket packet;
ServerIdentity idt = ServerSingletons.getConnection(parseAsPlayer(creatorId));
try {
Schematic.save_schematic_by_name(data,name);
packet = new MessagePacket("1/4 Saved as "+name+".json");
packet.setupAndSend(idt);
Schematic.save_schematic_by_name(Schematic.rotate_schematic(Vector3.Y,90,data),name+"_90");
packet = new MessagePacket("2/4 Saved as "+name+"_90.json");
packet.setupAndSend(idt);
Schematic.save_schematic_by_name(Schematic.rotate_schematic(Vector3.Y,180,data),name+"_180");
packet = new MessagePacket("3/4 Saved as "+name+"_180.json");
packet.setupAndSend(idt);
Schematic.save_schematic_by_name(Schematic.rotate_schematic(Vector3.Y,-90,data),name+"_270");
packet = new MessagePacket("4/4 Saved as "+name+"_270.json");
packet.setupAndSend(idt);
} catch (IOException e) {
System.out.println("An error occurred while saving schematic.");
packet = new MessagePacket("Error occured when saving to "+name+".json");
packet.setupAndSend(idt);
e.printStackTrace();
}
}
@Override
public void run_setup_canceled() {
}
@Override
public boolean set_setup_text(String value) {
if (step==3)
name=value;
return step==3;
}
@Override
public boolean set_setup_vector3(Vector3 value) {
return false;
}
@Override
public boolean set_setup_block_pos(BlockPosition value) {
if (step==0) {
p1 = value;//new Vector3(value.getGlobalX(), value.getGlobalY(), value.getGlobalZ());
zone = value.getZone();
}
else if (step==1) {
p2 = value;
if (!Objects.equals(zone, value.getZone()))
zone=null;
}
else if (step==2) {
p3 = value;
if (!Objects.equals(zone, value.getZone()))
zone=null;
}
return step==0 || step==1 || step==2;
}
}

View file

@ -9,6 +9,7 @@ public interface setupCreator {
regionSetup.register();
areaPermSetup.register();
areaFillSetup.register();
schemSave.register();
}
static void registerSetupCreator(String setupId, setupCreator creator) {

View file

@ -0,0 +1,175 @@
package net.pietru.cookie_utils.utils;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.utils.*;
import finalforeach.cosmicreach.GameAssetLoader;
import finalforeach.cosmicreach.blocks.BlockPosition;
import finalforeach.cosmicreach.blocks.BlockState;
import finalforeach.cosmicreach.blocks.MissingBlockStateResult;
import finalforeach.cosmicreach.io.SaveLocation;
import finalforeach.cosmicreach.world.BlockSetter;
import finalforeach.cosmicreach.world.Zone;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Schematic implements Json.Serializable {
public Vector3 offset = Vector3.Zero;
public Vector3 size = Vector3.Zero;
public String[] blockStates = new String[0];
public void store_blocks(BlockPosition start, BlockPosition end, Zone zone){
store_blocks(start,end,zone,Vector3.Zero);
}
public void store_blocks(BlockPosition start, BlockPosition end, Zone zone, Vector3 offset){
this.offset=offset;
Vector3 a = new Vector3(start.getGlobalX(),start.getGlobalY(),start.getGlobalZ());
Vector3 b = new Vector3(end.getGlobalX(),end.getGlobalY(),end.getGlobalZ());
BoundingBox bb = new BoundingBox(a,b);
bb.update();
bb.getDimensions(size);
blockStates=new String[(int) (size.x*size.y*size.z)];
start=block_util.getBlockPositionFromGlobalXYZ(zone,(int)bb.min.x,(int)bb.min.y,(int)bb.min.z);
for (int x = 0; x < size.x; x++) {
for (int y = 0; y < size.y; y++) {
for (int z = 0; z < size.z; z++) {
blockStates[(int) (x+y*size.x+z*size.x*size.y)]=start.getOffsetBlockPos(zone,x,y,z).getBlockState().toString();
}
}
}
}
public void paste_blocks(BlockPosition start, Zone zone){
paste_blocks(start,zone,offset);
}
public void paste_blocks(BlockPosition start, Zone zone, Vector3 offset){
for (int x = 0; x < size.x; x++) {
for (int y = 0; y < size.y; y++) {
for (int z = 0; z < size.z; z++) {
BlockPosition pos = start.getOffsetBlockPos(zone, (int) (x-offset.x), (int) (y-offset.y), (int) (z-offset.z));
String block = get_block(x,y,z);
BlockSetter.get().replaceBlock(zone, BlockState.getInstance(block, MissingBlockStateResult.MISSING_OBJECT),pos);
}
}
}
}
public String get_block(BlockPosition pos){
return get_block(pos.getGlobalX(),pos.getGlobalY(),pos.getGlobalZ());
}
public String get_block(Vector3 pos){
return get_block((int) pos.x, (int) pos.y, (int) pos.z);
}
public String get_block(int x, int y, int z){
return blockStates[(int) (x+y*size.x+z*size.x*size.y)];
}
public static Schematic rotate_schematic(Vector3 axis, int degrees, Schematic schem){
Schematic new_schematic = new Schematic();
new_schematic.blockStates=new String[schem.blockStates.length];
while (degrees>180 || degrees<-180){
if (degrees>180)
degrees-=360;
if (degrees<-180)
degrees+=360;
}
switch (degrees) {
case 0 -> {
new_schematic.size.set(schem.size);
new_schematic.offset=schem.offset.cpy();
}
case 90 -> {
new_schematic.size=new Vector3(schem.size.z,schem.size.y,schem.size.x);
new_schematic.offset=new Vector3(schem.offset.z,schem.offset.y,-schem.offset.x+schem.size.x-1);
}
case 180 -> {
new_schematic.size=schem.size.cpy();
new_schematic.offset=new Vector3(-schem.offset.z+schem.size.z-1,schem.offset.y,-schem.offset.x+schem.size.x-1);
}
case -90 -> {
new_schematic.size=new Vector3(schem.size.z,schem.size.y,schem.size.x);
new_schematic.offset=new Vector3(-schem.offset.z+schem.size.z-1,schem.offset.y,schem.offset.x);
}
}
Vector3 size = new_schematic.size;
for (int x = 0; x < schem.size.x; x++) {
for (int y = 0; y < schem.size.y; y++) {
for (int z = 0; z < schem.size.z; z++) {
switch (degrees) {
case 0 -> {
new_schematic.blockStates[(int) (x + y * size.x + z * size.x * size.y)] = schem.get_block(x, y, z);
}
case 90 -> {
new_schematic.blockStates[(int) (z + y * size.x + (-x+schem.size.x-1) * size.x * size.y)] = schem.get_block(x, y, z);
}
case 180 -> {
new_schematic.blockStates[(int) ((-x+schem.size.x-1) + y * size.x + (-z+schem.size.z-1) * size.x * size.y)] = schem.get_block(x, y, z);
}
case -90 -> {
new_schematic.blockStates[(int) ((-z+schem.size.z-1) + y * size.x + x * size.x * size.y)] = schem.get_block(x, y, z);
}
}
}
}
}
return new_schematic;
}
public static void save_schematic_by_name(Schematic schem, String name) throws IOException {
boolean ignored = new File(SaveLocation.getSaveFolderLocation() + "/schematics").mkdirs();
String file_path = SaveLocation.getSaveFolderLocation() + "/schematics/"+name+".json";
save_schematic(schem,file_path);
}
public static void save_schematic(Schematic schem, String path) throws IOException {
File file = new File(path);
FileWriter myWriter = new FileWriter(file);
Json json = new Json();
json.setOutputType(JsonWriter.OutputType.json);
myWriter.write(json.toJson(schem));
myWriter.close();
System.out.println("Successfully saved schematic.");
}
public static Schematic load_schematic_by_name(String name){
String file_path = SaveLocation.getSaveFolderLocation() + "/schematics/"+name+".json";
return load_schematic(file_path);
}
public static Schematic load_schematic(String path){
FileHandle fh = GameAssetLoader.loadAsset(path);
if (!fh.exists()) {
System.out.println("Schematic at " + path + " not found");
return null;
}
return new Json().fromJson(Schematic.class,fh);
}
@Override
public void write(Json json) {
json.writeValue("offset",offset);
json.writeValue("size",size);
json.writeValue("blockStates",blockStates);
}
@Override
public void read(Json json, JsonValue jsonValue) {
JsonValue v = jsonValue.get("offset");
offset=new Vector3(v.getFloat("x",0),v.getFloat("y",0),v.getFloat("z",0));
JsonValue s = jsonValue.get("size");
size=new Vector3(s.getFloat("x",0),s.getFloat("y",0),s.getFloat("z",0));
JsonValue states = jsonValue.get("blockStates");
blockStates=states.asStringArray();
}
}

View file

@ -1,10 +1,16 @@
package net.pietru.cookie_utils.utils;
import com.badlogic.gdx.math.Vector3;
import finalforeach.cosmicreach.blocks.BlockPosition;
import finalforeach.cosmicreach.world.Chunk;
import finalforeach.cosmicreach.world.Zone;
public class block_util {
public static BlockPosition getBlockPositionFromGlobalXYZ(Zone zone, Vector3 pos) {
return getBlockPositionFromGlobalXYZ(zone, (int) pos.x, (int) pos.y, (int) pos.z);
}
public static BlockPosition getBlockPositionFromGlobalXYZ(Zone zone, int x, int y, int z) {
Chunk c = zone.getChunkAtBlock(x, y, z);
if (c == null) {