Skip to content

Commit 29e01a1

Browse files
authored
Merge pull request #392 from bcalabro/patch-1
Updated buildout_utility.java with new JNI function calls
2 parents 879f48e + 7a6a0ea commit 29e01a1

2 files changed

Lines changed: 214 additions & 55 deletions

File tree

sku.0/sys.server/compiled/game/script/base_class.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22791,6 +22791,18 @@ public static String getBuildoutAreaName( float x, float z )
2279122791
*/
2279222792
public static native float[] getBuildoutAreaSizeAndCenter( float x, float z, String sceneId, boolean ignoreInternal, boolean allowComposite );
2279322793

22794+
/**
22795+
* Return the buildout area rectangle coords
22796+
* (x,z) position.
22797+
* <p>
22798+
* returns: float array or null
22799+
* float[0] -> width
22800+
* float[1] -> height
22801+
* float[2] -> centerX
22802+
* float[3] -> centerZ
22803+
*/
22804+
public static native float[] getBuildoutAreaRect(float x, float z, String sceneId, boolean allowComposite);
22805+
2279422806
/**
2279522807
* Notify the mount that its wearable-related visuals must be updated.
2279622808
*

sku.0/sys.server/compiled/game/script/developer/buildout_utility.java

Lines changed: 202 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,37 @@
11
package script.developer;
22

3+
import script.dictionary;
34
import script.library.sui;
45
import script.library.utils;
56
import script.location;
67
import script.obj_id;
8+
import script.transform;
79

810
import java.io.IOException;
9-
import java.io.PrintWriter;
10-
import java.nio.charset.StandardCharsets;
1111
import java.util.Arrays;
12-
import java.util.List;
1312

1413
/**
1514
* SWG Buildout Utility
1615
* For World Building in the Release Game Client
1716
* To Use: attach developer.buildout_utility to your player and say "info" for commands
18-
*
17+
* <p>
1918
* Most usage will be creating an object either with this script or by some other means,
2019
* targeting it, and saying "getBuildoutInfo" in spatial which will give you an SUI window
2120
* of everything you need to type in to add that object to a buildout.
22-
*
21+
* <p>
2322
* *************************************************
2423
* This is a WORK IN PROGRESS
2524
* I'm adding it now upon request to help a few people get the gist of buildouts.
2625
* *************************************************
27-
*
26+
* <p>
2827
* Authors: Aconite
2928
*/
3029
public class buildout_utility extends script.base_script {
3130

32-
public buildout_utility()
33-
{
31+
public buildout_utility() {
32+
3433
}
3534

36-
// Only list planets in the SCENES array that are full size (16000x16000)
37-
// Only worlds at full size using -8192 to 8192 coordinates should be used otherwise the positioning will be off because the buildout names won't match to the correct positioning boxes.
38-
public static final String[] SCENES = {
39-
"tatooine",
40-
"yavin4",
41-
"mustafar",
42-
"endor",
43-
"talus",
44-
"corellia",
45-
"rori",
46-
"dathomir",
47-
"dantooine",
48-
"naboo",
49-
"lok"
50-
};
51-
5235
public int OnAttach(obj_id self) throws InterruptedException {
5336
sendSystemMessageTestingOnly(self, "Buildout Utility Attached... say INFO for help.");
5437
return SCRIPT_CONTINUE;
@@ -85,6 +68,10 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
8568
sendConsoleMessage(self, "returns all buildout information for the specified object");
8669
sendConsoleMessage(self, "\\#00ffff getObjects \\#.");
8770
sendConsoleMessage(self, "returns all objects within 500m with buildout_utility.write objvar");
71+
//sendConsoleMessage(self, "\\#00ffff setAllBuildOutObjVars \\#.");
72+
//sendConsoleMessage(self, "finds all objects in the buildout area and attaches buildout_utility.write objvar if not already attached");
73+
sendConsoleMessage(self, "\\#00ffff updateServerBuildout \\#.");
74+
sendConsoleMessage(self, "finds everything in the buildout area that does not have a buildout ID and writes it to a .tab file in the Linux directory");
8875
//sendConsoleMessage(self, "\\#00ffff writeBuildout \\#bfff00 <file name> \\#.");
8976
//sendConsoleMessage(self, "writes all objects within 500m range with the buildout_utility.write objvar to a buildout formatted .csv file swg-main/linux/exe");
9077
sendConsoleMessage(self, "\\#ffff00 ============ ============ ============ ============ \\#.");
@@ -119,36 +106,92 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
119106
return SCRIPT_CONTINUE;
120107
}
121108

122-
List<String> list = Arrays.asList(SCENES);
123-
if(!list.contains(getCurrentSceneName())) {
124-
sendSystemMessageTestingOnly(self, "You cannot use this feature in your current scene (likely due to world size mismatch).");
125-
return SCRIPT_CONTINUE;
109+
StringBuilder sb = new StringBuilder();
110+
111+
sb.append("Buildout Information for Object: ").append(oid).append("\n\n");
112+
113+
if (hasObjVar(oid, "buildoutObjectId")) {
114+
sb.append(getHeaderFormat("Object ID in Buildout File"));
115+
sb.append("\t").append(getIntObjVar(oid, "buildoutObjectId"));
116+
sb.append("\n\n");
126117
}
127118

128-
location wp = getLocation(oid);
129-
String buildout = getBuildoutAreaName(wp.x, wp.z);
130-
float coord_x = wp.x - getBuildoutRootCoords(buildout).x;
131-
float coord_z = wp.z - getBuildoutRootCoords(buildout).z;
132-
obj_id cell = wp.cell;
133-
float[] q = getQuaternion(oid);
134-
boolean isInBuilding = isIdValid(cell);
135-
obj_id container = null;
136-
if (isInBuilding) {
137-
container = getContainedBy(cell);
119+
sb.append(getHeaderFormat("Server Template")).append("\t").append(getTemplateName(oid)).append("\n\n");
120+
sb.append(getHeaderFormat("Shared Template")).append("\t").append(getSharedObjectTemplateName(oid)).append("\n\n");
121+
122+
final location objectLoc = getLocation(oid);
123+
location topLoc = getLocation(oid);
124+
sb.append(getHeaderFormat("Buildout Area"));
125+
if (isIdValid(getTopMostContainer(oid))) {
126+
topLoc = getLocation(getTopMostContainer(oid));
127+
}
128+
final String buildoutAreaName = getBuildoutAreaName(topLoc.x, topLoc.z);
129+
sb.append("\t").append(buildoutAreaName).append("\n\n");
130+
131+
sb.append(getHeaderFormat("Container"));
132+
if (isIdValid(objectLoc.cell)) {
133+
// if the cell has a buildout object ID, we need to display that instead
134+
// because that's what actually goes in the buildout
135+
if (hasObjVar(objectLoc.cell, "buildoutObjectId")) {
136+
sb.append("\t").append(getIntObjVar(objectLoc.cell, "buildoutObjectId"));
137+
} else {
138+
sb.append("\t").append(objectLoc.cell);
139+
}
140+
} else {
141+
sb.append("\t").append(0);
142+
}
143+
sb.append("\n\n");
144+
145+
// Cell Index
146+
sb.append(getHeaderFormat("Cell Index"));
147+
sb.append("\t").append(getCellIndex(objectLoc.cell));
148+
sb.append("\n\n");
149+
150+
boolean isComposite = false;
151+
// X Y Z coordinates
152+
float[] buildout = getBuildoutAreaSizeAndCenter(objectLoc.x, objectLoc.z, objectLoc.area, false, false);
153+
if (buildout == null || buildout.length < 3) {
154+
isComposite = true;
155+
buildout = getBuildoutAreaRect(objectLoc.x, objectLoc.z, objectLoc.area, true);
156+
}
157+
sb.append(getHeaderFormat("Object to Parent Coordinates (for Buildout) [pX, pY, pZ]"));
158+
if (isIdValid(objectLoc.cell)) {
159+
sb.append("\t").append(objectLoc.x).append(",\n");
160+
sb.append("\t").append(objectLoc.y).append(",\n");
161+
sb.append("\t").append(objectLoc.z).append(",\n");
162+
} else {
163+
if (isComposite) {
164+
sb.append("\t").append((objectLoc.x - buildout[0])).append(",\n");
165+
sb.append("\t").append(objectLoc.y).append(",\n");
166+
sb.append("\t").append((objectLoc.z - buildout[2]));
167+
} else {
168+
sb.append("\t").append((objectLoc.x - (buildout[2] - (buildout[0] / 2)))).append(",\n");
169+
sb.append("\t").append(objectLoc.y).append(",\n");
170+
sb.append("\t").append((objectLoc.z - (buildout[3] - (buildout[1] / 2))));
171+
}
138172
}
139-
String message = "Buildout Information for Object: " + oid + "\n\n" +
140-
"Reminder, this currently supports EXTERIOR objects only. Interiors should probably be using a dungeon_spawner or interior spawn egg anyways." + "\n\n" +
141-
"template: " + getTemplateName(oid) + "\n\n" +
142-
"buildout: " + buildout + "\n\n" +
143-
"cell ID: " + cell + "\n\n" +
144-
"container: " + container + "\n\n" +
145-
"world coordinates (X, Y, Z): "+wp.x+", "+wp.y+", "+wp.z + "\n\n" +
146-
"buildout coordinates (X, Y, Z): " + coord_x+", "+wp.y+", "+coord_z+"\n\n" +
147-
"quaternion (qW, qX, qY, qZ): " + q[0] + ", " + q[1] + ", " + q[2] + ", " + q[3] + " \n\n" +
148-
"scripts: " + Arrays.toString(getScriptList(oid)) + "\n\n" +
149-
"objvars: " + getPackedObjvars(oid);
150-
151-
sui.msgbox(self, self, message, sui.OK_ONLY, "getBuildoutCoords", "noHanlder");
173+
sb.append("\n\n");
174+
175+
final float[] quaternion = getQuaternion(oid);
176+
sb.append(getHeaderFormat("Quaternion [qW, qX, qY, qZ]"));
177+
sb.append("\t").append(quaternion[0]).append(",\n");
178+
sb.append("\t").append(quaternion[1]).append(",\n");
179+
sb.append("\t").append(quaternion[2]).append(",\n");
180+
sb.append("\t").append(quaternion[3]);
181+
sb.append("\n\n");
182+
183+
sb.append(getHeaderFormat("Scripts"));
184+
sb.append(Arrays.toString(getScriptList(oid)));
185+
sb.append("\n\n");
186+
187+
sb.append(getHeaderFormat("ObjVars"));
188+
sb.append(getPackedObjvars(oid));
189+
sb.append("\n\n");
190+
191+
final int pid = sui.msgbox(self, self, sb.toString(), sui.OK_ONLY, "getBuildoutInfo", sui.MSG_INFORMATION, "noHandler");
192+
setSUIProperty(pid, "Prompt.lblPrompt", "Editable", "true");
193+
setSUIProperty(pid, "Prompt.lblPrompt", "GetsInput", "true");
194+
flushSUIPage(pid);
152195

153196
// ===========================================================================
154197
// ===== writeBuildout
@@ -208,7 +251,7 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
208251
count++;
209252
}
210253

211-
String header = "Listing all objects within 500m with buildout_utility.write objvar \n Total object count: "+count+"\n\n";
254+
String header = "Listing all objects within 500m with buildout_utility.write objvar \n Total object count: " + count + "\n\n";
212255
sui.msgbox(self, self, header + Arrays.toString(objects), sui.OK_ONLY, "getObjects", "noHandler");
213256

214257
// ===========================================================================
@@ -245,19 +288,124 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
245288
obj_id object = createObject(command2, me);
246289
setObjVar(object, "buildout_utility.write", 1);
247290

248-
if(isValidId(object)) {
291+
if (isValidId(object)) {
249292
sendSystemMessageTestingOnly(self, "createObject: Success, new object OID is " + object);
250293
} else {
251294
sendSystemMessageTestingOnly(self, "createObject: ERROR creating object. Check your template spelling.");
252295
}
253296

297+
return SCRIPT_CONTINUE;
298+
} else if (command1.equalsIgnoreCase("getBuildoutAreaRect")) {
299+
location loc = getLocation(self);
300+
float[] rect = getBuildoutAreaRect(loc.x, loc.z, loc.area, true);
301+
sendSystemMessageTestingOnly(self, "Area Rect (as x0, x1, y0, y1) is: " + rect[0] + ", " + rect[1] + ", " + rect[2] + ", " + rect[3]);
302+
} else if (command1.equalsIgnoreCase("getYaw")) {
303+
sendSystemMessageTestingOnly(self, "Yaw is: " + getYaw(getTarget(self)));
304+
} else if (command1.equalsIgnoreCase("setYaw")) {
305+
setYaw(getTarget(self), Float.parseFloat(command2));
306+
} else if (command1.equalsIgnoreCase("getTransform")) {
307+
transform t = getTransform_o2p(getTarget(self));
308+
sendSystemMessageTestingOnly(self, t.getLocalFrameI_p().toString());
309+
sendSystemMessageTestingOnly(self, t.getLocalFrameJ_p().toString());
310+
sendSystemMessageTestingOnly(self, t.getLocalFrameK_p().toString());
311+
} else if (command1.equalsIgnoreCase("updateServerBuildout")) {
312+
//get the current buildout area
313+
location here = getLocation(self);
314+
obj_id containingBuilding = getTopMostContainer(self);
315+
if (isIdValid(containingBuilding)) {
316+
here = getLocation(containingBuilding);
317+
}
318+
String buildoutAreaName = getBuildoutAreaName(here.x, here.z, getCurrentSceneName());
319+
String sceneName = getCurrentSceneName();
320+
sendSystemMessageTestingOnly(self, "Updating buildout for " + buildoutAreaName);
321+
//updateServerBuildout(self, sceneName, buildoutAreaName);
322+
return SCRIPT_CONTINUE;
323+
} else if (command1.equalsIgnoreCase("setAllBuildOutObjVars")) {
324+
obj_id[] objects = utils.getAllObjectsInBuildoutArea(self);
325+
326+
int count = 0;
327+
int addedCount = 0; // Count of objects we added objVar to
328+
329+
for (obj_id i : objects) {
330+
//skip player
331+
if (i == self) {
332+
continue;
333+
}
334+
count++;
335+
336+
// Check if the object has buildout objvar
337+
if (!hasObjVar(i, "buildout_utility.write")) {
338+
// Set the objvar on the object
339+
setObjVar(i, "buildout_utility.write", 1); // add objVar
340+
addedCount++;
341+
}
342+
}
343+
sendSystemMessageTestingOnly(self, "Added buildout_utility.write to " + addedCount + " out of " + count + " total objects in buildout");
344+
} else if (command1.equalsIgnoreCase("move")) {
345+
if (!tok.hasMoreTokens()) {
346+
sendSystemMessageTestingOnly(self, "SYNTAX: move <x> <y> <z>");
347+
return SCRIPT_CONTINUE;
348+
}
349+
350+
// parse floats from the command tokens
351+
float moveX = 0f;
352+
float moveY = 0f;
353+
float moveZ = 0f;
354+
try {
355+
moveX = Float.parseFloat(command2); // we already had command2 as nextToken()
356+
if (tok.hasMoreTokens()) {
357+
moveY = Float.parseFloat(tok.nextToken());
358+
}
359+
if (tok.hasMoreTokens()) {
360+
moveZ = Float.parseFloat(tok.nextToken());
361+
}
362+
} catch (Exception e) {
363+
sendSystemMessageTestingOnly(self, "Error parsing move coordinates. Usage: move <x> <y> <z>");
364+
return SCRIPT_CONTINUE;
365+
}
366+
367+
// get the target object
368+
obj_id target = getTarget(self);
369+
if (!isIdValid(target)) {
370+
sendSystemMessageTestingOnly(self, "You have no valid target!");
371+
return SCRIPT_CONTINUE;
372+
}
373+
374+
// get the target’s current location and move it
375+
location currentLoc = getLocation(target);
376+
currentLoc.x += moveX;
377+
currentLoc.y += moveY;
378+
currentLoc.z += moveZ;
379+
380+
// set the target’s new location
381+
setLocation(target, currentLoc);
382+
383+
sendSystemMessageTestingOnly(self, "Moved target by (" + moveX + ", " + moveY + ", " + moveZ + ")");
254384
return SCRIPT_CONTINUE;
255385
}
386+
256387
return SCRIPT_CONTINUE;
257388
}
258389

390+
public static int getCellIndex(obj_id cell) {
391+
if (isIdValid(cell)) {
392+
return Arrays.asList(getCellIds(getTopMostContainer(cell))).indexOf(cell);
393+
}
394+
return 0;
395+
}
396+
397+
public static boolean isWorldCoordinateOffset(String scene) {
398+
dictionary d = dataTableGetRow("datatables/buildout/buildout_scenes.iff", scene);
399+
return d != null && d.getInt("adjust_map_coordinates") > 0;
400+
}
401+
402+
public static String getHeaderFormat(String header) {
403+
return "\\#00FFFF" + header + ":\\#.\n";
404+
}
405+
259406
// ===========================================================================
260407
// ===== getBuildoutRootCoords
408+
// - BMC: 05/07/2025 - keeping this function here as some other code may still be using it.
261409
// ===========================================================================
262410
public static location getBuildoutRootCoords(String buildoutAreaName) throws InterruptedException {
263411
String buildoutAreaNumber = buildoutAreaName.substring(buildoutAreaName.length() - 3);
@@ -395,5 +543,4 @@ public static location getBuildoutRootCoords(String buildoutAreaName) throws Int
395543
return new location(0f, 0f, 0f);
396544
}
397545
}
398-
399-
}
546+
}

0 commit comments

Comments
 (0)