Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Major Updates to Mod Scripts Coming in March

April 16 (9 months ago)
The Aaron
Roll20 Production Team
API Scripter

That's completely fine, I don't mind talking about programming on any level, even the ground floor.  The people who don't struggle with imposter syndrome from time to time don't know enough about the subject to know how much they don't know yet. =D  

April 16 (9 months ago)
The Aaron
Roll20 Production Team
API Scripter

Hey everyone!

It's a few weeks later than we intended, but tomorrow is the big day!

Wednesday, April 17th at 1:00pm PDT, the updated Roll20 Mod Server will be rolled out!

We aren't expecting any problems, but to be prepared for good experiences in peak times, we're starting up early enough that we can monitor games as things get moving.

Your feedback will be important to make sure we identify any issues early and get a good resolution to them quickly.  If there ends up being a problem, we can safely revert back to the prior version with no loss of data or configuration, so keep us posted about your experiences.

I'm looking forward to seeing what we all build together, see you tomorrow!

April 17 (9 months ago)

Edited April 17 (9 months ago)
Riley D.
Roll20 Team

Hey folks,

We are in the process of rolling this out. One of the things to note right off the bat is that due to the underlying system that Aaron in place, it takes a bit longer to spin up the API Sandbox for large games (could take as much as 30+ seconds for some large games). We think we have a way to reduce this substantially, but we need to get real-world feedback on game sessions to know what to tweak. Note that after the sandbox spins up, the response time for the API itself should be just as fast as it was before. The other tradeoff here is that large games that wouldn't load at all in the previous version should load in this one.

I think our plan right now is to let this run for a bit so we can start seeing what sort of feedback/errors/etc. folks run into, and then we may make a decision on whether to turn this back off for a bit while we make tweaks...but we're interested to hear your feedback so let us know what you see!

Thanks!

April 17 (9 months ago)
The Aaron
Roll20 Production Team
API Scripter

Hey everyone!

We're going to pull this back.  We gathered some great data, but there are some memory constraints with very large games that we need to solve.  While we would be able to support 99% of current games, there would be some edge cases where games would not be able to start and that's just not tenable.  I'm going to be working on optimizing those memory constraints, and see about speeding up startup as well.  We'll post back with a new schedule when we get a handle on the changes.

April 17 (9 months ago)
Riley D.
Roll20 Team

Hey folks -- just a quick update on this. As you know there are quite a few significant changes that were made to the API System to modernize it and bring it up to speed on some of our newer features. I think given that, it would be a better rollout strategy to let people opt into using the new system and trying it out, rather than just rolling it out to every game all at once.

So we're going to quickly build out an option to let you do that. That will delay the release of this about a week, but the good news is once this is in place, we can roll it out and leave it out (rather than it having to be "perfect" day one). In addition, this will set us up so that in the future we could have a "Beta" branch and a "Release" branch of the API to help enable faster development -- honestly this is something we should have done a long time ago.

So, apologies on the delay, but we'll get this out hopefully next week and I think in the long term this short delay to invest in the API sandbox "version picker" will be well worth the wait. We'll keep you posted.

April 17 (9 months ago)
Andrew R.
Pro
Sheet Author

Excellent! I’m keen to help with Beta testing. I missed the rollout because I was asleep in Australia at the time. 

April 23 (9 months ago)
Riley D.
Roll20 Team

Hey folks!

We have this new opt-in system built and ready to go, I'm planning to roll it out tomorrow. At that time you'll be able to opt in to Aaron's new API changes and start testing them with your games. So we'll keep you posted when that goes live tomorrow. Thanks!

April 23 (9 months ago)
Pat
Pro
API Scripter

Okay, I wanted to update the old Teleport mod, to do so, I believe I need checkin-checkout software to work with the mod server, but I'm short on details and it's been a few years since I've done it. Is there a quickstart around, and has it changed? 

April 25 (9 months ago)
Riley D.
Roll20 Team

Hey all!

The first part of this went out this evening, but it's not fully enabled yet. You will now see a toggle on the Mod Scripts page where you can switch between the "Default" or "Experimental" API Sandbox version. Toggling it right now will have to real effect, but we should roll out the backend to this tomorrow. I'll keep you posted. Thanks!

April 25 (9 months ago)
Riley D.
Roll20 Team

Okay here we go! This is now live and working.

If you go to your Mod Scripts page, you can switch to the Experimental version. You can tell that you are in the Experimental version of the sandbox because you will see the following message when the sandbox starts up:

"SANDBOX: Ready fired after 7.80s, 602 objects."

Note that the "switching version" stuff can be kind of finnicky for already running games. If for some reason it doesn't actually switch over, it will always work if you just leave the game entirely and let the sandbox timeout due to inactivity then come back. But just noting this isn't really meant for switching rapidly back and forth between the API Sandboxes, it's more for setting it once and then using that sandbox for that game.

I'd also recommend testing the new Experimental Sandbox on a copy of your game, of course. In theory it should be fully backward compatible, but it is Beta.

So go out and use it and give us your feedback, and I'll turn it over to Aaron to field questions and bug reports and all that for the actual new work that's been done :-)

Thanks!

April 26 (9 months ago)

What tag do you want us to use in the help request?

April 26 (9 months ago)

Edited April 27 (8 months ago)

When you start testing by copying a game without players, then adding Mod scripts without first launching the game, expect errors on mods that access the player objects. For example: adding APIHeartBeat yields TypeError: Reduce of empty array with no initial value.

Launching the game once solves the issue.

April 27 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter

Oh, interesting!  I'll try and duplicate that. 

April 27 (8 months ago)

Edited April 27 (8 months ago)

Currently you can identify that the Experimental sandbox is selected because the Mod Output Console shows

"SANDBOX: Ready fired after 6.24s, 578 objects."

would it be possible to also report whether jumpgate beta is applicable for this game?

I am comparing four versions (legacy vtt, jumpgate, legacy mod, new mod) and having this in the Mod Output Console would make it easier comparing logs.

April 28 (8 months ago)

Edited April 28 (8 months ago)
P1)  The new findObjs implementation does not behave as the old one in exactly the same way. For example: searching on imgsrc must have had some extra logic to compare image urls.

this might be a reason for the many macro creations of ApiHeartbeat. The CombatMaster mod also creates many objects too many.


2) The new toFront does not bring all objects to the front, it must have some logic to test the controlledby field.


3) iobserved that the new sandbox code checks image urls and changes these to the new image delivery urls.

https://s3.amazonaws.com/files.d20.io/... =>  https://files.d20.io/...

Any mods that compare img url fields (with or without getCleanImgsrc) break.


Details and investigation details have been pm-ed to the Aaron.


BTW i am happily surprised that the bugs i run into are specific edge cases. This is a good first public beta.

April 28 (8 months ago)

Edited April 28 (8 months ago)
Andrew R.
Pro
Sheet Author

I can report that all the Mods I use in my 13th Age Glorantha game are working exactly as expected. They are:

  • MetaScriptToolbox
  • TokenMod
  • TokenNameNumber
  • ScriptCards

I noted Martijn's report above and launched once before adding Mods and switching to Experimental.

Next I'm going to copy my 13G & TOR2e Library games and switch to Experimental for more testing.

April 28 (8 months ago)
Andrew R.
Pro
Sheet Author

I just tried using a ScriptCards feature that I haven't tried before, and I got an error, so I'm reporting it here and in the ScriptCards thread. 

The script I'm running is 

!scriptcard {{
    --#title|Style_Runes
    --/| Rune-Air (Orange)
    --#titlecardbackground|#FFA500
    --S#Rune|Air
}}

and the error message I get is 

"SANDBOX: Ready fired after 4.39s, 1138 objects."
"WARNING: Refusing to set \"current\" to undefined. [Roll20 attribute -NwZEHmFt-tTY2RhdogE]"

I was using the Original Method of Saving and Loading but I wanted to try the Enhanced Methods of Saving and Loading as part of my testing. 

April 28 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter


Martijn S. said:

Currently you can identify that the Experimental sandbox is selected because the Mod Output Console shows

"SANDBOX: Ready fired after 6.24s, 578 objects."

would it be possible to also report whether jumpgate beta is applicable for this game?

I am comparing four versions (legacy vtt, jumpgate, legacy mod, new mod) and having this in the Mod Output Console would make it easier comparing logs.


There isn't a way for the Mod API server to tell if Jumpgate is enabled that I'm aware of.  The Mod API server operates on the data model of the game, where as Jumpgate is a different UI that uses the same data model.

April 28 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter


Martijn S. said:

P1)  The new findObjs implementation does not behave as the old one in exactly the same way. For example: searching on imgsrc must have had some extra logic to compare image urls.

this might be a reason for the many macro creations of ApiHeartbeat. The CombatMaster mod also creates many objects too many.

That's right!  When I cleaned up the image code, and added in support for duplicating marketplace content already in the game, I set up optimization of the urls to get rid of the problem of aways needing to substitute a thumb url, and changed them to the faster image endpoint.  However, as you surmised, that's causing a miss on finding the image.  Internally, I'm matching the imgsrc in other places against a uniq key calculated out of the URL.  I don't know if I can repurpose that code, but at a minimum, I can do the same transform on the incoming url before the match and that should handle the problem. 


2) The new toFront does not bring all objects to the front, it must have some logic to test the controlledby field.

I will dig into this one.  Are you saying it only seems to work on objects you control?  Are you using TokenMod for this by chance?


3) I observed that the new sandbox code checks image urls and changes these to the new image delivery urls.

https://s3.amazonaws.com/files.d20.io/... =>  https://files.d20.io/...

Any mods that compare img url fields (with or without getCleanImgsrc) break.

This is the same issue as 1), really.  I'll get that addressed.


Details and investigation details have been pm-ed to the Aaron.
BTW i am happily surprised that the bugs i run into are specific edge cases. This is a good first public beta.

Thanks on both counts!  It would be great to release with no bugs at all, but as they say, "if debugging is the process of taking bugs out of code, coding is the process of putting them in there!"



April 28 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter


Andrew R. said:

I just tried using a ScriptCards feature that I haven't tried before, and I got an error, so I'm reporting it here and in the ScriptCards thread. 

The script I'm running is 

!scriptcard {{
    --#title|Style_Runes
    --/| Rune-Air (Orange)
    --#titlecardbackground|#FFA500
    --S#Rune|Air
}}

and the error message I get is 

"SANDBOX: Ready fired after 4.39s, 1138 objects."
"WARNING: Refusing to set \"current\" to undefined. [Roll20 attribute -NwZEHmFt-tTY2RhdogE]"

I was using the Original Method of Saving and Loading but I wanted to try the Enhanced Methods of Saving and Loading as part of my testing. 

This is great, actually.  There is a problem in the existing sandbox when attribute values get set to a bad value (particularly NaN).  What this means is that ScriptCards has a case where it tries to set the value of current to undefined, and the new Mod Server is detecting that and not doing it.  Right now, that means that current goes unset, and retains its prior value.  It might make more sense in these cases to just set it to "" (empty string), assuming that a bad value means just clear it.  I didn't make that choice initially because to my thinking it would always be a bug in the script itself if this came in as a bad value, and I'd want to find and fix that on the script side.  Making it vocal with a warning like this should let script authors clean up those problems without breaking the sandbox when it happens.

April 30 (8 months ago)
Victor B.
Pro
Sheet Author
API Scripter

@The Aaron, one of the challenges I faced with CM is being able to transfer the existing combat to a new page.  The current exposed architecture of Roll20 doesn't allow for changing the current page.  I looked at the pagefolder functionality.  Could this be leveraged? 

April 30 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter

PageFolders won't help with that, but it is something I've talked to Riley about. 

May 01 (8 months ago)
Andrew R.
Pro
Sheet Author

Thank you for the explanation, and I agree with your reasoning. I found the problem with my script and corrected it. 

The Aaron said:

This is great, actually. … Making it vocal with a warning like this should let script authors clean up those problems without breaking the sandbox when it happens.





May 01 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter

Great!

May 03 (8 months ago)

This just happen. has anyone encounter the same thing.


May 03 (8 months ago)

Just in case somebody ask this is the full view. I have scripts on this campaign.



May 03 (8 months ago)

Never mind it corrected by itself. 

May 05 (8 months ago)

I keep getting errors in one of my campaigns where the sandbox frequently crashes with not a informative error message. could someone help me out? Thanks.

May 06 (8 months ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

Is there an error log below (see an example in the screen shot two posts above yours)? That might contain useful information to include here.

May 06 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter

Possible Infinite Loop Detected happens when the scripts take too long before relinquishing control back to the sandbox.  Usually, this will be a script reacting to an event by doing something that takes a very long time.  On rare occasions, this will happen when you start the sandbox if your game is extremely large (like, more than 500,000 objects).  So, the two important questions are:

  1. Is your game really large?
  2. What scripts do you have installed?

In the case of 1, you can move things out of the game to another game for storage and remove them from the source game.  In the case of 2, you need to identify which script might be causing the issue and get it fixed.  The fix is often pretty easy, and many of us can help with that.  Just post a list of the scripts you have, and we can help you start looking into it.

May 06 (8 months ago)


May 06 (8 months ago)

I dont think its to large but I could be wrong. I can invite to game if necessary.

May 06 (8 months ago)

Edited May 06 (8 months ago)


Aryan said:

I dont think its to large but I could be wrong. I can invite to game if necessary.


with the survey mod you can count the objects in your game and know for sure. See https://app.roll20.net/forum/permalink/10675897/



Let's go through your list of MODs. Most of these only react to chat or react to changes to single objects (and then change single objects).
The way to detect whether these MODs are the culprit is to have a second browser open with the MOD Output Log next to your play game.

Aura/Tint HealtColors creates some FX object on startup. As FXs are documented to be not implemented, that mod might be suspect.

The '5th Edition OGL by Roll20 Companion Script' MOD sets the on('chat:message',..) outside the on('ready',...), that might give an issue if you chat something at exactly the moment that the sandbox is starting up. But as you state it is recurring, this is very unlikely.

May 06 (8 months ago)

Edited May 06 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter

with that list of scripts, there isn't an obvious culprit.

Nice updates!!

May 22 (8 months ago)
The Aaron
Roll20 Production Team
API Scripter

Hi all,

We've pushed out an update for the Experimental branch that should fix the issues with findObjs() when searching by image URL.  Also some minor issues with updates to `_` properties (like `_lastpage`).

Please keep the feedback coming, it's really helpful!

wow gone for 8 months and TheAaron is made official. CONGRATS and excited to see the new changes to roll20. 

May 26 (8 months ago)

Edited May 26 (8 months ago)
Richard @ Damery
Pro
API Scripter

findObjs() in the experimental sandbox still does not seem to be working correctly for finding handouts.

I've not yet done extensive testing of the RPGMaster suite in the experimental sandbox, but initially mostly seems to run fine.  However there is one issue with findObjs() for handouts.

My mod suite RPGMaster creates 16 API help handouts when first loaded, and then checks for these each subsequent load (checking the version number to see if they need updating). However, if I load the RPGMaster suite into the experimental sandbox it never finds the handouts, and creates another 16 handout objects every time the campaign is loaded (or the sandbox restarts).  The code I use to find the handouts is:

let dbCS = findObjs({ type:'handout', name:obj.name },{caseInsensitive:true});
if (!dbCS || !dbCS[0]) {
    ... create the handout ...
} else {
    ... check the version and update the 'notes' if necessary ...
}
where obj.name resolves to the name of the handout being looked for. This works fine in the default sandbox.
Is this a known issue? Do you need more info?

Hi All;  

Would anyone know if these improvements are why one of my favourite scripts has stopped working??

Community Forums: [Script] Critical Sound Effects v1.0 | Roll20: Online virtual tabletop

May 27 (7 months ago)

Edited May 27 (7 months ago)
Andrew R.
Pro
Sheet Author


Joshua C. said:

Hi All;  

Would anyone know if these improvements are why one of my favourite scripts has stopped working??

The improvements are available only if you change to Experimental. So try it in Experimental, then change it back to Default and try it again. 

May 27 (7 months ago)
The Aaron
Roll20 Production Team
API Scripter

I don't know why it would quit working, but I have tried this version of it (minor updates for modern code style and loading efficiency), and it worked on both production and experimental.  It will also output whether it was able to find the two songs needed, like this in the API log:

"Script loaded: Critical Sound Effects"
"  * criticalHit: [Loaded]"
"  * criticalFail: [Loaded]"

Script:

//Critical Sound Effects v1.2.3

on('ready',() => {
  let excludeGM = false; // this to false if you wish to include GM rolls
  let defaults = {
    css: {
      button: {
        'border': '1px solid #cccccc',
        'border-radius': '2px',
        'background-color': '#006dcc',
        'margin': '0 .1em',
        'font-weight': 'bold',
        'padding': '.1em 1em',
        'color': 'white'
      }
    }
  };
  let templates = {};
  let criticalHit = null;
  let criticalFail = null;
  let allsongs = findObjs({
    _type: 'jukeboxtrack'
  });

  allsongs.forEach(function(song) {
    if(song.get('title') === 'Critical Hit') {
      criticalHit = song;
    } else if (song.get('title') === 'Critical Fail') {
      criticalFail = song;
    }
  });



  buildTemplates();


  function criticalHitOrFail(content) {
    if (content.rolls) {
      content.rolls.forEach(function(roll) {

        if (roll.dice === 1 && roll.sides === 20) {
          if (isCriticalHit(roll)) {
            play(criticalHit);
          } else if (roll.results[0].v === 1) {
            play(criticalFail);
          }
        }

        if (roll.dice === 2 && roll.sides === 20 && roll.mods && roll.mods.customCrit) {
          if (keptResultIsCriticalHit(roll)) {
            play(criticalHit);
          }
          else if (keptResultIsCriticalFailure(roll)) {
            play(criticalFail);
          }
        }

        function isCriticalHit(roll) {
          return roll.results[0].v === 20 || roll.mods && roll.mods.customCrit && roll.results[0].v >= roll.mods.customCrit[0].point;
        }

        function keptResultIsCriticalHit(roll) {
          let customCrit = roll.mods.customCrit[0].point;

          return roll.mods && roll.mods.keep &&
            roll.results.some(function(result) {
              return result.d === undefined && result.v === 20 ||
                result.d === undefined && result.v >= customCrit;
            });
        }

        function keptResultIsCriticalFailure(roll) {
          return roll.mods && roll.mods.keep &&
            roll.results.some(function(result) {
              return result.d === undefined && result.v === 1;
            });
        }
      });
    }
  }


  on("chat:message", function(msg) {

    if (!playerIsGM(msg.playerid) || !excludeGM && msg.type !== "gmrollresult") {
      //for Shaped 5e Character Sheet
      if (msg.inlinerolls) {
        msg.inlinerolls.forEach(function(inlineRoll) {
          criticalHitOrFail(inlineRoll.results);
        });
      }

      //for roll chat command
      else if (msg && isJson(msg.content)) {
        let content = JSON.parse(msg.content);
        criticalHitOrFail(content);
      }
    }

  });

  function isJson(str) {
    try {
      JSON.parse(str);
    } catch (e) {
      return false;
    }
    return true;
  }

  function play (song) {
    if (song) {
      song.set({'playing': true, 'softstop': false});
    }
  }

  function buildTemplates() {
    templates.cssProperty =_.template(
      '<%=name %>: <%=value %>;'
    );

    templates.style = _.template(
      'style="<%='+
      '_.map(css,function(v,k) {'+
      'return templates.cssProperty({'+
      'defaults: defaults,'+
      'templates: templates,'+
      'name:k,'+
      'value:v'+
      '});'+
      '}).join("")'+
      ' %>"'
    );

    templates.button = _.template(
      '<a <%= templates.style({'+
      'defaults: defaults,'+
      'templates: templates,'+
      'css: _.defaults(css,defaults.css.button)'+
      '}) %> href="<%= command %>"><%= label||"Button" %></a>'
    );
  }

  log('Script loaded: Critical Sound Effects');
  log(`  * criticalHit: [${criticalHit?'Loaded':'Missing <Critical Hit>'}]`);
  log(`  * criticalFail: [${criticalFail?'Loaded':'Missing <Critical Fail>'}]`);
});