On May 12 an update will be deployed that will introduce some changes to the API which can require adjustments in your script. The changes affect two fields:
-
The underlying data structure in which flags data is stored on the server was revised for optimization purposes, and now the
Flag
prototype does not have theid
property. If you have worked only with propertiesname
,color
/secondaryColor
, andmemory
, you have nothing to worry about. Otherwise please change your logic in order not to use theid
property. Besides, the constantsCOLOR_*
now represent integer values rather than strings, so if you used their values directly, please make sure to use names of variables from now on. -
We are considerably expanding the list of prototypes of game objects. Now all the prototypes will be arranged into a hierarchy and inherited in a chain. Here is the tree of prototypes:
Room |
|||
RoomPosition |
|||
RoomObject (room, pos) |
|||
├ | ConstructionSite |
||
├ | Creep |
||
├ | Flag |
||
├ | Mineral |
||
├ | Resource |
||
├ | Source |
||
└ | Structure (structureType, hits, hitsMax, destroy, notifyWhenAttacked, isActive) |
||
├ | OwnedStructure (my, owner) |
||
│ | ├ | StructureController |
|
│ | ├ | StructureExtension |
|
│ | ├ | StructureExtractor |
|
│ | ├ | StructureKeeperLair |
|
│ | ├ | StructureLab |
|
│ | ├ | StructureLink |
|
│ | ├ | StructureNuker |
|
│ | ├ | StructureObserver |
|
│ | ├ | StructurePowerBank |
|
│ | ├ | StructurePowerSpawn |
|
│ | ├ | StructureRampart |
|
│ | ├ | StructureSpawn (aliased as Spawn for backward compatibility) |
|
│ | ├ | StructureStorage |
|
│ | ├ | StructureTerminal |
|
│ | └ | StructureTower |
|
├ | StructureContainer |
||
├ | StructureRoad |
||
└ | StructureWall |
You are free to use these prototypes in your scripts:
Game.rooms.W0N0.storage instanceof StructureStorage // true
Game.rooms.W0N0.storage instanceof OwnedStructure // true
Game.rooms.W0N0.storage instanceof Structure // true
Game.rooms.W0N0.storage instanceof RoomObject // true
So, because of this, if you have overrided some properties or methods, you have to check that you are doing this in the right place of the tree.
These changes have already been deployed on the Public Test Realm, so we recommend to go there and check if your script works correctly before the update goes live on the main server.
Can we get a new copy from PROD to PTR?
What is the reason to remove the ID behind flags? It was the one thing that was uniform between all objects, which now means my complete path/route caching mechanism is broken and has to be re-written.
To say the least, I'm not happy about this.
It has been copied by the time this article had been published.
The allowed flags count is unlimited for every player, and some players have thousands of them, while owning only few “real” game objects. However, they were stored as real database objects which affects its performance significantly. Now, they all are serialized into string form and stored in a few database entries.
id
property cannot be assigned by database to them in this case.Another option to solve this perf issue would be introducing a hard limit for flags, but we really don’t want to go this way.
For a quick and dirty fix I’d recommend using some abstract layer on top of
Flag.name
property like that:function getObjectOrFlagById(id) { return Game.getObjectById(id) || Game.flags[id]; } function getIdOfObjectOrFlag(objectOrFlag) { if(objectOrFlag instanceof Flag) { return objectOrFlag.name; } return objectOrFlag.id; }
Thanks for the quick reply Artem.
My rooms are RCL 7 inside the PTR, thats why I asked for a copy of prod.
I'm all for the unlimited amount of flags, as it doesn't limit people's creations.
I'll try to get the "dirty fix" working, sadly regexes aren't exactly quick, but buys some time.
Sadly the only place where I used this ID is inside the path-cache because the Game.getObjectById() method was so performant, the rest used flag names.
It seems like transferEnergy is completely removed now, can you confirm this?
Right, something went wrong. Copied again.
On which prototype? It has been deprecated for ages on storages, so it has not been added to
StructureStorage
. However, it’s still there inStructureExtension
,StructureSpawn
, etc.It was on StructureStorage, Apparently I still used it to abstract away the Spawn and Storage difference.
Can we get an StructureSpawn.transfer(target, resource) to make it more uniform? I suggest that StructureSpawn.transfer(someCreep, RESOURCE_*) will return ERR_INVALID_ARGS if it's not energy.
Cause it might help some people, this here should register the id property again, using the flags name. Ofc won't help with issues where you've cached current Flag IDs, but the code at least won't completely break because of a missing property:
In combination with this:
https://gist.github.com/Amadox/4099f4f87bd7d3ff188fb21510cd6662
as a wrapper for Game.getObjectById
Feel free to extend
StructureSpawn
prototype this way, if you’d like to....will so do that. Also, quite excited about Spawn finally inheriting from Structure.. :D
Great change! I was desperately waiting for a proper prototype chain. Appreciate it!
One addition: I would appreciate having a prototype "NeutralStructures" to group containers, walls and roads (and future neutral ones). I think this would be consistent to the rest of the hierarchy.
It would not have any own properties though. What are you going to use it for, any usage examples that don’t fit into
Structure
prototype?You could write filters based on this prototype, instead of having to enumerate all of those structures separately. Perhaps one could extend the FIND constants to FIND_NEUTRAL_STRUCTURES as well. I realize, that it's a rather limited use case, but it might come in handy. And since you are revamping the structure anyways...? At the moment I already have 100+ prototype extensions - I guess once I advance deeper into currently untouched aspects of the game, there might be some use for me. I wouldn't be surprised, if other players already have some more concrete examples.
Artem, can we remove the depricate creep.transferEnergy as well? This way we remove everything depricated in 1 go.
This change would be a perfect match for Node 6, e.g. with having "super" and function "name" properties. But ofc I understand if you won't be able to do this soon.
I would reconsider removing Flag ids. It's not too hard to get around, like you have shown, but it's an unnecessary complication of the class hierarchy and hence the documentation. For example, in all the find path and moveTo methods you might need to specify that you can move to a RoomObject or a Flag, or "anything that has a pos", but that's needlessly complicating things.
I suggest giving the Flags a standard code generated UUID.
UUID doesn't seem to be a good solution when there could be hundreds of items generated across different machines within a few milliseconds. There is a considerable collision chance in this case.
I sincerely doubt it. From the article: "In other words, only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%"
*(edit to note: this is referring to UUIDv4)*
If you're still unsure, you might want to prefix the id with a player id.
You are talking about fully RFC-compliant UUID. However, most JavaScript implementations are plagued with either broken (at least in V8)
Math.random
, or extremely costlycrypto.randomBytes
calls. Both are unreliable in our use case.However, we might end up with simply aliasing flag ids to something like
"f_"+name
, which seems to be enough since they are unique to their owner, and are not accessible to others anyway.On the other hand, it is not about the ID generation algorithm. Flags don’t represent any real “physical” objects, they are invisible to other players, cannot be obtained via
getObjectById
by anyone except their owner. So theid
property (which identifies the object globally in the game world) doesn’t make any sense in their case, they just don’t exist in the game world basically, they are sort of visualization of some player’s array on his own screen. So it seems to be very consistent that they are not derived from theRoomObject
prototype.There is a node-uuid package promising RFC-compliant UUIDs, but I agree that your method solves the problem in an extremely quick and simple way. No matter the method, then the hierarchy can be streamlined.
node-uuid uses
crypto.randomBytes
. You will not be happy with the performance ofRoom.createFlag
if we go this way :)On the other hand (again),
RoomObject
could contain onlyroom
andpos
and noid
, then flags could be derived as well. We’ll have to think about that.To reply to your point about "real, physical objects": I see your point. However, as a player I don't see any difference, because I see and use flags like any other game object that I am able to select and interact with (unlike e.g. terrain). From my "player point of view", they're not a special case and I would prefer they worked like all other game objects, even with id.
Like you have shown before, there's also not a huge problem to implement getObjectById to also consider flag ids (though possibly with a small performance hit every time you ask for an object by ID and it's not found and have to check flags too, unless they are in the same list as other objects with ID).
I admit that from the “player point of view” they are like
RoomObject
in the way that they have the sameRoom
andRoomPosition
linked by the game engine to them, so they might inherit those properties from the appropriate prototype. However, as they won’t have any real database IDs anyway, aliasing their IDs to their names is likely a task for user code than for the game engine.Removing
id
fromRoomObject
and makingFlag
derived from it, seems to be the most sensible move.