Let's all try to read thoroughly before replying peeps;
includes reading my message thoroughly before replying. Hmm.. they should add a read thoroughly button to this post toolbar,.. that would be cool anyway...
I am guessing this information might be useful.
Please don't bother with Dark-Data; it is too slow for what you want; please don't tell me it is faster than arrays without showing me an example; I've got a test on my hard drive showing that it is not worth using Dark-Data for anything whatsoever.
I'd rather you use text lists or XML plugins than Dark Data. Even still, XML plugin use is faster than text lists, and the following is faster than either.
DIY Terrains
Firstly; judging by the messages I get the impression you are not using the Matrix1 utility make plane command; which offers multiple grid parameters for you to create your own terrain mesh. Forgive me if I am wrong and you are in-fact using it. You can manipulate the vertices on it using vertex data commands.
Arrays in arrays
Array to memblock to array
This is a grey area; now, what I was doing not so long ago was storing arrays in arrays using banks (Matrix1 version of memblocks which have unlimited instances), but you can simply use the Make Memblock From Array and forget the banks if you feel 255 memblocks is enough.
What takes place is an array is converted into a memblock, which is then stored in an array. The conversion from array to memblock is minimal, about 1% of one millisecond or so. Frankly, if you look at the memblock of a basic array, it is literally a series of 4 byte integers, or 2 byte words or what ever the datatype is.
Here is some of the source code; you seem knowledgeable so it might make sense:
`Binary Modular Runtimes
`bMA_DataValues.dba
`======================
//==================================================
Function AddValue(v#,iDataBlock)
i = DataBlocks(iDataBlock).ValueCount + 1
Inc DataBlocks(iDataBlock).ValueCount
Values#( i ) = v#
Endfunction i
//==================================================
Function AddValueData(sName$, value#, iRef)
_New DataBlocks()
d = __n (DataBlocks())
DataBlocks(d).Name$ = sName$
DataBlocks(d).Value# = value#
DataBlocks(d).Ref = iRef
Endfunction d
//==================================================
Function Value#(iDataBlockID)
f# = DataBlocks(iDataBlockID).Value#
Endfunction f#
//==================================================
Function Value$(iDataBlockID, iDecimals)
s$ = Str$( DataBlocks(iDataBlockID).Value#, iDecimals )
Endfunction s$
//==================================================
Function ShowValueArrayMsg( iDataBlock, sPrefix$, sIndexSuffix$, sSuffix$ )
sp$ = DataBlocks(iDataBlock).ElementPrefix$
ss$ = DataBlocks(iDataBlock).ElementSuffix$
si$ = DataBlocks(iDataBlock).IndexSuffix$
DataMsg$( CurrentDataMsg ) = ""
DataBlocks(iDataBlock).ElementPrefix$ = Def$(sPrefix$, sp$)
DataBlocks(iDataBlock).ElementSuffix$ = Def$(sSuffix$, ss$)
DataBlocks(iDataBlock).IndexSuffix$ = Def$(sIndexSuffix$, si$ )
ForEachValueIn( iDataBlock, Get Ptr To Function("ValueMsg") )
Msg( DataMsg$( CurrentDataMsg ) , "" )
DataBlocks(iDataBlock).ElementPrefix$ = sp$
DataBlocks(iDataBlock).ElementSuffix$ = ss$
DataBlocks(iDataBlock).IndexSuffix$ = si$
Endfunction
//==================================================
Function ValueMsg( i, iIndex, iCount, iDataBlock )
If DataBlocks(iDataBlock).ShowElementIndex
S$ = DataBlocks(iDataBlock).ElementPrefix$ + Str$( iIndex ) + DataBlocks(iDataBlock).IndexSuffix$
s$ = s$ + Str$(i) + DataBlocks(iDataBlock).ElementSuffix$
Else
S$ = DataBlocks(iDataBlock).ElementPrefix$
s$ = s$ + Str$(i) + DataBlocks(iDataBlock).ElementSuffix$
Endif
DataMsg$( CurrentDataMsg ) = s$
EndFunction 1
//==================================================
Function AddValueArray(sName$, iRef)
d = NewValueArray(sName$, 1, iRef)
Endfunction d
//==================================================
Function NewValueArray(sName$, iSize, iRef)
iSize = Max(iSize,0)
d = UseFreeData()
DataBlocks(d).Name$ = sName$
DataBlocks(d).Flags = Bit Set Mask( Bit Set( 0, F_VALUE_ARRAY ), F_ARRAY )
DataBlocks(d).Size = iSize
Make Memblock From Array 1, Values#()
b = NewBank()
Make Bank From Memblock b, 1
Delete Memblock 1
If Bank Exist( DataBlocks(d).ValueBank )
Delete Bank DataBlocks(d).ValueBank
Endif
DataBlocks(d).ValueBank = b
Endfunction d
//==================================================
Function AddValues#(iDataBlock, iOptionalDefaultValuePtr, iCount)
If Bit Intersect Mask( DataBlocks(iDataBlock).Flags, F_ARRAY )
If DataBlocks(iDataBlock).ValueBank > 0
Make Memblock From Bank 2, DataBlocks(iDataBlock).ValueBank
Make Array From Memblock Values#(), 2
Delete Memblock 2
n = DataBlocks(iDataBlock).ValueCount
s = n + 1
e = s + iCount - 1
QLg("--")
QLg("Value of numbers in existing array " + Str$(n))
//------------------------
For i = s to e
Inc DataBlocks(iDataBlock).ValueCount
If iOptionalDefaultValuePtr > 0
Values#() = Call Function Ptr( iOptionalDefaultValuePtr, i, e, iDataBlock )
Else
Values#() = DefValue#
Endif
QLg("Add number at index " + Str$(i) + " with a value of " + Str$(Values#()) )
Next i
//------------------------
DataBlocks(d).Size = e
Make Memblock From Array 1, Values#()
Delete Bank DataBlocks(iDataBlock).ValueBank
Make Bank From Memblock DataBlocks(iDataBlock).ValueBank, 1
Delete Memblock 1
BLg("Bank size: " + Str$( Get Bank Size( DataBlocks(iDataBlock).ValueBank )))
Else
Throw("Could not add data using iteration in datablock " + DataBlocks(iDataBlock).Name$ + Lf$() + Lf$() + "The datablock contains no array memory bank", 1 )
Endif
Else
Throw("Could not add data using iteration in datablock " + DataBlocks(iDataBlock).Name$ + Lf$() + Lf$() + "The datablock contains no array", 1 )
Endif
Endfunction
//==================================================
Function EditValues(iDataBlock, iPtr, iLoops, iPreEditPtr, iPostEditPtr)
If Bit Intersect Mask( DataBlocks(iDataBlock).Flags, F_ARRAY )
If DataBlocks(iDataBlock).ValueBank > 0
Make Memblock From Bank 2, DataBlocks(iDataBlock).ValueBank
Make Array From Memblock Values#(), 2
Delete Memblock 2
n = DataBlocks(iDataBlock).ValueCount
Local iEditedCount = 0
For l = 1 to iLoops
` Pre edit
If Function Ptr Is Valid( iPreEditPtr )
If Call Function Ptr( iPreEditPtr, l, n, iDataBlock ) = 0 Then Exit
Endif
` Edit
For i = 1 to n
fOld# = Values#(i)
fNew# = Call Function Ptr( iPtr, i, Values#(i), l, iCount, iDataBlock )
Values#(i) = fNew#
If fOld# <> fNew# Then Inc iEditedCount
Next i
` Post edit
If Function Ptr Is Valid( iPostEditPtr )
If Call Function Ptr( iPostEditPtr, l, n, iDataBlock ) = 0 Then Exit
Endif
Next l
Make Memblock From Array 1, Values#()
Delete Bank DataBlocks(iDataBlock).ValueBank
Make Bank From Memblock DataBlocks(iDataBlock).ValueBank, 1
Delete Memblock 1
Else
Throw("Could not edit data using iteration in datablock " + DataBlocks(iDataBlock).Name$ + Lf$() + Lf$() + "The datablock contains no array memory bank", 1 )
Endif
Else
Throw("Could not edit data using iteration in datablock " + DataBlocks(iDataBlock).Name$ + Lf$() + Lf$() + "The datablock contains no array", 1 )
Endif
Endfunction iEditedCount
//==================================================
Function WriteValues(d)
If DataBlockExist(d)
If Bank Exist( DataBlocks(d).ValueBank ) = 0
If DataBlocks(d).ValueBank = 0 Then DataBlocks(d).ValueBank = NewBank()
Else
Delete Bank DataBlocks(d).ValueBank
Endif
Make Memblock From Array 1, Values#()
Make Bank From Memblock DataBlocks(d).ValueBank, 1
Delete Memblock 1
Else
Throw("Could not write Values to datablock. Datablock " + Str$(d) + " does not exist", 1 )
Endif
Endfunction
//==================================================
Function ReadValues(d)
If DataBlockExist(d)
If Bank Exist( DataBlocks(d).ValueBank ) = 0
DataBlocks(d).ValueBank = NewBank()
Clear Array Values#()
Else
Make Memblock From Bank 2, DataBlocks(d).ValueBank
Make Array From Memblock Values#(), 2
Delete Memblock 2
Endif
Else
Throw("Could not read Values from datablock. Datablock " + Str$(d) + " does not exist", 1 )
Endif
Endfunction
//==================================================
Function ValueCount(iDataBlock)
c = DataBlocks(iDataBlock).ValueCount
Endfunction c
//==================================================
Function ValueCount$(iDataBlock)
s$ = Str$( ValueCount(iDataBlock))
Endfunction s$
This snippet WAS my method for storing arrays, in arrays, in arrays and so on. Focus on the ReadValues and WriteValues commands. Ignore the Lg/Throw commands and the other functions.
I have one problem with this method; and I do understand that using banks are not necessary, and may be the cause of the problem; storing strings does not work here, and I get the feeling the values are inconsistent; something is going on. The strings you put in are not the same you get out. I do not trust it; but again it could be the banks.
So what I am saying is, this should work, but seems to not be so, I'm not currently using it in my game; it could be problem with the banks; I haven't got round to investigating it.
Relationships
This is the method I am now using, and was have been for the past 5 years; it is commonly used in the DBP community. I also use variables and PTRs to store special indexes.
There is only one array for each data type. The relationships are indexes stored in each entry.
Here are the link variables in a parent class; First and Last. The first is the first index of the first element added to the parent; and the last is the previously added element.
Each element has a link to the previous, next and first element; this is optional.
Here is an example of looping elements of the same type:
NextChild = Ent(1).First
While NextChild
` DoActions
NextChild = Ent(NextChild).Next
EndWhile
Here is an example of looping elements of a different type:
NextAI = Ent(1).FirstAI
While NextAI
` DoActions
NextAI = AI(NextAI).Next
EndWhile
This method continues to loop until the next element is zero.
Pointers
This method uses a Matrix1 function name or pointer; functions called by a string or numeric representation. The function handles to extraction and insertion of elements.
Here is an abstract example
Dim Entity(1000) as EntityType
Root = 0
Base = Get Ptr To Function "BaseEntity"
Door = Get Ptr To Function "DoorEntity"
DoorHandle = Get Ptr To Function "DoorHandleEntity"
Map = Add( Base, Root, 0 )` Add the map to the root entity
NewDoor = Add( Door, BaseEntity, 0 ) ` Add a door to the map entity
NewHandle = Add( DoorHandle, Door , NewDoor ) ` Add a handle to the door entity
` Call custom add functions or add default
Function Add( iEntityClassPTR, iParentClassPTR, iParentID )
iOperationAdd = 1
If iEntityClassPTR
id = Call Function Ptr( iParentClassPTR, iOperationAdd, iEntityClassPTR, iParentID )
Else
Array Insert At Bottom Entity()
id = Array Count (Entity())
EndIf
EndFunction id
Function DoorEntity( iOperation, iClass, ID )
Select iOperation
Case 1 `Insert constant here
Array Insert At Bottom Entity()
result = Array Count( Entity() )
Entity().Class = iClass
Entity(ID).Last = result
Entity(result).Parent = ID
` And so on
EndCase
EndFunction
` And so on
This example is one step up in complication from the previous one, in that the operations are customizable and are organized by a generic function. Low level programming of such operations simulates an extensible library of functions and arrays.
This one is advanced, but allows you to create more unique relationships. The members of a class are defined in functions as-well as fields.
Blitz Terrain
Excellent plugin; you need to play around with it to get the most out of it; it has its own rendering pipeline which you need to work with. It might be worth using it as the visual representation of your grid.
I hear about what you are saying with re-invention of the wheel, but maybe it would be a cool option to spend your time adding to what's already there. If you feel like making your own terrain system because you think you will be better of without Blitz Terrain, by all means.
What I always say is forget the name of tools; ignore their names; focus on what they can do. Blitz Terrain is actually good at creating things like water and paving.