Doing RoomVisual Logic Just For the Room I'm Looking At?



  • Hi.

    I'm trying to create a RoomVisual that will show the haves/wants for the terminal in my rooms (if it exists).

    From the docs, it seems like the way I do this is to generate a RoomVisual for every single room in my empire. This seems really wasteful. I only want to generate a RoomVisual for the room that I am actually looking at in UX. Is there a way to figure out what room I'm looking at in the browser?

    Maybe this is a feature request.

    If it were implemented as a callback, that would be even more elegant, probably. "Hey I'm about to draw this room, do you want to create a RoomVisual here or what?"

    👍


  • If you construct a RoomVisual without any parameters, it will apply to all rooms (without the overhead of creating a new RoomVisual for every room)



  • I've been wondering about this too. I didn't know about RoomVisual without any parameters - that's helpful.

    However, I find I often want to view different things in each room (building plans is a good example). Having a way to only draw the visuals for the room which I am looking at would save CPU.


  • Dev Team

    @shedletsky said in Doing RoomVisual Logic Just For the Room I'm Looking At?:

    From the docs, it seems like the way I do this is to generate a RoomVisual for every single room in my empire. This seems really wasteful.

    This isn't wasteful. new RoomVisual() creates one single instance that is broadcasted for every room, rather than an instance per each room. Perhaps we have to explain it the docs more verbose.



  • @artch said in Doing RoomVisual Logic Just For the Room I'm Looking At?:

    @shedletsky said in Doing RoomVisual Logic Just For the Room I'm Looking At?:

    From the docs, it seems like the way I do this is to generate a RoomVisual for every single room in my empire. This seems really wasteful.

    This isn't wasteful. new RoomVisual() creates one single instance that is broadcasted for every room, rather than an instance per each room. Perhaps we have to explain it the docs more verbose.

    I think the problem is that you don't know what room you're actually looking at. Visuals logic for rooms you're not currently viewing can get quite expensive. It's a bit meta, but it would be nice to have an array somewhere with rooms you're currently viewing so you could short circuite out visuals logic for rooms you can't see. Right now I don't use visuals nearly as much as I otherwise would as they're just too expensive to do the logic for across 20+ rooms. Starts eating into creep intents.

    👍


  • Something like a RoomVisual.callback you could register to that only runs for the room you are viewing would be pretty cool.



  • One solution would be to allow only one RoomVisual instance and give it an arry with all rooms that are currently subscribed, since it could be multiple rooms.

    You can emulate that with a "info flag" as workaround



  • @tigga @artch

    Tigga nails it.

    I want to:

    1. Foreach room that is visible to me in the GUI
    2. Do a bunch of calculations that might be expensive
    3. Present the results as a RoomVisual

    I don't want to:

    1. Do a bunch of calculations that might be expensive for every room in my empire
    2. Present the results for all 120 rooms in a RoomVisual and maybe hit the 500kb limit, especially since I am only looking at 1 room at a time

    The best solution I have to far is I have a console command that turns on my viz layer for a specific room (it takes the roomName as an arg). However, this is fairly tedious if I need to type in a command for each room I want to look at when I'm debugging. I want Screeps to give me that roomName as an arg somewhere. What rooms are visible to my user in the GUI?


  • Dev Team

    Unfortunately, that is not technically possible, since it would require syncing game engine state and frontend client state. There is no such communication mechanism in the game, and implementing it would break the current architecture.



  • Even something as simple as firing something similar to a console command automatically with the room name as a parameter when a room is opened by a user would serve the purpose in a make-shift way.


  • Dev Team

    @gankdalf Game engine code is not aware of anything happening in the game client, there is no connection between them in our decoupled architecture.



  • But the client has its (fake) console. I mean even just having the client itself run a predefined console command when it opens a room would serve the purpose in a way.


  • Dev Team

    @gankdalf The console is not fake, it's a part of the game engine and is being executed in the same runtime loop as your script.



  • @artch Sorry, the only reason I called it "fake" was because the last time I looked at the engine code, that is what I thought it was called, and I wanted to differentiate it from the browser console.


  • Dev Team

    @gankdalf It is called fake because it's not real JS console interface. The game client has no direct access to it, it sends console commands in the same way as it commits scripts.

    Also, you may have multiple tabs open with different rooms, and engine code should not be concerned with these semantics.



  • @artch That is exactly to what I was referring though. It is a bit of a make-shift solution, but lets say I had this script for my in-game code.

    const _rooms = [];
    const _lruRooms = {};
    const ROOM_LIMIT = 3;
    
    global.viewedRoom = function(roomName) {
    	if (_room.indexOf(roomName)) {
    		_rooms.push(roomName);
    	}
    }
    
    global.visibleRooms = () => {
    	return Object.keys(_lruRooms);
    }
    
    export function loop() {
    	for (const roomName of _rooms) {
    		_lruRooms[roomName] = Game.time;
    	}
    	while (Object.keys(_lruRooms).length > ROOM_LIMIT) {
    		let oldest;
    		for (const roomName in _lruRooms) {
    			if (_lruRooms.hasOwnProperty(roomName)) {
    				if (!oldest && _lruRooms[roomName] < _lruRooms[oldest]) {
    					oldest = roomName;
    				}
    			}
    		}
    		delete _lruRooms[oldest];
    	}
    }
    

    If the OnRoomLoad event (or whatever the event is) for the client used the client -> console end-point to fire off a console command of viewedRoom("roomName");, it would be possible to limit the number of rooms I was creating visuals for by only creating them for at most the last 3 rooms I opened.

    As you have stated, this may not be something that should be implemented into the default client, but I am looking through the existing TamperMonkey scripts trying to find the OnRoomLoad and PostToConsole event and end-point, so that I can try it out.



  • I created an in-game script that, in conjunction with a PR for backend-local, would provide you a solution. you'd just have to run something in your console to catch each client. I feel like this would be your best bet. Have fun 🙂


  • Dev Team

    Posting a console command on every room load is not encouraged. If each player does so, it would significantly affect backend performance. We reserve the right to rate limit your console if we detect any automatic activity outside of our Auth Tokens system.



  • @artch So if SemperRabbit's script were changed to use an actual post to the API end-point with an auth token, that would be acceptable?


  • Dev Team

    @gankdalf Yes, since Auth Tokens are rate limited. Note that the limit for POST /api/user/console is 360 requests per hour, see here.