Game Development Community

Interesting...RTSUnits with no datablocks!

by Stephen Zepp · in RTS Starter Kit · 11/15/2004 (9:54 pm) · 16 replies

(this is not a criticism, it's laughing at myself, and asking if anyone has any ideas!)

I have absolutely no clue how I pulled it off, but in our client-server environment, we've got our units populating nicely server side on a login, and the client can manipulate them at will---but, they have no datablocks client side!

I noticed this when I downloaded the new portraits and plugged 'em in, but wasn't getting the groups I expected--everything was one image, and it was the first one. I started poking around in the SelectionDisplay (very nice script btw, once I figured it out!), stepped through the sorting and indexing of the portraits, and determined that when I had a single unit selected, and issued:

(%this is the PlayGui)
%this.getSelectedObject(0).getDataBlock().getName();, it returned an empty string!

%this.getSelectedObject(0).dump(); returns:

Dumping %this.getSelectedObject
Member Fields:
position = "-35 -45 93.0625"
rotation = "1 0 0 0"
scale = "1 1 1"
Tagged Fields:
...

Now, as far as I am aware, the datablocks should have been ghosted to the client when the object was created server side, but I'm still giggling about my ghosted objects--they are so ghostly they have no data at all ;)

So the big question is...how can a ghosted object make it across the connection without a datablock, and without crashing?

More to come as I debug!

#1
11/16/2004 (4:30 am)
After dreaming about spectral dataBlocks, floating about unattached to any body, walking through walls and such, laughing at me in creepy, chilling voices, I am beginning to think that the dataBlocks did actually get passed, but somehow got placed in the wrong namespace. They exist and are attached on the server, and at least appear to be sent properly (working on monitoring code to prove that), but they simply aren't attached to the client side ghosted RTSUnits.

1) Is it possible/probable that dataBlocks can be sent across to the client, but put in a different namespace than when the units themselves are ghosted?

2) Is namespace assignment when ghosted objects are created somehow linked to when/where in the missionDownload sequence they happen?

3) Is there a way to dump to console the entire namespace of ConObjects?
#2
11/16/2004 (10:53 am)
Quick bump to see if anyone has any of the answers to the above questions, and even better, may have run into something like this in the past (objects with no datablocks).

I've actually gotten 1) and 3) figured out. 1) Yes, it can be done, how/why I have no idea! 3) the console tree(); command. I had forgotten all about that.

Using tree(); I've found that the dataBlocks themselves actually are in the accessable namespace---well, let me correct that: the -data- within the blocks are showing up in tree(); as RTSUnitData. However, even a manual attempt in the console to link an object with one of the 3 base RTSUnitData blocks won't work:

1259.setDataBlock("botBlock"); ==> botBlock not found!

As I mentioned, I can actually visually see the RTSUnitData object (that one for example had an ID of 30), but they are not linked to the namespace somehow, and definitely not linked to the RTSUnit objects. For all instances, RTSUnit.getDataBlock().getName(); returns an empty string.

EDIT: Would anyone that has happened to have put together some Con::printf statements used for debugging during the ghosting/missionDownload phase happen to have them handy? Been tearing my hair out trying to figure out the best way to produce some user handy debugging messages.
#3
11/16/2004 (1:55 pm)
Well, I'm stuck! Been beating my head against this for 3 days now, and simply cannot figure out why my dataBlocks are loading server side, but are not available with %player = new RTSUnit()
{
dataBlock = %data;
}

I'm almost positive that in the transition from start pack to integrated, I have a script that has a hidden dependency of some sort--either positional, or related to namespace somehow.

I apologize ahead of time for the spam, but if anyone experienced with the way the files should be loaded can take a look, I would be a happy camper!

(server console log starts next message. NOTE: You don't see the client side, but for this issue it's not a factor).

EDIT: As the console shows, the latest version exposed what looks like the real error: the datablocks are NOT being assigned server side either. In many cases, I was able to get the units to appear anyway without datablocks, and be manipulated, still without datablocks.
#4
11/16/2004 (1:57 pm)
Server Console Log: Edited for content, to fit the width of your screen, and for time allotted:

% [szepp@this nemesis-server]$ ./nemesisd_DEBUG.bin -dedicated -nohomedir -mission game/data/missions/frenzy.mis 
Sleep latency: 19ms
% 
--------- Initializing Common Module ---------
% 
--------- Initializing Nemesis Server ---------
Loading compiled script game/server/init.cs.
Loading compiled script game/data/init.cs.
Loading compiled script game/data/terrains/grassland/propertyMap.cs.
% 
--------- Initializing Nemesis Vortex Server ---------
Loading compiled script common/server/audio.cs.
Loading compiled script common/server/server.cs.
Loading compiled script common/server/message.cs.
Loading compiled script common/server/commands.cs.
Loading compiled script common/server/missionInfo.cs.
Loading compiled script common/server/missionLoad.cs.
Loading compiled script common/server/missionDownload.cs.
Loading compiled script common/server/clientConnection.cs.
Loading compiled script common/server/kickban.cs.
Loading compiled script common/server/game.cs.
Loading compiled script game/server/scripts/audio/audioProfiles.cs.
Loading compiled script game/server/scripts/audio/player.cs.
[b]Loading compiled script game/server/scripts/fx/player.cs.
Loading compiled script game/server/scripts/units/base.cs.
Loading compiled script game/data/players/player/player.cs.[/b]
Validation required for shape: game/data/players/player/player.dts
Loading compiled script game/server/scripts/units/player.cs.
Loading compiled script game/data/players/orc/player.cs.
Loading compiled script game/data/players/elf-sylvan/player.cs.
Loading ElfSylvanDts datablock
Loading compiled script game/data/players/lich/player.cs.
Loading compiled script game/data/players/elf-high/player.cs.
Loading compiled script game/server/scripts/players/orc.cs.
Validation required for shape: game/data/players/orc/player.dts
Loading compiled script game/server/scripts/players/elf-sylvan.cs.
LOading ElfSylvanBody Playerdata
Validation required for shape: game/data/players/elf-sylvan/player.dts
Loading compiled script game/server/scripts/players/lich.cs.
Loading Lich Playerdata
Validation required for shape: game/data/players/lich/player.dts
Loading compiled script game/server/scripts/players/elf-high.cs.
LOading ElfhighBody Playerdata
Validation required for shape: game/data/players/elf-high/player.dts
[b]Loading compiled script game/server/scripts/units/bot.cs.
Validation required for shape: game/data/units/bot/bot.dts
Warning: (game/player.cc @ 290) PlayerData::preload - Unable to find named animation sequence 'back'!
...
Loading compiled script game/server/scripts/units/rifleman.cs.
Validation required for shape: game/data/units/rifleman/rifleman.dts
Warning: (game/player.cc @ 290) PlayerData::preload - Unable to find named animation sequence 'back'!
...
Loading compiled script game/server/scripts/units/shocker.cs.
Validation required for shape: game/data/units/shocker/shocker.dts
Warning: (game/player.cc @ 290) PlayerData::preload - Unable to find named animation sequence 'back'!
...
Loading compiled script game/server/scripts/items/building.cs.
Validation required for shape: game/data/shapes/building-sets/rts-demo/building.dts
Warning: (game/player.cc @ 290) PlayerData::preload - Unable to find named animation sequence 'root'!
...
[/b]
(cont)
#5
11/16/2004 (1:58 pm)
Loading compiled script game/server/scripts/core/centerPrint.cs.
Loading compiled script game/server/scripts/core/commands.cs.
Loading compiled script game/server/scripts/core/item.cs.
Loading compiled script game/server/scripts/core/radiusDamage.cs.
Loading compiled script game/server/scripts/core/shapeBase.cs.
Loading compiled script game/server/scripts/core/teams.cs.
Loading compiled script game/server/scripts/core/triggers.cs.
Loading compiled script game/server/scripts/core/weapon.cs.
Loading compiled script game/server/scripts/core/stats.cs.
Loading compiled script game/server/scripts/core/buffs.cs.
Loading compiled script game/server/scripts/globals.cs.
Loading compiled script game/server/scripts/items/camera.cs.
Loading compiled script game/server/scripts/items/crossbow.cs.
ParticleEmitterData(CrossbowBoltEmitter) velocityVariance > ejectionVelocity
Error: shape game/data/shapes/weapons/rtscrossbow/ammo.dts-collision detail 0 (Collision-3) bounds box invalid!
Loading compiled script game/server/scripts/items/staticShape.cs.
Loading compiled script game/server/scripts/core/game.cs.
Loading compiled script game/server/scripts/port-overrides.cs.
Loading compiled script game/server/scripts/core/gameConnection.cs.
% 
--------- Starting Dedicated Server ---------
Exporting server prefs...
Starting multiplayer mode
Binding server port to default IP
UDP initialized on port 28010
Unable to initialize IPX - error 5
Loading compiled script game/server/scripts/core/db.cs.
Database connection established.
Loading compiled script game/server/scripts/core/accountServer.cs.
Loading compiled script game/server/scripts/units/pathManager.cs.
Loading compiled script game/server/scripts/markers.cs.
Loading compiled script game/server/scripts/inventory.cs.
Loading compiled script game/server/scripts/health.cs.
Loading compiled script game/server/scripts/chimneyfire.cs.
Binding server port to default IP
--- Listening for new account info on port 20006
*** LOADING MISSION: game/data/missions/frenzy.mis
*** Stage 1 load
*** Stage 2 load
Executing game/data/missions/frenzy.mis.

*** Mission loaded
Engine initialized...
% 
[b]Note: The following block is for our account server, it's spammy but working as intended[/b]
AccountServer::onConnectRequest--%this is 1044
New Client: 1059
Account: 1060
Client connection from IP:69.139.199.88:2858 Socket id: 12
AccountServer::onConnectRequest--created new soul 1061

Valid Nemesis Client..
AccountServer::ParseCommand: Raw %line:>:LGN:Zenithar1:3B531F69A6FA15D254EAD68DA0BC6BF7:45<
Command = 'LGN' Argument = Zenithar1:3B531F69A6FA15D254EAD68DA0BC6BF7:45
Login
Pulled Soul from %ActiveSouls, got 1061

%client.PlayerName = Zenithar1

NumRows = 1
ColName UserID MaxColSize = 2
ColName UserLoginName MaxColSize = 10
ColName UserPassword MaxColSize = 33
ColName UserStatus MaxColSize = 2
ColName UserAuthorityLevel MaxColSize = 2
%result.UserPassword >3B531F69A6FA15D254EAD68DA0BC6BF7
%client.Password >3B531F69A6FA15D254EAD68DA0BC6BF7<
User Zenithar1 validated.
Client Told us Entity is 45
Got Connect challenge Request from IP:69.139.199.88:2857
Got Connect Request
Connect Params:
1: 1063
2: Zenithar1
3: 
4: 1060

Client sent us a client id of1060
[b]End of account server report[/b]
CADD: 1063 IP:69.139.199.88:2857
*** Sending mission load to client: game/data/missions/frenzy.mis
Mapping string: MissionStartPhase1Ack to index: 0
Mapping string: MissionStartPhase2Ack to index: 1
Ghost Always objects received.
Mapping string: MissionStartPhase3Ack to index: 2
(cont)
#6
11/16/2004 (1:59 pm)
[b]Server--RTSConnection::onClientEnterGame, %this is 1063 [/b]

Object 'riflemanBlock' is not a member of the 'GameBaseData' data block class
game/server/scripts/core/gameConnection.cs (107): Register object failed for object (null) of class RTSUnit.
game/server/scripts/core/gameConnection.cs (109): Unable to find object: '0' attempting to call function 'getDataBlock'
game/server/scripts/core/gameConnection.cs (109): Unable to find object: '' attempting to call function 'getName'
RTSConnection::createPlayer--Created new %player 0 for Connection 1063 dataBlock = 
Set::add: Object "0" doesn't exist
game/server/scripts/core/gameConnection.cs (113): Unable to find object: '0' attempting to call function 'setControllingConnection'
game/server/scripts/core/gameConnection.cs (114): Unable to find object: '0' attempting to call function 'setSkinName'
game/server/scripts/core/gameConnection.cs (115): Unable to find object: '0' attempting to call function 'setTeam'
game/server/scripts/core/gameConnection.cs (116): Unable to find object: '0' attempting to call function 'setTransform'
Set::add: Object "0" doesn't exist

Object 'RTSObserver' is not a member of the 'GameBaseData' data block class
game/server/scripts/core/gameConnection.cs (54): Register object failed for object (null) of class RTSCamera.
Set::add: Object "0" doesn't exist
game/server/scripts/core/gameConnection.cs (58): Unable to find object: '0' attempting to call function 'scopeToClient'
Error reading from socket: Connection reset by peer
Client 0, IP:69.139.199.88:2858 disconnected. (1060)
%
#7
11/16/2004 (3:07 pm)
Hey Stephen,

Quick answers before I analyze the full content of this thread:

1. There is no namespacing in script. Client side datablocks don't typically get names sent over, so you should be working solely with IDs client side (the nice thing about datablocks is that they have the same ID client and server).

2. No namespacing in script.

3. tree() will show you the full object hierarchy in Torque. This is just representative of what objects contain what other objects, and has no implications for namespace.

So if you're on the server, you can't access the datablocks by name?
#8
11/16/2004 (3:20 pm)
Well, I've gone through about 15 iterations in the last 4 days on this, the last post with the console log is basically the root error. I used tree quite a few times to analyze what was on the client, and many times I could see the RTSUnitData objects in the client side tree, as well as being able to see the RTSUnit objects--however, the RTSUnit objects did not have any of the 4 RTSUnitData blocks assigned.

Right now, the console output seems to be the root cause of the error--not even the server RTSUnit has a datablock assigned, due to the error

'riflemanBlock' is not a member of the 'GameBaseData' data block class

what's wierd, and what lead me to think it was a namespace issue, is the fact that the base.cs and rifleman.cs scripts load without any errors at all.

By the way, I realize that most of those scripts were already compiled, but I have repeatedly deleted all of the .dso's--just happened to grab the latest console log.

The underlying code and script files for the gameConnection.cs are exactly the same as the RTS kit.
#9
11/16/2004 (4:07 pm)
Well, I can't explain why, but RTSUnitData::onAdd() is NOT being called. It's being loaded in and compiled, but the creation of units is somehow not calling it.
#10
11/16/2004 (5:28 pm)
Well, I've nailed it down as far as I can tell to the fact that when you try to declare the new RTSUnit, with %data as the datablock, RTSUnitData::onAdd() is absolutely not being called.

function RTSConnection::createPlayer(%this, %spawnPoint, %index)
{
   switch(%index % 3)
   {
      case 0:
         %data = botBlock;
      case 1:
         %data = riflemanBlock;
      case 2:
         %data = shockerBlock;
   }
      
   %player = new RTSUnit() 
   {
      scale = "1 1 1";
      dataBlock = %data;
      shapeFile = "~/data/players/player/player.dts";
      path = "";
   };
echo("RTSConnection::createPlayer--Created new %player" SPC %player SPC "for Connection " @ %this SPC
     "dataBlock =" SPC %player.getDataBlock().getName() );

   MissionCleanup.add(%player);
   
   %player.setControllingConnection(%this);
   %player.setSkinName( getWord($Pref::Server::TeamInfo[%this.getTeam()], 3) );
   %player.setTeam(%this.getTeam());
   %player.setTransform(%spawnPoint);
   %player.client = %this;
                    
   %player.stats["Kills"] = (getRandom() * 5) % 5;
   %player.stats["Damage Delt"] = (getRandom() * 1000) % 1000;
   
   // Add the unit to the group of units
   %this.units.add(%player);
}

I've triple checked the path for shapeFile, our directory structure looks like:

exe dir
--game
----data
------players
---------player.dts

gameConnection.c (where this function resides) is in:

exe dir
--game
----server
------scripts
--------core
----------gameConnection.cs

it does seem unusual to me that the /game/ isn't in there, but all other .dts shapes at any level use the exact same path as above. /server/ and /data/ are at the same dirpath level (both under exedir/game/).

if the path to the shapeFile was incorrect, wouldn't it give some sort of error? or could this really be the issue?
#11
11/16/2004 (7:39 pm)
RTSUnitData::onAdd isn't called at that point... it should get called when the datablock {} block is executed. Sorry not to give more verbose replies, trying to balance my desire to play HL2 with my desire to get RTS work done. ;)
#12
11/16/2004 (7:46 pm)
Lol...

Yes, I agree (from my debugging code in RTS Pack stock), it executes pretty much at the new RTSUnit {...} time. In fact, what I was seeing in stock was :

RTSConnection::createPlayer();
RTSUnitData::onAdd();
-->echo out data about the block

repeat the above for each unit created server side (and this was in the server side console)

Thing is, my current (broken) port to our code gives the console log above--which has debug lines that -should- echo out "RTSUnitData::onAdd()", but instead you get the error message about "is not a member of the 'GameBaseData' datablock class.

My guess here is that there is some indirect dependencies on the order of the files you exec that I keep missing, but I've been moving files all around all weekend, and not "caught" it yet.
#13
11/17/2004 (5:54 am)
Small anecdote:

If you haven't been following the whole EA eats their developers discussions around the net, here's a little proof of how bad a crunch can be to efficiency and effectiveness:

Greg and I have been self-crunching for easily a full week now, and it looks like it's probably cost me a good 20 hours of debugging. As it turns out, this issue (not a member of GameBaseData) has (of course) been asked before on the forums, but being as tired as I was, I failed to use common and normal troubleshooting guidelines, and assumed that it was a "first time error" based on the import from the RTS Pack into our code. I also assumed that if I simply did things in the right order regarding the datablocks themselves (there are dependencies of a sort in there), I would be good to go.

Based on a simple forum search on "gamebasedata", I found out that I was right in a way, it is a dependency thing (what order you load your scripts in), but it had nothing to do with the datablocks themselves--just the fact that you have to load in your datablocks for most things -after- the server has been created, not before.

I'm guessing that in a non-dedicated server environment, this is transparent, but in a dedicated server setup, we can't create all the RTSUnit datablock stuff until after the server itself has been created and initialized.

Greg is refactoring all of our server bootup sequence now, so I haven't actually proven this is the solution, but I'm confident that when we move the associated scripts to post dedicated server creation, the bug will go away.

Morale of the story: When crunching it may make sense to review from time to time your normal workflow "checklists" (either in memory, or if you actually have one). Had I performed the standard phase of troubleshooting "research the problem in your community, if any" (that's my internal checklist, nothing formal), I would have easily saved a good 5+ days of headache!
#14
11/17/2004 (8:42 am)
An update:

I've done an extensive comparison of objects in the client when running the RTS demo "standalone", and running our project in dedicated server mode.

RTS Standalone groupings:

GhostAlwaysSet
Mission Area
Sunflare2
Terrain
Sky
Sun
sunflare1
DataBlockGroup
-has ALL dataBlocks in the game
--RTSUnitData with appropriate block names
ServerConnection
RTSUnits
fxSunlight
Sun
Sky
TerrainBlock
MissionArea

Nemesis client-server(dedicated) groupings (client side):

GhostAlwaysSet
EMPTY
DataBlockGroup
EMPTY
ServerConnection
RTSUnits
fxSunlight
Sun
Sky
TerrainBlock
MissionArea
most datablocks, including RTSUnitData, but they have no names on them (riflemanBlock, botBlock, etc. are missing)
all the audio profiles, etc. are here as well.

This implies to me that something is wrong with how our various objects are assigned SimGroups on the client side...so how is that accomplished? We didn't touch anything related to missionDownload and such as far as we know.
#15
11/18/2004 (7:31 am)
Update: After some very extensive research, troubleshooting, and contacting others with dedicated server setups, it appears that the current release of TGE intentionally does NOT allow datablocks to be accessed via the client--either that, or it's a set of bugs in the engine itself.

To wit: both our project and Adellion have used the tree(); command in console on a client connected to a dedicated server, and the DataBlocks group is NOT populated with any data whatsoever.

Every datablock is in the ServerConnection group, and does NOT have a name attached to the datablock itself, and therefore cannot be viewed with $ObjectID.getDataBlock().getName);, nor can it be set client side with $ObjectID.setDataBlock();. This does actually make some sort of convoluted sense, since you want the server to be authoritative regarding objects, but it brings up the following problem:

The SelectionDisplay script uses extensive datablock names to sort the selected units, and display the proper images. This does work (obviously) for anyone running in single player mode (local), and we do not know if this display has been tested in a multi-player environment, but my guess is that it will not actually work properly.

Any feedback from the RTS pack devs regarding if that functionality was tested in a multi-player setup? If it was not, do you have a possible alternative implementation that would work in all cases (single/local player, multi-play, dedicated client/server), or at least some suggestions for how to resolve out the datablock information that is assigned to a local ghosted object?

EDIT: We just confirmed this using the resource: How to identify objects from client to server...

The SelectionDisplay scripts make the assumption that DataBlocks are available and indexable via name, which is not the case in all scenarios. We're working on a fix to the script now.
#16
11/18/2004 (11:30 am)
We've closed out this bug in our project, and I wanted to say thanks to all that helped with (and discovered!) the issue. As it turns out, the fact that dedicated clients do not have access to datablocks via "name" reference is intentional.

Please see this thread, SelectionDisplay incorrect assumption: Client datablocks for one type of solution.