-
Notifications
You must be signed in to change notification settings - Fork 0
/
ShipConstructor.java
287 lines (237 loc) · 12.4 KB
/
ShipConstructor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
package com.prplplus.shipconstruct;
//static imports are here so that the hull in examples isn't infinitely long
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_BLOCK;
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_CORNER_LB;
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_CORNER_LT;
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_CORNER_RB;
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_CORNER_RT;
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_SPIKE_B;
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_SPIKE_L;
import static com.prplplus.shipconstruct.Hull.HULL_ARMOR_SPIKE_T;
import static com.prplplus.shipconstruct.Hull.HULL_BLOCK;
import static com.prplplus.shipconstruct.Hull.HULL_SPACE;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
public class ShipConstructor {
private static void pushBytes(ByteArrayOutputStream buffer, String bytes) {
bytes = bytes.replaceAll("\\s+", "");
for (int i = 0; i < bytes.length(); i += 2) {
String str = bytes.substring(i, i + 2);
int data = Integer.parseInt(str, 16);
buffer.write(data);
}
}
//in little endian format
private static void pushIntLE(ByteArrayOutputStream buffer, int val, int bytes) {
for (int i = 0; i < bytes; i++) {
buffer.write(val);
val = val >>> 8;
}
}
private static void pushIntLE(ByteArrayOutputStream buffer, int val) {
pushIntLE(buffer, val, 4);
}
private static void pushStringWithLength(ByteArrayOutputStream buffer, String string) {
pushIntLE(buffer, string.length(), 2); //only 2 byte in the name length
//the name itself
try {
buffer.write(string.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
public static String construct(Ship ship) {
return construct(ship.width, ship.height, ship.hull, ship.modules, ship.commandX, ship.commandY,
ship.name, ship.designer, ship.description, ship.CITG_ID, ship.instabuild);
}
public static String construct(int width, int height, int[] hull, List<ModuleAtPosition> modules, int centerX, int centerY,
String name, String designer, String description, String CITG_ID, boolean instabuild) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
//fix input data
if (designer == null)
designer = "";
if (description == null)
description = "";
if (CITG_ID == null)
CITG_ID = "";
modules = modules.stream().filter(m -> !m.module.isCustom()).collect(Collectors.toList()); //remove custom modules
//header
pushBytes(buffer, "0A04 0072 6F6F 7403 0100 73");
//ship type
if (instabuild) {
pushStringWithLength(buffer, "Ship8");
} else {
pushStringWithLength(buffer, "Ship99");
}
//designer, description and CITG
pushBytes(buffer, "03 0100 61");
pushStringWithLength(buffer, designer);
pushBytes(buffer, "03 0100 64");
pushStringWithLength(buffer, description);
pushBytes(buffer, "03 0200 636B");
pushStringWithLength(buffer, CITG_ID);
//rest of the header
pushBytes(buffer, "E9 0300 6D70 73");
//number of modules
pushIntLE(buffer, modules.size());
//module data
for (ModuleAtPosition module : modules) {
pushIntLE(buffer, Module.encodePosition(module.module.code));
pushIntLE(buffer, Module.encodePosition(module.x));
pushIntLE(buffer, Module.encodePosition(module.y));
}
//always the same data
pushBytes(buffer, "01 0200 6877");
//width
pushIntLE(buffer, width);
//always the same data
pushBytes(buffer, "0102 0068 68");
//height
pushIntLE(buffer, height);
//always the same data
pushBytes(buffer, "0B 0200 6870");
//total hull size
pushIntLE(buffer, width * height);
//hull info
for (int hullPiece : hull) {
pushIntLE(buffer, hullPiece);
}
//always the same data
pushBytes(buffer, "0103 0063 6D78");
//x position of the center
pushIntLE(buffer, centerX);
//always the same data
pushBytes(buffer, "0103 0063 6D79");
//y position of the center
pushIntLE(buffer, centerY);
//always the same data
pushBytes(buffer, "0302 0073 6E");
//length of the name
pushIntLE(buffer, name.length(), 2); //only 2 byte in the name length
//the name itself
try {
buffer.write(name.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace(System.out);
}
//and finally a zero at the end
pushBytes(buffer, "00");
byte[] result = buffer.toByteArray();
//System.out.println("Width: " + width + ", height: " + height);
//result = Base64.getDecoder().decode("CgQAcm9vdAMBAHMGAFNoaXA5OekDAG1wcwIAAAAAAABAAAAAAAAAAEAAAABAAACAQAAAAEABAgBodwUAAAABAgBoaAUAAAALAgBocBkAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQMAY214AQAAAAEDAGNteQEAAAADAgBzbgoARXhwb3J0VGVzdAA=");
/*int[] result1 = new int[result.length];
for (int i = 0; i < result1.length; i++) {
result1[i] = result[i] >= 0 ? result[i] : result[i] + 256;
}
System.out.println(Arrays.toString(result1));*/
return Base64.getEncoder().encodeToString(result);
}
//A test/debug method for building a 3x3 shi with just the command module
public static String constructDummy() {
int[] hull = { HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK };
return construct(3, 3, hull, new ArrayList<>(), 0, 0, "DUMMY", null, null, null, false);
}
// A test/showcase method for building a Lathe
public static String constructLathe() {
int width = 12;
int height = 7;
int[] hull = {
HULL_SPACE, HULL_ARMOR_SPIKE_T, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_ARMOR_SPIKE_T, HULL_SPACE, HULL_SPACE, HULL_SPACE,
HULL_ARMOR_CORNER_RT, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LT, HULL_SPACE, HULL_SPACE,
HULL_SPACE, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LT, HULL_SPACE,
HULL_SPACE, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_SPIKE_L,
HULL_SPACE, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LB, HULL_SPACE,
HULL_ARMOR_CORNER_RB, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LB, HULL_SPACE, HULL_SPACE,
HULL_SPACE, HULL_ARMOR_SPIKE_B, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_ARMOR_SPIKE_B, HULL_SPACE, HULL_SPACE, HULL_SPACE
};
List<ModuleAtPosition> modules = new ArrayList<>();
modules.add(new ModuleAtPosition(1, 2, Module.ENGINE));
modules.add(new ModuleAtPosition(6, 2, Module.LATHE));
modules.add(new ModuleAtPosition(9, 3, Module.LASER));
int centerX = 3;
int centerY = 2;
String name = "LATHE";
return construct(width, height, hull, modules, centerX, centerY, name, "Tester", "Test lathe", null, false);
}
// A test/showcase method for building a Cruiser
public static String constructCruiser() {
int width = 11;
int height = 9;
int[] hull = {
HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_ARMOR_CORNER_RT, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LT, HULL_SPACE, HULL_SPACE,
HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_ARMOR_CORNER_RT, HULL_ARMOR_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LT, HULL_SPACE,
HULL_ARMOR_CORNER_RT, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LT,
HULL_SPACE, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK,
HULL_SPACE, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK,
HULL_SPACE, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK,
HULL_ARMOR_CORNER_RB, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LB,
HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_ARMOR_CORNER_RB, HULL_ARMOR_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LB, HULL_SPACE,
HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_SPACE, HULL_ARMOR_CORNER_RB, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_BLOCK, HULL_ARMOR_CORNER_LB, HULL_SPACE, HULL_SPACE
};
List<ModuleAtPosition> modules = new ArrayList<>();
modules.add(new ModuleAtPosition(1, 3, Module.ENGINE));
modules.add(new ModuleAtPosition(5, 6, Module.MISSLE_LAUNCHER));
modules.add(new ModuleAtPosition(7, 5, Module.CANNON));
modules.add(new ModuleAtPosition(9, 4, Module.LASER));
modules.add(new ModuleAtPosition(8, 4, Module.PARTICLE_BEAM));
modules.add(new ModuleAtPosition(7, 2, Module.CANNON));
modules.add(new ModuleAtPosition(5, 1, Module.MISSLE_LAUNCHER));
int centerX = 4;
int centerY = 3;
String name = "CRUISER";
String designer = "ShipConstr";
String description = "A demostration of creating a cruiser ship in program.";
String CITG_ID = "c94bc32d1c0e9e18c6566cfa9087bc7f";
boolean instabuild = false;
return construct(width, height, hull, modules, centerX, centerY, name, designer, description, CITG_ID, instabuild);
}
//a debug method
public static void printB64(String encoded) {
byte[] data = Base64.getDecoder().decode(encoded);
for (int i = 0; i < data.length; i += 16) {
for (int j = 0; j < 16 && i + j < data.length; j++) {
int value = data[i + j];
value += value < 0 ? 256 : 0;
System.out.format("%02X", value);
if (j % 2 == 1) {
System.out.print(' ');
}
}
System.out.println();
}
System.out.println();
}
public static void main(String[] args) {
System.out.println("Dummy: " + constructDummy());
System.out.println("Lathe: " + constructLathe());
System.out.println("Cruiser: " + constructCruiser());
}
public static class Ship {
public int width, height;
public int[] hull;
public List<ModuleAtPosition> modules;
public int commandX, commandY;
public String name;
public String designer;
public String description;
public String CITG_ID;
public boolean instabuild;
public Ship(int width, int height, int[] hull, List<ModuleAtPosition> modules, int commandX, int commandY,
String name, String designer, String description, String CITG_ID, boolean instabuild) {
this.width = width;
this.height = height;
this.hull = hull;
this.modules = modules;
this.commandX = commandX;
this.commandY = commandY;
this.name = name;
this.designer = designer;
this.description = description;
this.CITG_ID = CITG_ID;
this.instabuild = instabuild;
}
}
}