Require distinct panorama locations for rounds and captures
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 6m30s

This commit is contained in:
2026-10-16 10:09:36 +05:00
parent c9fc9496eb
commit 1a34eb71c2
16 changed files with 367 additions and 3 deletions

View File

@@ -29,7 +29,7 @@ public final class MineGeoClient implements ClientModInitializer {
public String server(){var c=MinecraftClient.getInstance();return c.getCurrentServerEntry()!=null?c.getCurrentServerEntry().address:"Singleplayer";}
public void saveConfig()throws Exception{Files.createDirectories(config.getParent());var j=new JsonObject();j.addProperty("token",token);j.addProperty("targetMap",targetMap);Files.writeString(config,gson.toJson(j));}
public void message(String text){status=text;var c=MinecraftClient.getInstance();if(c.player!=null)c.player.sendMessage(Text.literal("[MineGeo] "+text),false);}
public void capture(){try{if(dataset==null)throw new IllegalStateException("Join an Overworld and explore first");var c=MinecraftClient.getInstance();if(!dataset.contains(c.player.getX(),c.player.getZ()))throw new IllegalStateException("Outside this map's 512-block boundary. Start a new map here.");int limit=24;if(dataset.points.size()>=limit)throw new IllegalStateException("This capture already contains "+limit+" locations");pending=new SurfaceDataset.Point("p"+java.util.UUID.randomUUID().toString().replace("-","").substring(0,12),c.player.getX(),c.player.getEyeY(),c.player.getZ());c.setScreen(null);Capture.start(dataset.directory.resolve(pending.id()));message("Capturing six views. Stand still; press G to cancel.");}catch(Exception e){message(e.getMessage());}}
public void capture(){try{if(uploading||Capture.active())throw new IllegalStateException("Finish the current operation first");if(dataset==null)throw new IllegalStateException("Join an Overworld and explore first");var c=MinecraftClient.getInstance();if(!dataset.contains(c.player.getX(),c.player.getZ()))throw new IllegalStateException("Outside this map's 512-block boundary. Start a new map here.");int limit=24;if(dataset.points.size()>=limit)throw new IllegalStateException("This capture already contains "+limit+" locations");if(dataset.hasLocation(c.player.getX(),c.player.getEyeY(),c.player.getZ()))throw new IllegalStateException("This location is already captured. Move to another block first.");pending=new SurfaceDataset.Point("p"+java.util.UUID.randomUUID().toString().replace("-","").substring(0,12),c.player.getX(),c.player.getEyeY(),c.player.getZ());c.setScreen(null);Capture.start(dataset.directory.resolve(pending.id()));message("Capturing six views. Stand still; press G to cancel.");}catch(Exception e){message(e.getMessage());}}
public void savedCapture(Path path){try{if(pending==null||!path.getFileName().toString().equals(pending.id()))return;dataset.points.add(pending);dataset.save();message("Panorama saved locally ("+dataset.points.size()+" total). Press G for preview or upload.");}catch(Exception e){message("Saving capture failed: "+e.getMessage());}finally{pending=null;}}
public void newMap(){try{if(uploading||Capture.active())throw new IllegalStateException("Finish the current operation first");dataset=SurfaceDataset.create(server());message("New 512 × 512 map started. Older maps remain in .minecraft/minegeo.");}catch(Exception e){message(e.getMessage());}}
public void pair(){background.execute(()->{try{saveConfig();var uploader=new UploadClient("");var pair=uploader.beginPairing();String code=pair.get("deviceCode").getAsString();String link=pair.get("verificationUri").getAsString();MinecraftClient.getInstance().execute(()->{message("Approve code "+pair.get("userCode").getAsString()+" at "+link);net.minecraft.util.Util.getOperatingSystem().open(link);});for(int i=0;i<120;i++){Thread.sleep(5000);var response=uploader.pollPairing(code);if(response.get("status").getAsString().equals("approved")){token=response.get("token").getAsString();saveConfig();MinecraftClient.getInstance().execute(()->message("Account linked. You can upload maps now."));return;}}throw new IllegalStateException("Pairing expired. Try linking again.");}catch(Exception e){MinecraftClient.getInstance().execute(()->message("Pairing: "+e.getMessage()));}});}

View File

@@ -20,6 +20,7 @@ public final class SurfaceDataset {
private SurfaceDataset(Path directory,String server,int x,int z){this.directory=directory;this.server=server;minX=x;minZ=z;for(int iz=0;iz<512;iz++)for(int ix=0;ix<512;ix++)image.setRGB(ix,iz,((ix/16+iz/16)%2==0)?0xff4c493d:0xff3b3932);}
public static SurfaceDataset create(String server)throws Exception{var c=MinecraftClient.getInstance();var root=c.runDirectory.toPath().resolve("minegeo");Files.createDirectories(root);var dataset=new SurfaceDataset(root.resolve(UUID.randomUUID().toString()),server,(Math.floorDiv(c.player.getBlockX(),16)-16)*16,(Math.floorDiv(c.player.getBlockZ(),16)-16)*16);Files.createDirectories(dataset.directory);dataset.saveLocal();return dataset;}
public static SurfaceDataset open(String server)throws Exception{Path root=MinecraftClient.getInstance().runDirectory.toPath().resolve("minegeo");if(Files.exists(root)){try(var dirs=Files.list(root)){for(Path path:dirs.sorted(Comparator.reverseOrder()).toList()){Path state=path.resolve("local.json");if(!Files.exists(state))continue;var j=JsonParser.parseString(Files.readString(state)).getAsJsonObject();if(!j.get("server").getAsString().equals(server))continue;var d=new SurfaceDataset(path,server,j.get("minX").getAsInt(),j.get("minZ").getAsInt());d.name=j.get("name").getAsString();for(var p:j.getAsJsonArray("viewpoints")){var v=p.getAsJsonObject();d.points.add(new Point(v.get("id").getAsString(),v.get("x").getAsDouble(),v.get("y").getAsDouble(),v.get("z").getAsDouble()));}for(var k:j.getAsJsonArray("coverage"))d.coverage.add(k.getAsString());if(Files.exists(path.resolve("map.png"))){var saved=ImageIO.read(path.resolve("map.png").toFile());d.image.getGraphics().drawImage(saved,0,0,null);}return d;}}}return create(server);}
public boolean hasLocation(double x,double y,double z){return points.stream().anyMatch(p->Math.floor(p.x())==Math.floor(x)&&Math.floor(p.y())==Math.floor(y)&&Math.floor(p.z())==Math.floor(z));}
public boolean contains(double x,double z){return x>=minX&&x<minX+512&&z>=minZ&&z<minZ+512;}
public void scan(MinecraftClient c){
if(scanning==null){int px=Math.floorDiv(c.player.getBlockX(),16),pz=Math.floorDiv(c.player.getBlockZ(),16);outer:for(int radius=0;radius<=12;radius++)for(int dz=-radius;dz<=radius;dz++)for(int dx=-radius;dx<=radius;dx++){if(Math.max(Math.abs(dx),Math.abs(dz))!=radius)continue;int cx=px+dx,cz=pz+dz;String key=cx+","+cz;if(coverage.contains(key)||!contains(cx*16,cz*16))continue;if(c.world.getChunk(cx,cz,ChunkStatus.FULL,false)==null)continue;scanning=key;chunkX=cx;chunkZ=cz;cursor=0;break outer;}}