Bathtor / EPCompendium

Eclipse Phase Data in Scala/Scala.js
MIT License
2 stars 3 forks source link

How does one make use of this? #27

Closed geoidesic closed 4 years ago

geoidesic commented 4 years ago

Hi,

I don't understand how to implement this. The instructions aren't clear about where to insert the dependencies?

  1. I have created a new game with custom character sheet and pasted in your html, css and translations manually (as the "alternate" sheet doesn't appear as an option in the drop-down.
  2. I have then added an API Script and pasted your API Script in there.
  3. But now I don't understand how to integrate the custom compendium?
Bathtor commented 4 years ago

You basically do exactly the same as with the API script. The compendium release really is just an API script that contains mostly json.

I made a quick video to show the process, since people are often confused about this, but Youtube is taking forever to publish it, so I guess I'll be posting it tomorrow instead.

Bathtor commented 4 years ago

Well, at least the SD version is available now: https://www.youtube.com/watch?v=yoCmffUp9BE HD may need a few more hours of processing I suppose.

Let me know if that helps, and if yes I'll add it to the documentation.

geoidesic commented 4 years ago

Thanks Lars,

I think the video is great. I wouldn’t have been able to figure out what to do without it.

Pity there’s no sound? I think you just talking over it would really help with context – I didn’t understand what you were doing with the site’s security certificate or why for example, which you could easily explain. I also didn’t really understand the bit at the end where you’re exporting stuff from a website – wasn’t sure why that’s not just built into the compendium?

Looks like amazing work btw. Scala is complicated! I’m hoping to build a Gamma World 3rd Edition character sheet plus compendium (just for me, not for public release, due to licensing). I’m also hoping to build my own RPG system, so having a compendium would be handy. Looks like a LOT of work though :-/

Cheers, Noel

On 24 Dec 2019, at 02:21, Lars Kroll notifications@github.com wrote:

Well, at least the SD version is available now: https://www.youtube.com/watch?v=yoCmffUp9BE https://www.youtube.com/watch?v=yoCmffUp9BE HD may need a few more hours of processing I suppose.

Let me know if that helps, and if yes I'll add it to the documentation.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Bathtor/EPCompendium/issues/27?email_source=notifications&email_token=ABDMKK4RHHWYAZXCLTKIBXDQ2FIZBA5CNFSM4J6WY4G2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHSFMBQ#issuecomment-568612358, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABDMKKYPC6HF5DEG3QO6J3TQ2FIZBANCNFSM4J6WY4GQ.

Bathtor commented 4 years ago

Pity there’s no sound? I think you just talking over it would really help with context – I didn’t understand what you were doing with the site’s security certificate or why for example, which you could easily explain. I also didn’t really understand the bit at the end where you’re exporting stuff from a website –wasn’t sure why that’s not just built into the compendium?

Yeah, I don't have good setup for recording sound right now...Maybe I'll do a voice-over in the new year, when I get back to work and can use the equipment there. For now you'll have to make do with the explanations in the video description^^ I explain the security certificate thingy there, btw ;)

Well, most of the stuff from the website is build in the compendium as well. So you can kinda choose if you want to use the website or the API script. Whichever seems more convenient. Website may be easier to set up for people, since you can just use the dropdown sheet and dropdown script, instead of having to manually paste the compendium script. I usually also use the website when I'm GMing, since it's visually easier to find information there, compared to the chat output.

The only thingy you really have to do from the website is random character generation, because that code is waaaay too complicated for a Roll20 API script. Remember that API scripts have an execution time limit, and if they run out of time, they'll be interrupted in the middle of whatever they were doing, leaving your game in a potentially inconsistent state. That's pretty annoying, if you want to do thousands of random samples to generate a character. Thus, I use the website to generate characters and them import them into Roll20 as shown. This has saved me sooooooooo much time, since I implemented it, because in EP NPCs are basically just as complicated to build as player characters, which used to take me hours for every single combat-ready NPC (the other, of course, didn't need so much detail). Now I can just generate something from the right category and maybe tweak it a bit to fit into my theme for the character, and then I'm done.

Looks like amazing work btw. Scala is complicated!

It's also very convenient and easy to maintain ;)

I’m hoping to build a Gamma World 3rd Edition character sheet plus compendium (just for me, not for public release, due to licensing). I’m also hoping to build my own RPG system, so having a compendium would be handy. Looks like a LOT of work though :-/

Yeah, it may have been a bit of work to get where I am now. I did some rough math on my toggle.com stats, and the Sheet, Script, Compendium, Char Generator, and Website together have taken me around 500h over the past 3 years, I think. Of course, I also developed the Scala libraries for wrapping Roll20's code in something easier to work with during that time, which you probably wouldn't have to do if you worked either directly in Javascript or in Scala (since my libraries for this are open source). That should save you...I don't know...some time^^

geoidesic commented 4 years ago

The basic templates offered on the wiki are pretty awful :( and I couldn’t find anything about tabs on the Wiki. I don’t know Scala but I think your sheet is impressive.. pity I can’t read it.

I’ve been trying to get going on building a sheet but making very little progress. It doesn’t seem to allow one to add JavaScript… so how did you manage to get tabs working? Is that via a service-worker?

On 24 Dec 2019, at 13:25, Lars Kroll notifications@github.com wrote:

Pity there’s no sound? I think you just talking over it would really help with context – I didn’t understand what you were doing with the site’s security certificate or why for example, which you could easily explain. I also didn’t really understand the bit at the end where you’re exporting stuff from a website –wasn’t sure why that’s not just built into the compendium?

Yeah, I don't have good setup for recording sound right now...Maybe I'll do a voice-over in the new year, when I get back to work and can use the equipment there. For now you'll have to make do with the explanations in the video description^^ I explain the security certificate thingy there, btw ;)

Well, most of the stuff from the website is build in the compendium as well. So you can kinda choose if you want to use the website or the API script. Whichever seems more convenient. Website may be easier to set up for people, since you can just use the dropdown sheet and dropdown script, instead of having to manually paste the compendium script. I usually also use the website when I'm GMing, since it's visually easier to find information there, compared to the chat output.

The only thingy you really have to do from the website is random character generation, because that code is waaaay too complicated for a Roll20 API script. Remember that API scripts have an execution time limit, and if they run out of time, they'll be interrupted in the middle of whatever they were doing, leaving your game in a potentially inconsistent state. That's pretty annoying, if you want to do thousands of random samples to generate a character. Thus, I use the website to generate characters and them import them into Roll20 as shown. This has saved me sooooooooo much time, since I implemented it, because in EP NPCs are basically just as complicated to build as player characters, which used to take me hours for every single combat-ready NPC (the other, of course, didn't need so much detail). Now I can just generate something from the right category and maybe tweak it a bit to fit into my theme for the character, and then I'm done.

Looks like amazing work btw. Scala is complicated!

It's also very convenient and easy to maintain ;)

I’m hoping to build a Gamma World 3rd Edition character sheet plus compendium (just for me, not for public release, due to licensing). I’m also hoping to build my own RPG system, so having a compendium would be handy. Looks like a LOT of work though :-/

Yeah, it may have been a bit of work to get where I am now. I did some rough math on my toggle.com stats, and the Sheet, Script, Compendium, Char Generator, and Website together have taken me around 500h over the past 3 years, I think. Of course, I also developed the Scala libraries for wrapping Roll20's code in something easier to work with during that time, which you probably wouldn't have to do if you worked either directly in Javascript or in Scala (since my libraries for this are open source). That should save you...I don't know...some time^^

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Bathtor/EPCompendium/issues/27?email_source=notifications&email_token=ABDMKKYUVTLYPCI256J2WMLQ2HWTXA5CNFSM4J6WY4G2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHTB3TI#issuecomment-568729037, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABDMKK6LE6RFJDBOS5G3MT3Q2HWTXANCNFSM4J6WY4GQ.

Bathtor commented 4 years ago

The basic templates offered on the wiki are pretty awful :( and I couldn’t find anything about tabs on the Wiki. I don’t know Scala but I think your sheet is impressive.. pity I can’t read it. I’ve been trying to get going on building a sheet but making very little progress. It doesn’t seem to allow one to add JavaScript… so how did you manage to get tabs working? Is that via a service-worker?

Actually, the tabs are a wonderful cheat, that you can do in pure CSS. Basically the "links" to the tabs are actually a fancy radio button, and the show/hide property of the page they address is managed by selecting on the content value of the radio button. You don't really need to use sheet-workers for this, but sometimes you need to use Roll20's attribute sync feature to get the selected value into another input element. This also has the lovely advantage, that the selected tab is persisted across sessions...and the not-so-lovely disadvantage, that when GM and player are looking at the same sheet, they are always going to switch each other's tabs :D

In my sheet, I use these sheet attributes for the radio toggle, which Roll20 automatically syncs into all other fields with the same attribute tag. I use this to sync the value of the radio button into a hidden input field (.sheet-pageToggle) at the same HTML nesting depth as all the individual tab divs. Each of the tabs has its own class, e.g., .sheet-tab1, .sheet-tab2, etc. And then there's a CSS rule for each tab to hide them if they are not selected:

input.sheet-pageToggle:not([value="1"]) ~ .sheet-tab1 {
  display: none;
}
input.sheet-pageToggle:not([value="2"]) ~ .sheet-tab2 {
  display: none;
}

and so on...

In general, I borrowed a lot of ideas, like this one, from Kryx' D&D 5E Shaped sheet. If you prefer reading HTML+JS over Scala, take a look there for inspiration.

Although, I think that Scala is a lot easier to read and write, but it may have a bit of learning curve :D You can see the Scala code that generates that particular layout here. You can see how it just parametrises the HTML and CSS it generates by the id number of the tab via ${id} (which is just a string splice in Scala).

geoidesic commented 4 years ago

Ok.. so you’re dynamically generating your CSS also from Scala in order to provide labels for your radio buttons that are disguised as buttons?

On 26 Dec 2019, at 13:55, Lars Kroll notifications@github.com wrote:

The basic templates offered on the wiki are pretty awful :( and I couldn’t find anything about tabs on the Wiki. I don’t know Scala but I think your sheet is impressive.. pity I can’t read it. I’ve been trying to get going on building a sheet but making very little progress. It doesn’t seem to allow one to add JavaScript… so how did you manage to get tabs working? Is that via a service-worker?

Actually, the tabs are a wonderful cheat, that you can do in pure CSS. Basically the "links" to the tabs are actually a fancy radio button, and the show/hide property of the page they address is managed by selecting on the content value of the radio button. You don't really need to use sheet-workers for this, but sometimes you need to use Roll20's attribute sync feature to get the selected value into another input element. This also has the lovely advantage, that the selected tab is persisted across sessions...and the not-so-lovely disadvantage, that when GM and player are looking at the same sheet, they are always going to switch each other's tabs :D

In my sheet, I use these sheet attributes for the radio toggle, which Roll20 automatically syncs into all other fields with the same attribute tag. I use this to sync the value of the radio button into a hidden input field (.sheet-pageToggle) at the same HTML nesting depth as all the individual tab divs. Each of the tabs has its own class, e.g., .sheet-tab1, .sheet-tab2, etc. And then there's a CSS rule for each tab to hide them if they are not selected:

input.sheet-pageToggle:not([value="1"]) ~ .sheet-tab1 { display: none; } input.sheet-pageToggle:not([value="2"]) ~ .sheet-tab2 { display: none; } and so on...

In general, I borrowed a lot of ideas, like this one, from Kryx' D&D 5E Shaped sheet. If you prefer reading HTML+JS over Scala, take a look there https://github.com/Roll20/roll20-character-sheets/tree/master/5eShaped for inspiration.

Although, I think that Scala is a lot easier to read and write, but it may have a bit of learning curve :D You can see the Scala code that generates that particular layout here https://github.com/Bathtor/sheet-framework/blob/f5b373d23ac531f447530502c0b4d35c9a03ea7d/framework/jvm/src/main/scala/com/lkroll/roll20/sheet/tabbed/TabbedSheet.scala#L115-L123. You can see how it just parametrises the HTML and CSS it generates by the id number of the tab via ${id} (which is just a string splice in Scala).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Bathtor/EPCompendium/issues/27?email_source=notifications&email_token=ABDMKKYJ5YLFZWYIJIGKZGLQ2SLSTA5CNFSM4J6WY4G2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHVPG6A#issuecomment-569045880, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABDMKK6JIL6H7HHHIIUWFEDQ2SLSTANCNFSM4J6WY4GQ.

Bathtor commented 4 years ago

Ok.. so you’re dynamically generating your CSS also from Scala in order to provide labels for your radio buttons that are disguised as buttons?

Yup. Although calling this "dynamically" is a bit of an exaggeration. I use the Scala code to generate HTML and CSS, which I then upload to Roll20. So from Roll20's perspective, of course, all of this is just static.

I'm basically just abusing Scala as a templating engine, so I don't have to maintain repetitive HTML/CSS stuff, and I get some of the compiler's semantic analysis power to sanity-check the stuff I write, before I generate the markup from it. This usually saves a few testing round-trips to Roll20 when I'm developing, and in particular when I'm refactoring code later.

geoidesic commented 4 years ago

One thing I don’t get from the video is where you are doing the Macro import. When I click on the macro tab in Roll20, I don’t get that option. I can add a new macro, but there’s no import option. Any ideas?

Bathtor commented 4 years ago

One thing I don’t get from the video is where you are doing the Macro import. When I click on the macro tab in Roll20, I don’t get that option. I can add a new macro, but there’s no import option. Any ideas?

As I (also) pointed out in the description below the video, you need Roll20ES for that. Without it, you'll have to copy each macro manually from the markdown file instead.

geoidesic commented 4 years ago

Thanks for all the help so far – I’m making good progress!

Could you please show me your data structure for the compendium data? It’s not clear from the Scala for me. I’m wondering specifically about arrays vs. Objects and whether items should have a numerical id.

I’m looking at this structure currently:


Compendium: {
          gear: [
                {
                  name: 'Backpack',
                  cost: 5,
                  weight: 1,
                  notes: 'Capacity: 15kg'
                },
...
Thoughts?

> On 26 Dec 2019, at 15:26, Lars Kroll <notifications@github.com> wrote:
> 
> One thing I don’t get from the video is where you are doing the Macro import.
> When I click on the macro tab in Roll20, I don’t get that option. I can add a new macro, but there’s no import option.
> Any ideas?
> 
> As I (also) pointed out in the description below the video, you need Roll20ES <https://ssstormy.github.io/roll20-enhancement-suite/> for that. Without it, you'll have to copy each macro manually from the markdown file instead.
> 
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub <https://github.com/Bathtor/EPCompendium/issues/27?email_source=notifications&email_token=ABDMKKZGH4WM44ZETBXTZCTQ2SWIRA5CNFSM4J6WY4G2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHVSIQI#issuecomment-569058369>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ABDMKK67NSIDEBIYQTDIJHTQ2SWIRANCNFSM4J6WY4GQ>.
> 
Bathtor commented 4 years ago

Sure, the generated Javascript with JSON entries embedded for, for example, the "Weapons" group looks like this:

EPCompendium.addData(
    "6.0.0", // version number of the compendium
    "weapon", // item group
    [
        {
            "name":"Plasma Blade",
            "type":{"$type":"Blades"}, // the $type thingy is something my Scala JSON generator inserts to differentiate types from values...think of them as names for enum entries
            "descr":"Not really a sword, per se, the plasma sword is a sort of specialized plasma torch. A lengthened c-shaped framework above the handle uses a laser and magnetic coils to stabilize a “beam” of ionized, superheated gas (plasma). The open sides of the framework allow the “sword” to be used as a superheated cutting implement. Though dangerous to wield in melee, it is sometimes favored as a weapon against heavily armored exsurgents by some sentinels. Plasma swords are wielded using Blades skill.",
            "damage":{"dmgD10":2,"dmgConst":8,"dmgType":"Energy"},
            "effect":null,
            "ap":-8,
            "price":{"$type":"High"},
            "range":{"$type":"Melee"},
            "source":"Firewall"
        },
        // other weapons ...
    ]
);

For importing via sheet field, instead of via the script-loaded compendium library, the format for the same item looks like this:

{
    "$type":"Weapon",
    "value":{
        "name":"Plasma Blade",
        "type":{"$type":"Blades"},
        "descr":"Not really a sword, per se, the plasma sword is a sort of specialized plasma torch. A lengthened c-shaped framework above the handle uses a laser and magnetic coils to stabilize a “beam” of ionized, superheated gas (plasma). The open sides of the framework allow the “sword” to be used as a superheated cutting implement. Though dangerous to wield in melee, it is sometimes favored as a weapon against heavily armored exsurgents by some sentinels. Plasma swords are wielded using Blades skill.",
        "damage":{"dmgD10":2,"dmgConst":8,"dmgType":"Energy"},
        "effect":null,
        "ap":-8,
        "price":{"$type":"High"},
        "range":{"$type":"Melee"},
        "source":"Firewall"
    },
    "version":"6.0.0"
}

You can see that they essentially contain the same information, just the script version avoids some redundant repetitions of the item type and the version, to save some space.

The reason I always keep compendium versions with the items, is to make sure that they don't accidentally get loaded by an outdated script, which might not know all the fields and thus leave things in a partially imported, inconsistent state (or simply crash^^).

To answer your question: You can see that I use objects very heavily, and only use arrays where they make sense, for example when I really need a list of things, like passing multiple weapons at the same time to the indexer (that is what EPCompendium.addData basically does...it indexes all the loaded values so they become searchable and loadable).

About a numerical id...well...the question is, what you would like to do with it. If you have many very similar names for your items, but must differentiate them, then you may want to employ some kind of an id. It doesn't necessarily have to be numerical. For example, you could implement the full-text search, and it returns all the matches plus their ids in the chat, and when you want to import something you click on the item and it passes the id again to import script, so you can perform some kind of efficient lookup. That sounds lovely and that is what databases do, right? The problem here is: How do you make sure you keep those ids unique? You are writing JSON basically by hand, how are you going to make sure you never accidentally double apply an id? In a database, the management engine has an algorithm to ensure it only create unique ids, or if the user is supplying the id, then the engine will check that it's unique against its primary index. So you basically gotta do something similar. Either during loading, or (perhaps preferably) before publishing. For the EP Compendium I simply use names as ids, but I ensure during JSON generation that the names are at least unique within a group, since otherwise the items become inaccessible to users once loaded.

As for your proposed structure, the object I'm sure is fine, but I wouldn't recommend going with a single large compendium file. It will be very annoying to maintain as it grows in size and you are trying too add things and modify things in there. I'd go with a number of smaller files, each for a particular type of item, and then just write some quick and simple script that basically pastes all the entries together for publishing. As I said...I generate all the JSON from Scala (though the language doesn't really matter), because it makes it much easier for me to make schema changes later, or use the information in different ways. For example, I generate the code for all the macros, which I showed in the video, from the same code base, just using the item types and item ids from the data. It's much more flexible if you keep the data in a way that you can easily manipulate programmatically.