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



  • @artch, I absolutely understand your concern about server load. Would it be ok to edit it to only push to console when the user changes rooms, not every tick? And if so, is there a better way than the following? The only current way I can see, is still using angular.element($('body')).injector().get('Connection').onRoomChange() and tracking URL changes or changes to the roomName value in the room scope. Would that be acceptable to the devs? I doubt many users are switching rooms quickly enough to overburden the servers, and fewer still would actually be using a script like this.

    Also, I think that the auth token support could be easily included in these scripts. I'll start using that in all my future endeavours.



  • @artch Cool. I don't see myself changing rooms more than 20-50 times an hour, and that would only be if I am sitting there exploring for the whole hour, so that should be well within the rate limit.

    👆


  • EDIT - this snippet only works in IVM. To support non-IVM, the rooms cache would need placed into Memory

    So at the bottom of this post is an example script that uses the user/console API to create this functionality. It will inject the functionality into your running client whenever your global resets, or whenever you run the console command injectViewHistory();. It should never inject the functionality into your client more than once, even if the global resets. It will put an undefined into your console each time you change rooms. See this forum post for details on that functionality getting changed: https://screeps.com/forum/topic/2182/allow-third-party-software-to-not-spam-the-in-game-console

    Note that this example script does not use the correct auth token end-point, so if you spam room changes rapidly, you could get rate-limited like @artch already stated. This call is very easy to change to a post with your auth token, but I did not use the auth token version in this prototype.

    You must save the script below as a module named viewhistory. Then, in your main module you can then use it like this:

    main.js

    var viewhistory = require('viewhistory');
    viewhistory.inject();
    
    module.exports.loop = function() {
        console.log(viewhistory.rooms());
    }
    

    viewhistory.js

    let injected = false;
    const _rooms = {};
    const ROOM_LIMIT = 3;
    
    global.injectViewHistory = function() {
        injected = false; 
        inject();
    }
    
    function inject(){
        if(!injected) {
            injected = true;
            var output = `<SPAN>Trying to inject View History code!</SPAN>
            <SCRIPT>
            if (typeof watching === "undefined") {
                var watching = false;
                let lastRoom = "sim";
                
                function attach() {
                    if(!$('section.game').length) return setTimeout(attach,100);
                
                    let gameScope = angular.element($('body')).scope();
                    if (gameScope && !watching) {
                        watching = true;
                        gameScope.$watch('Loader.loadingCnt', (n) => {
                            if (n === 0) {
                                let roomScope = angular.element($('section.room')).scope();
                                if (roomScope) {
                                    let Api = angular.element($('section.game')).injector().get('Api');
                                    let room = roomScope.Room;
                                    if (room) {
                                        if (lastRoom !== room.roomName) {
                                            lastRoom = room.roomName;
                                            console.log("viewed " + room.roomName);
                                            /* should be replaced with an auth token post to user/console instead of injected */
                                            Api.post('user/console',{
                                                expression: "viewedRoom('" + room.roomName + "');",
                                                shard: room.shardName
                                            });
                                        }
                                    }
                                }
                            }
                        });
                    }
                }
                
                $(function () {
                    setTimeout(attach);
                });
            }
            </SCRIPT>`
    	    console.log(output.replace(/(\r\n|\n|\r)\t+|(\r\n|\n|\r) +|(\r\n|\n|\r)/gm, ''));
        }
    }
    
    function rooms() {
    	return Object.keys(_rooms);
    }
    
    global.viewedRoom = function(roomName) {
    	_rooms[roomName] = Game.time;
    	let keys = Object.keys(_rooms).length;
    	while (keys > ROOM_LIMIT) {
    		let oldest;
    		for (const roomName in _rooms) {
    			if (_rooms.hasOwnProperty(roomName)) {
    				if (!oldest || _rooms[roomName] < _rooms[oldest]) {
    					oldest = roomName;
    				}
    			}
    		}
    		keys--;
    		delete _rooms[oldest];
    	}
    }
    
    module.exports = {
        inject,
        rooms
    };