Skip to content

Commit a013a02

Browse files
committed
v1.2
1 parent d506192 commit a013a02

File tree

5 files changed

+206
-50
lines changed

5 files changed

+206
-50
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## Version 1.2
4+
5+
Version: 1.2
6+
Author: monkey0506
7+
Date: 28 March 2009
8+
Description: Added `Stack.GetItemsArray`, `File.WriteStack`, `File.ReadStackBack`, and
9+
`Stack.LoadFromFile` functions. The module now exports `StackDataFormat` so it can be used by other
10+
scripts for extending the module. It is not imported, it must be locally imported to the script
11+
requiring it. Modified the way `Stack.Copy` formats the data to better prevent collisions. Fixed a
12+
bug with `Stack.Push` where if you were adding an item at a specific index `ItemCount` was still
13+
getting increased. Added data type `eStackDataInvalid` to indicate that the object is not valid
14+
`StackData`. Included module information in the Properties pane for the script.
15+
316
## Version 1.0
417

518
Version: 1.0

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ AGS v3.1.2+
2929

3030
Defines the current version of the module, formatted as a `float`.
3131

32+
#### Stack_VERSION_120
33+
34+
Defines version 1.2 of the module.
35+
3236
#### Stack_VERSION_100
3337

3438
Defines version 1.0 of the module.
@@ -45,6 +49,7 @@ Defines version 1.0 of the module.
4549
- `eStackDataGUI`: The stored data is a GUI
4650
- `eStackDataGUIControl`: The stored data is a GUIControl
4751
- `eStackDataStack`: The stored data is a Stack object
52+
- `eStackDataInvalid`: The object does not contain any valid StackData
4853

4954
#### StackPopType
5055

@@ -146,6 +151,18 @@ object can **only** be used with/by the following functions:
146151

147152
Returns a StackData object containing `theFloat`.
148153

154+
#### Stack.GetItemsArray
155+
156+
`StackData[] Stack.GetItemsArray()`
157+
158+
Returns an array containing each of the items in the stack. The size of the array will be the same
159+
as the [ItemCount](#stackitemcount). If `ItemCount` is 0, returns `null`.
160+
161+
*NOTE:* Since the stacks are all vectorized, it's not practical for this to be implemented as a
162+
property. Doing so would require a static size specified for the size of the property. This method
163+
allows you to get the items in a dynamic array without having to limit the number of items that can
164+
be returned this way.
165+
149166
#### Stack.GUIControlToData
150167

151168
`static StackData Stack.GUIControlToData(GUIControl *theControl)`
@@ -182,6 +199,14 @@ Returns whether the stack has **no** items in it.
182199

183200
Returns the number of items stored in the stack.
184201

202+
#### Stack.LoadFromFile
203+
204+
`void Stack.LoadFromFile(File *theFile)`
205+
206+
Attempts to read back a `Stack` object from `theFile`, and load it into this stack. If `theFile`
207+
was not written by [File.WriteStack](#filewritestack) this will crash the game, just as the normal
208+
`File` functions do.
209+
185210
#### Stack.LoadFromStack
186211

187212
`bool Stack.LoadFromStack(StackData otherStack)`
@@ -222,6 +247,25 @@ by [Stack.Copy](#stackcopy).
222247

223248
Returns a StackData object containing `theString`.
224249

250+
---------
251+
252+
### File
253+
254+
#### File.WriteStack
255+
256+
`bool File.WriteStack(StackData stackCopy)`
257+
258+
Writes the stack data from `stackCopy` to the file. If `stackCopy` does not contain a valid stack,
259+
or there is an error writing to the file, returns `false`.
260+
261+
#### File.ReadStackBack
262+
263+
`StackData File.ReadStackBack()`
264+
265+
Attempts to read back a `Stack` object from the file. If the file was not written by
266+
[File.WriteStack](#filewritestack) this will crash the game, just as the normal `File` functions
267+
do.
268+
225269
## Examples
226270

227271
This module is admittedly a bit intimidating, so here's a couple examples of how the scripts can be used.

Stack.asc

Lines changed: 76 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11

22
String StackDataDelimiter;
33
String StackDataFormat;
4+
export StackDataFormat; // allow extensions from other scripts
45
String StackDataCopyFormat;
5-
int StackDataCopyID = 0;
66

77
StackDataType GetType(this StackData*) {
8+
if (this.Length < (StackDataFormat.Length - 1)) return eStackDataInvalid;
89
StackData type = this.Substring(0, StackDataFormat.Length - 1);
9-
return type.Chars[type.IndexOf(":") + 1];
10+
int i = type.IndexOf(":");
11+
if (i == -1) return eStackDataInvalid;
12+
char c = type.Chars[i + 1];
13+
if (type != String.Format(StackDataFormat, c)) return eStackDataInvalid;
14+
return c;
1015
}
1116

1217
int GetAsInt(this StackData*) {
@@ -103,39 +108,32 @@ static StackData Stack::GUIControlToData(GUIControl *theControl) {
103108
return StackData.Format("%s%d", type, ((theControl.OwningGUI.ID * AGS_MAX_CONTROLS_PER_GUI) + theControl.ID));
104109
}
105110

106-
StackData StackDataMergeArray(StackData array[]) {
107-
if ((array == null) || (StackData.IsNullOrEmpty(array[0])) || (array[0].AsInt <= 0)) return null;
111+
StackData MergeArray(this Stack*, StackData array[]) {
112+
if (array == null) return null;
108113
StackData glue = StackDataDelimiter;
109114
StackData buffer = "";
110-
int i = 1;
111-
int size = array[0].AsInt;
112-
while (i <= size) {
115+
int i = 0;
116+
int size = this.ItemCount;
117+
while (i < size) {
113118
buffer = buffer.Append(array[i]);
114-
if (i < size) buffer = buffer.Append(glue);
119+
if (i < (size - 1)) buffer = buffer.Append(glue);
115120
i++;
116121
}
117122
return buffer;
118123
}
119124

120-
StackData[] SplitDataByItems(this Stack*) {
125+
StackData[] GetItemsArray(this Stack*) {
121126
if (this.Data == null) return null;
122-
StackData items[] = new StackData[this.ItemCount + 1];
123-
items[0] = StackData.Format("%d", this.ItemCount);
127+
StackData items[] = new StackData[this.ItemCount];
124128
StackData buffer = this.Data;
125129
String format = StackDataFormat.Substring(0, StackDataFormat.IndexOf(":") + 1);
126130
int i = buffer.IndexOf(format);
127-
int j = 1;
128-
while ((i != -1) && (j <= this.ItemCount)) {
131+
int j = 0;
132+
while ((i != -1) && (j < this.ItemCount)) {
129133
StackDataType type = buffer.Chars[format.Length];
130134
if (type == eStackDataStack) {
131135
StackData temp = buffer.Substring(StackDataFormat.Length - 1, buffer.Length);
132-
StackData stamp = temp.Substring(0, StackDataCopyFormat.IndexOf(":") + 1);
133-
i = stamp.Length;
134-
while ((temp.Chars[i] >= '0') && (temp.Chars[i] <= '9')) {
135-
stamp = stamp.AppendChar(temp.Chars[i]);
136-
i++;
137-
}
138-
stamp = stamp.Append(StackDataCopyFormat.Substring(StackDataCopyFormat.IndexOf(":%d") + 3, StackDataCopyFormat.Length));
136+
StackData stamp = temp.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
139137
temp = temp.Substring(stamp.Length, temp.Length);
140138
i = temp.IndexOf(stamp);
141139
if (i != -1) items[j] = buffer.Truncate(i + (StackDataFormat.Length - 1) + (stamp.Length * 2));
@@ -170,12 +168,14 @@ bool Stack::Push(StackData data, int index) {
170168
this.ItemCount++;
171169
return true;
172170
}
173-
StackData items[] = this.SplitDataByItems();
174-
int size = items[0].AsInt;
175-
if (index < size) items[index + 1] = data;
176-
this.Data = StackDataMergeArray(items);
177-
if (index >= size) this.Data = this.Data.Append(StackDataDelimiter.Append(data));
178-
this.ItemCount++;
171+
StackData items[] = this.GetItemsArray();
172+
int size = this.ItemCount;
173+
if (index < size) items[index] = data;
174+
this.Data = this.MergeArray(items);
175+
if (index >= size) {
176+
this.Data = this.Data.Append(StackDataDelimiter.Append(data));
177+
this.ItemCount++;
178+
}
179179
return true;
180180
}
181181

@@ -187,28 +187,26 @@ StackData Stack::Pop(bool remove, int index) {
187187
}
188188
if ((index < 0) || (index >= this.ItemCount) || (!this.ItemCount) ||
189189
(StackData.IsNullOrEmpty(this.Data))) return null;
190-
StackData items[] = this.SplitDataByItems();
191-
int size = items[0].AsInt;
192-
if (index >= size) return null;
193-
StackData data = items[index + 1];
190+
StackData items[] = this.GetItemsArray();
191+
int size = this.ItemCount;
192+
StackData data = items[index];
194193
if (remove) {
195194
this.ItemCount--;
196195
if ((!this.ItemCount) || (size == 1)) {
197196
this.Data = null;
198197
items = null; // prevent AGS 3.1.2 bug - Object not in managed pool.
199198
return data;
200199
}
201-
StackData buffer[] = new StackData[size];
202-
int i = 1;
203-
while (i < size) {
204-
if (i <= index) buffer[i] = items[i];
200+
StackData buffer[] = new StackData[this.ItemCount];
201+
int i = 0;
202+
while (i < this.ItemCount) {
203+
if (i < index) buffer[i] = items[i];
205204
else buffer[i] = items[i + 1];
206205
i++;
207206
}
208-
buffer[0] = StackData.Format("%d", size - 1);
209207
items = buffer;
210208
}
211-
this.Data = StackDataMergeArray(items);
209+
this.Data = this.MergeArray(items);
212210
items = null; // prevent AGS 3.1.2 bug - Object not in managed pool.
213211
return data;
214212
}
@@ -222,10 +220,30 @@ bool Stack::IsEmpty() {
222220
return (!this.ItemCount);
223221
}
224222

223+
StackData BuildKey(this Stack*) { // returns a 128-bit (16-byte) key for Stack::Copy
224+
StackData key = "";
225+
int i = 0;
226+
while (i < 16) {
227+
char c = 0;
228+
int j = 7;
229+
while (j >= 0) { // build-a-byte
230+
DateTime *now = DateTime.Now;
231+
bool bit = (Random(now.RawTime) % 2); // returns either 1 or 0
232+
c += (bit << j); // then we shift that bit into place
233+
j--;
234+
}
235+
if (c) {
236+
key = key.AppendChar(c);
237+
i++;
238+
}
239+
}
240+
return key;
241+
}
242+
225243
StackData Stack::Copy() {
226244
StackData type = StackData.Format(StackDataFormat, eStackDataStack);
227-
StackData stamp = StackData.Format(StackDataCopyFormat, StackDataCopyID);
228-
StackDataCopyID++;
245+
StackData key = this.BuildKey();
246+
StackData stamp = StackData.Format(StackDataCopyFormat, key);
229247
StackData data = this.Data;
230248
if (data == null) data = "";
231249
return StackData.Format("%s%s%d,%d,%s%s", type, stamp, this.ItemCount, this.PopType, data, stamp);
@@ -234,13 +252,7 @@ StackData Stack::Copy() {
234252
bool Stack::LoadFromStack(StackData otherStack) {
235253
if ((otherStack == null) || (otherStack.GetType() != eStackDataStack)) return false;
236254
StackData data = otherStack.Substring(StackDataFormat.Length - 1, otherStack.Length);
237-
StackData stamp = data.Substring(0, StackDataCopyFormat.IndexOf(":") + 1);
238-
int i = stamp.Length;
239-
while ((data.Chars[i] >= '0') && (data.Chars[i] <= '9')) {
240-
stamp = stamp.AppendChar(data.Chars[i]);
241-
i++;
242-
}
243-
stamp = stamp.Append(StackDataCopyFormat.Substring(StackDataCopyFormat.IndexOf(":%d") + 3, StackDataCopyFormat.Length));
255+
StackData stamp = data.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
244256
data = data.Substring(stamp.Length, data.Length);
245257
data = data.Truncate(data.IndexOf(stamp));
246258
StackData buffer = data.Substring(0, data.IndexOf(","));
@@ -252,8 +264,26 @@ bool Stack::LoadFromStack(StackData otherStack) {
252264
return true;
253265
}
254266

267+
bool WriteStack(this File*, StackData stackCopy) {
268+
if ((this.Error) || (stackCopy == null) || (stackCopy.GetType() != eStackDataStack)) return false;
269+
this.WriteString(stackCopy);
270+
return (!this.Error);
271+
}
272+
273+
StackData ReadStackBack(this File*) {
274+
if ((this.Error) || (this.EOF)) AbortGame("File::ReadStackBack: File was not written by File::WriteStack.");
275+
StackData data = this.ReadStringBack();
276+
if ((data == null) || (data.GetType() != eStackDataStack) || (this.Error)) AbortGame("File::ReadStackBack: File was not written by File::WriteStack.");
277+
return data;
278+
}
279+
280+
void Stack::LoadFromFile(File *theFile) {
281+
if ((theFile == null) || (theFile.Error) || (theFile.EOF)) AbortGame("Stack::LoadFromFile: File was not written by File::WriteStack.");
282+
this.LoadFromStack(theFile.ReadStackBack());
283+
}
284+
255285
function game_start() {
256286
StackDataDelimiter = "**STACKDATA**";
257287
StackDataFormat = "**STACKDATA:%c**";
258-
StackDataCopyFormat = "**STACKDATA STACK:%d**";
288+
StackDataCopyFormat = "**STACKDATA STACK:%s**";
259289
}

0 commit comments

Comments
 (0)