Author Topic: Errors in dedicated server save script  (Read 915 times)

A while ago I found a script to save the bricks from the console of a dedicated server, I liked it because this wouldn't mean I would lose bricks if I didn't see an area where was built in.
Now since I got this script I have already solved 2 bugs, one of them was events not being saved properly, events with an output text would get messed up and leave some numbers in place. Another had to do with ownership not being stored properly, so I made a second loop just to store ownership as I compared the savegame that was outputted by the script with the one I saved with my client.

Although the major ownership problems are now gone, I still sometimes have problems with ownership being messed up after loading a saved game.
Half of the built house would belong to the owner of the street and the other half would belong to the owner of the house. While the house is on a single baseplate.

Another problem is that event output is still not being solved properly. Although output texts don't change anymore, stuff like spawnexplosion->vehicle explosion will end up in spawnexplosion -> none after load.

And a third thing, which I'm not sure is really a saving issue are brick properties like collision, rendering and raycasting although there only are problems with these on JVS doors.

Could someone please review this script as I am not sure if it uses the right properties from the bricks.
And second, is there somewhere I can findout what properties an object has?

The brick saving script:
Code: [Select]
function dediSave(%name, %desc, %events, %ownership)
{
%path = "saves/" @ MissionInfo.saveName @ "/" @ %name @ ".bls";
if(!isWriteableFileName(%path))
{
error("Cannot save to file: ", %path);
return;
}
%file = new FileObject();
%file.openForWrite(%path);
%file.writeLine("This is a Blockland save file.  You probably shouldn't modify it cause you'll screw it up.");
%file.writeLine("1"); // What does this mean?
%file.writeLine(%desc);
for(%i=0;%i<64;%i++)
%file.writeLine(getColorIDTable(%i));
%bricks = 0;
for(%i=0;%i<mainBrickGroup.getCount();%i++)
%bricks += mainBrickGroup.getObject(%i).getCount();
%file.writeLine("Linecount " @ %bricks);

for(%i=0;%i<mainBrickGroup.getCount();%i++)
{
%group = mainBrickGroup.getObject(%i);
for(%a=0;%a<%group.getCount();%a++)
{
%brick = %group.getObject(%a);
if (%ownership && %brick.isBasePlate() && !$Server::LAN)
{

%print = (%brick.getDataBlock().subCategory $= "Prints") ? getPrintTexture(%brick.getPrintID()) : ""; // Possibly better way to check?
%file.writeLine(%brick.getDataBlock().uiName @ "\" " @ %brick.getPosition() SPC %brick.getAngleID() SPC %brick.isBasePlate() SPC %brick.getColorID() SPC %print SPC %brick.getColorFXID() SPC %brick.getShapeFXID() SPC %brick.isRayCasting() SPC %brick.isColliding() SPC %brick.isRendering());
if(%events)
{
if(%brick.getName() !$= "")
%file.writeLine("+-NTOBJECTNAME " @ %brick.getName());
if(%brick.numEvents > 0)
{
for(%b=0;%b<%brick.numEvents;%b++)
{
%params = "";

%targetClass = %brick.eventTargetIdx[%b] >= 0 ? getWord(getField($InputEvent_TargetListfxDTSBrick_[%brick.eventInputIdx[%b]], %brick.eventTargetIdx[%b]), 1) : "fxDtsBrick";
%paramList = $OutputEvent_parameterList[%targetClass, %brick.eventOutputIdx[%b]];
for(%c=0;%c<4;%c++)
{
if(firstWord(getField(%paramList, %c)) $= "dataBlock")
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1].uiName;
else
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1];
}
%file.writeLine("+-EVENT" TAB %b TAB %brick.eventEnabled[%b] TAB %brick.eventInput[%b] TAB %brick.eventDelay[%b] TAB %brick.eventTarget[%b] TAB %brick.eventNT[%b] TAB %brick.eventOutput[%b] @ %params);
}
}
}
if(isObject(%brick.emitter))
%file.writeLine("+-EMITTER " @ %brick.emitter.emitter.uiName @ "\" " @ %brick.emitterDirection);
if(%brick.getLightID() >= 0)
%file.writeLine("+-LIGHT " @ %brick.getLightID().getDataBlock().uiName @ "\" "); // Not sure if something else comes after the name
if(isObject(%brick.item))
%file.writeLine("+-ITEM " @ %brick.item.getDataBlock().uiName @ "\" " @ %brick.itemPosition SPC %brick.itemDirection SPC %brick.itemRespawnTime);
if(isObject(%brick.audioEmitter))
%file.writeLine("+-AUDIOEMITTER " @ %brick.audioEmitter.getProfileID().uiName @ "\" "); // Not sure if something else comes after the name
if(isObject(%brick.vehicleSpawnMarker))
%file.writeLine("+-VEHICLE " @ %brick.vehicleSpawnMarker.uiName @ "\" " @ %brick.reColorVehicle);

%file.writeLine("+-OWNER " @ getBrickGroupFromObject(%brick).bl_id);
}
}
}

for(%i=0;%i<mainBrickGroup.getCount();%i++)
{
%group = mainBrickGroup.getObject(%i);
for(%a=0;%a<%group.getCount();%a++)
{
%brick = %group.getObject(%a);
if (%ownership && %brick.isBasePlate() && !$Server::LAN)
{
continue;
}
%print = (%brick.getDataBlock().subCategory $= "Prints") ? getPrintTexture(%brick.getPrintID()) : ""; // Possibly better way to check?
%file.writeLine(%brick.getDataBlock().uiName @ "\" " @ %brick.getPosition() SPC %brick.getAngleID() SPC %brick.isBasePlate() SPC %brick.getColorID() SPC %print SPC %brick.getColorFXID() SPC %brick.getShapeFXID() SPC %brick.isRayCasting() SPC %brick.isColliding() SPC %brick.isRendering());
if(%events)
{
if(%brick.getName() !$= "")
%file.writeLine("+-NTOBJECTNAME " @ %brick.getName());
if(%brick.numEvents > 0)
{
for(%b=0;%b<%brick.numEvents;%b++)
{
%params = "";

%targetClass = %brick.eventTargetIdx[%b] >= 0 ? getWord(getField($InputEvent_TargetListfxDTSBrick_[%brick.eventInputIdx[%b]], %brick.eventTargetIdx[%b]), 1) : "fxDtsBrick";
%paramList = $OutputEvent_parameterList[%targetClass, %brick.eventOutputIdx[%b]];
for(%c=0;%c<4;%c++)
{
if(firstWord(getField(%paramList, %c)) $= "dataBlock")
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1].uiName;
else
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1];
}
%file.writeLine("+-EVENT" TAB %b TAB %brick.eventEnabled[%b] TAB %brick.eventInput[%b] TAB %brick.eventDelay[%b] TAB %brick.eventTarget[%b] TAB %brick.eventNT[%b] TAB %brick.eventOutput[%b] @ %params);
}
}
}
if(isObject(%brick.emitter))
%file.writeLine("+-EMITTER " @ %brick.emitter.emitter.uiName @ "\" " @ %brick.emitterDirection);
if(%brick.getLightID() >= 0)
%file.writeLine("+-LIGHT " @ %brick.getLightID().getDataBlock().uiName @ "\" "); // Not sure if something else comes after the name
if(isObject(%brick.item))
%file.writeLine("+-ITEM " @ %brick.item.getDataBlock().uiName @ "\" " @ %brick.itemPosition SPC %brick.itemDirection SPC %brick.itemRespawnTime);
if(isObject(%brick.audioEmitter))
%file.writeLine("+-AUDIOEMITTER " @ %brick.audioEmitter.getProfileID().uiName @ "\" "); // Not sure if something else comes after the name
if(isObject(%brick.vehicleSpawnMarker))
%file.writeLine("+-VEHICLE " @ %brick.vehicleSpawnMarker.uiName @ "\" " @ %brick.reColorVehicle);
}
}
%file.close();
%file.delete();

echo("Saved: " @ %path);
}

<edit> I like to add, that saving with the client does solve the owner problem. But the client won't save everything that has been built. Everything outside of its viewed range will not have been saved.

<edit2> I have found the next by comparing a client savegame to the dedicated save game.
Client:
Code: [Select]
+-EVENT 0 1 onPlayerTouch 0 -1 _Ultra_Turrent spawnProjectile 200 0 0 -1 0 0 0 2

dediSave: Note that the -1 in the output parameters are gone.
Code: [Select]
+-EVENT 0 1 onPlayerTouch 0 -1 _Ultra_Turrent spawnProjectile 200 0 0 0 0 0 2
This code seems to generate those parameters:

Code: [Select]
%params = "";

%targetClass = %brick.eventTargetIdx[%b] >= 0 ? getWord(getField($InputEvent_TargetListfxDTSBrick_[%brick.eventInputIdx[%b]], %brick.eventTargetIdx[%b]), 1) : "fxDtsBrick";

%paramList = $OutputEvent_parameterList[%targetClass, %brick.eventOutputIdx[%b]];
for(%c=0;%c<4;%c++)
{
if(firstWord(getField(%paramList, %c)) $= "dataBlock")
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1].uiName;
else
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1];
}

« Last Edit: December 13, 2008, 10:54:22 AM by NukeBuster »

Download the latest version.
http://returntoblockland.com/forums/download.php?cmd=viewFile&id=376

[Edit] Although I don't remember fixing this:
And a third thing, which I'm not sure is really a saving issue are brick properties like collision, rendering and raycasting although there only are problems with these on JVS doors.
Can you explain what doesn't work?
« Last Edit: December 13, 2008, 12:09:53 PM by Randy »

The doors lose their properties somehow. You can walk through them, they don't open at all or they don't even show at all.


By the way. I have found the event problem, and i saw that was still in your new version.

look at what I updated.
Current code I have:
Code: [Select]
%params = "";

%targetClass = %brick.eventTargetIdx[%b] >= 0 ? getWord(getField($InputEvent_TargetListfxDTSBrick_[%brick.eventInputIdx[%b]], %brick.eventTargetIdx[%b]), 1) : "fxDtsBrick";
%paramList = $OutputEvent_parameterList[%targetClass, %brick.eventOutputIdx[%b]];

for(%c=0;%c<4;%c++)
{
if(firstWord(getField(%paramList, %c)) $= "dataBlock")
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1].uiName;
else
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1];

}
%file.writeLine("+-EVENT" TAB %b TAB %brick.eventEnabled[%b] TAB %brick.eventInput[%b] TAB %brick.eventDelay[%b] TAB %brick.eventTarget[%b] TAB %brick.eventNT[%b] TAB %brick.eventOutput[%b] @ %params);

Current code you have:
Code: [Select]
%targetClass = %brick.eventTargetIdx[%b] >= 0 ? getWord(getField($InputEvent_TargetListfxDTSBrick_[%brick.eventInputIdx[%b]], %brick.eventTargetIdx[%b]), 1) : "fxDtsBrick";
%paramList = $OutputEvent_parameterList[%targetClass, %brick.eventOutputIdx[%b]];
%params = "";
for(%c=0;%c<4;%c++)
{
if(firstWord(getField(%paramList, %c)) $= "dataBlock" && %brick.eventOutputParameter[%b, %c + 1] >= 0)
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1].uiName;
else
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1];
}
%file.writeLine("+-EVENT" TAB %b TAB %brick.eventEnabled[%b] TAB %brick.eventInput[%b] TAB %brick.eventDelay[%b] TAB %brick.eventTarget[%b] TAB %brick.eventNT[%b] TAB %brick.eventOutput[%b] @ %params);

Fix:
Code: [Select]
if(firstWord(getField(%paramList, %c)) $= "dataBlock")
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1].getName();
else
%params = %params TAB %brick.eventOutputParameter[%b, %c + 1];

Note the getName().

For the ownership, I already put the bricks with ownership first but still get messed up. I'll try that with your script.
« Last Edit: December 13, 2008, 01:16:16 PM by NukeBuster »

somecrap

The code by Randy worked fine, you added some dumbass () after uiName. Furthermore things should only be saved using their uiname not their datablock name.

The code by Randy worked fine, you added some dumbass () after uiName. Furthermore things should only be saved using their uiname not their datablock name.

That was a small copy-paste to forum error, it has never been used as uiName(). Only as uiName.
As the only thing I've changed was %brick.eventOutputParameter[%b, %c + 1].getName(); instead of %brick.eventOutputParameter[%b, %c + 1].uiName;
You could have seen this in my original post.



I have confirmed that the event output bug is still in Randy's script, it prints "Akimbo Gun Bullet" where it should print "akimboGunProjectile".

I have compared client save vs dedisave to get this data.

dedisave:
Code: [Select]
+-EVENT 0 1 onActivate 0 Self spawnProjectile 0 0 0 Akimbo Gun Bullet 0 0 0 1
clientsave:
Code: [Select]
+-EVENT 0 1 onActivate 0 Self spawnProjectile 0 0 0 akimboGunProjectile 0 0 0 1
I am however still conducting an ownership test.

<edit> The ownership problem I was having doesn't appear to be in your code.
So now I'm very happy. :D Look into the output params though.

Nuke
« Last Edit: December 13, 2008, 01:28:15 PM by NukeBuster »

That was a small copy-paste to forum error, it has never been used as uiName(). Only as uiName.

Owch, A weird copy-paste error that adds () in random places!

copy paste as in i'll edit the other to match what I have ;)

The ownership issues seemed to have been solved, but today I spawned in someones house again. So it might not be completely correct. However, I'm not able to find any significant differences in save files concerning ownership between client and server save files except for the order in which ownership is stored.

When I save the game with the client and load that savegame, ownership seems to be ok again.
« Last Edit: December 15, 2008, 10:25:39 AM by NukeBuster »

Owch, A weird copy-paste error that adds () in random places!
Quick, Inform bill gates!

I know what causes the problem, only not yet how to solve it.


On loading all the baseplates get placed, after a while bricks start to from where houses are to be put together. Now bricks in the air get placed much earlier on some buildings then the bricks on the baseplate. While the baseplate detirmines the owner of the bricks as far as I can tell.

When I saw this, I noticed some other builds that had bricks pop up before there was a connection with the baseplate I went to these bricks and found out I am the owner of those bricks while not of the complete build.

Maybe the saving needs to be done lowest tile (of a group) first. so it'll build from the ground up.
Nuke
« Last Edit: December 15, 2008, 04:41:04 PM by NukeBuster »