Results 1 to 9 of 9

Thread: Spawning Dynamic Deck With JSON - spawnObjectJSON()

  1. #1

    Question Spawning Dynamic Deck With JSON - spawnObjectJSON()

    Hi,

    I'm looking to use a web API to build a deck based on a URL entered into a UI input field. The API would return JSON containing a list of all the card face image URLs. Each image URL would be a single image.

    What I'm having trouble with is understanding how to spawn a deck of cards using spawnObjectJSON(). I looked at the documentation (https://api.tabletopsimulator.com/base/#spawnobjectjson). But, it didn't seem to have everything I needed.

    Are there any examples showing how to use spawnObjectJSON() in a similar way that I'm trying to do?

    Thanks,

    Ray

  2. #2
    As far as I can tell, spawnObjectJSON() uses the same json as the normal save system in tabletop simulator. This gives a lot more control over object spawning than the regular spawnObject(), at the cost of being slightly more complex to use.

    If you want to find out the proper format for a particular item, all you should need to do is save the item normally and open the json file. Here's an example for a combined deck using cards from three separate custom decks, which should be roughly what you need:

    Code:
    {
      "Name": "Deck",
      "Transform": {
    	"posX": 3.05444169,
    	"posY": 1.3547008,
    	"posZ": 29.8444023,
    	"rotX": 1.18271551E-07,
    	"rotY": 180.0,
    	"rotZ": 180.0,
    	"scaleX": 1.0,
    	"scaleY": 1.0,
    	"scaleZ": 1.0
      },
      "Nickname": "",
      "Description": "",
      "ColorDiffuse": {
    	"r": 0.713235259,
    	"g": 0.713235259,
    	"b": 0.713235259
      },
      "Locked": false,
      "Grid": true,
      "Snap": true,
      "IgnoreFoW": false,
      "Autoraise": true,
      "Sticky": true,
      "Tooltip": true,
      "GridProjection": false,
      "HideWhenFaceDown": true,
      "Hands": false,
      "SidewaysCard": false,
      "DeckIDs": [
    	100,
    	101,
    	2552,
    	2553,
    	2806,
    	2803
      ],
      "CustomDeck": {
    	"1": {
    	  "FaceURL": "https://i.imgur.com/AO64Y0s.jpg",
    	  "BackURL": "https://i.imgur.com/iYOc0fK.jpg",
    	  "NumWidth": 10,
    	  "NumHeight": 7,
    	  "BackIsHidden": false,
    	  "UniqueBack": false
    	},
    	"25": {
    	  "FaceURL": "http://i.imgur.com/ezTuMn9.jpg",
    	  "BackURL": "http://i.imgur.com/ztdLG0J.jpg",
    	  "NumWidth": 10,
    	  "NumHeight": 7,
    	  "BackIsHidden": false,
    	  "UniqueBack": false
    	},
    	"28": {
    	  "FaceURL": "http://i.imgur.com/ERqjcC4.jpg",
    	  "BackURL": "http://i.imgur.com/FGgRaFo.jpg",
    	  "NumWidth": 10,
    	  "NumHeight": 7,
    	  "BackIsHidden": false,
    	  "UniqueBack": false
    	}
      },
      "XmlUI": "",
      "LuaScript": "",
      "LuaScriptState": "",
      "ContainedObjects": [
    	{
    	  "Name": "Card",
    	  "Transform": {
    		"posX": 3.054374,
    		"posY": 1.34333086,
    		"posZ": 29.8444862,
    		"rotX": 359.99176,
    		"rotY": 179.9994,
    		"rotZ": -0.00251165754,
    		"scaleX": 1.0,
    		"scaleY": 1.0,
    		"scaleZ": 1.0
    	  },
    	  "Nickname": "Joker",
    	  "Description": "Bee Deck by WolfieAD",
    	  "ColorDiffuse": {
    		"r": 0.713235259,
    		"g": 0.713235259,
    		"b": 0.713235259
    	  },
    	  "Locked": false,
    	  "Grid": true,
    	  "Snap": true,
    	  "IgnoreFoW": false,
    	  "Autoraise": true,
    	  "Sticky": true,
    	  "Tooltip": true,
    	  "GridProjection": false,
    	  "HideWhenFaceDown": true,
    	  "Hands": true,
    	  "CardID": 100,
    	  "SidewaysCard": false,
    	  "CustomDeck": {
    		"1": {
    		  "FaceURL": "https://i.imgur.com/AO64Y0s.jpg",
    		  "BackURL": "https://i.imgur.com/iYOc0fK.jpg",
    		  "NumWidth": 10,
    		  "NumHeight": 7,
    		  "BackIsHidden": false,
    		  "UniqueBack": false
    		}
    	  },
    	  "XmlUI": "",
    	  "LuaScript": "",
    	  "LuaScriptState": "",
    	  "GUID": "8fe0e1"
    	},
    	{
    	  "Name": "Card",
    	  "Transform": {
    		"posX": 2.91222978,
    		"posY": 1.48913145,
    		"posZ": 30.0354462,
    		"rotX": 359.827118,
    		"rotY": 180.0025,
    		"rotZ": 359.721161,
    		"scaleX": 1.0,
    		"scaleY": 1.0,
    		"scaleZ": 1.0
    	  },
    	  "Nickname": "Joker",
    	  "Description": "Bee Deck by WolfieAD",
    	  "ColorDiffuse": {
    		"r": 0.713235259,
    		"g": 0.713235259,
    		"b": 0.713235259
    	  },
    	  "Locked": false,
    	  "Grid": true,
    	  "Snap": true,
    	  "IgnoreFoW": false,
    	  "Autoraise": true,
    	  "Sticky": true,
    	  "Tooltip": true,
    	  "GridProjection": false,
    	  "HideWhenFaceDown": true,
    	  "Hands": true,
    	  "CardID": 101,
    	  "SidewaysCard": false,
    	  "CustomDeck": {
    		"1": {
    		  "FaceURL": "https://i.imgur.com/AO64Y0s.jpg",
    		  "BackURL": "https://i.imgur.com/iYOc0fK.jpg",
    		  "NumWidth": 10,
    		  "NumHeight": 7,
    		  "BackIsHidden": false,
    		  "UniqueBack": false
    		}
    	  },
    	  "XmlUI": "",
    	  "LuaScript": "",
    	  "LuaScriptState": "",
    	  "GUID": "8dbb26"
    	},
    	{
    	  "Name": "Card",
    	  "Transform": {
    		"posX": 2.974755,
    		"posY": 1.50762165,
    		"posZ": 29.58145,
    		"rotX": 0.009934531,
    		"rotY": 0.0007355382,
    		"rotZ": 359.971924,
    		"scaleX": 1.0,
    		"scaleY": 1.0,
    		"scaleZ": 1.0
    	  },
    	  "Nickname": "Joker",
    	  "Description": "timCopwell's Designed Deck",
    	  "ColorDiffuse": {
    		"r": 0.713246942,
    		"g": 0.713246942,
    		"b": 0.713246942
    	  },
    	  "Locked": false,
    	  "Grid": true,
    	  "Snap": true,
    	  "IgnoreFoW": false,
    	  "Autoraise": true,
    	  "Sticky": true,
    	  "Tooltip": true,
    	  "GridProjection": false,
    	  "HideWhenFaceDown": true,
    	  "Hands": true,
    	  "CardID": 2552,
    	  "SidewaysCard": false,
    	  "CustomDeck": {
    		"25": {
    		  "FaceURL": "http://i.imgur.com/ezTuMn9.jpg",
    		  "BackURL": "http://i.imgur.com/ztdLG0J.jpg",
    		  "NumWidth": 10,
    		  "NumHeight": 7,
    		  "BackIsHidden": false,
    		  "UniqueBack": false
    		}
    	  },
    	  "XmlUI": "",
    	  "LuaScript": "",
    	  "LuaScriptState": "",
    	  "GUID": "666d3e"
    	},
    	{
    	  "Name": "Card",
    	  "Transform": {
    		"posX": 2.768989,
    		"posY": 1.48170149,
    		"posZ": 29.4517937,
    		"rotX": -0.0018954993,
    		"rotY": 0.0132661238,
    		"rotZ": 358.8727,
    		"scaleX": 1.0,
    		"scaleY": 1.0,
    		"scaleZ": 1.0
    	  },
    	  "Nickname": "Joker",
    	  "Description": "timCopwell's Designed Deck",
    	  "ColorDiffuse": {
    		"r": 0.713246942,
    		"g": 0.713246942,
    		"b": 0.713246942
    	  },
    	  "Locked": false,
    	  "Grid": true,
    	  "Snap": true,
    	  "IgnoreFoW": false,
    	  "Autoraise": true,
    	  "Sticky": true,
    	  "Tooltip": true,
    	  "GridProjection": false,
    	  "HideWhenFaceDown": true,
    	  "Hands": true,
    	  "CardID": 2553,
    	  "SidewaysCard": false,
    	  "CustomDeck": {
    		"25": {
    		  "FaceURL": "http://i.imgur.com/ezTuMn9.jpg",
    		  "BackURL": "http://i.imgur.com/ztdLG0J.jpg",
    		  "NumWidth": 10,
    		  "NumHeight": 7,
    		  "BackIsHidden": false,
    		  "UniqueBack": false
    		}
    	  },
    	  "XmlUI": "",
    	  "LuaScript": "",
    	  "LuaScriptState": "",
    	  "GUID": "ce7b00"
    	},
    	{
    	  "Name": "Card",
    	  "Transform": {
    		"posX": 3.13249063,
    		"posY": 1.49252927,
    		"posZ": 29.74459,
    		"rotX": 0.002566977,
    		"rotY": 180.0028,
    		"rotZ": 0.0165499058,
    		"scaleX": 1.0,
    		"scaleY": 1.0,
    		"scaleZ": 1.0
    	  },
    	  "Nickname": "Ace",
    	  "Description": "Shovel Knight Playing Cards by MAX_STONE_1",
    	  "ColorDiffuse": {
    		"r": 0.713235259,
    		"g": 0.713235259,
    		"b": 0.713235259
    	  },
    	  "Locked": false,
    	  "Grid": true,
    	  "Snap": true,
    	  "IgnoreFoW": false,
    	  "Autoraise": true,
    	  "Sticky": true,
    	  "Tooltip": true,
    	  "GridProjection": false,
    	  "HideWhenFaceDown": true,
    	  "Hands": true,
    	  "CardID": 2806,
    	  "SidewaysCard": false,
    	  "CustomDeck": {
    		"28": {
    		  "FaceURL": "http://i.imgur.com/ERqjcC4.jpg",
    		  "BackURL": "http://i.imgur.com/FGgRaFo.jpg",
    		  "NumWidth": 10,
    		  "NumHeight": 7,
    		  "BackIsHidden": false,
    		  "UniqueBack": false
    		}
    	  },
    	  "XmlUI": "",
    	  "LuaScript": "",
    	  "LuaScriptState": "",
    	  "GUID": "65a019"
    	},
    	{
    	  "Name": "Card",
    	  "Transform": {
    		"posX": 3.00983286,
    		"posY": 1.5173701,
    		"posZ": 30.1534061,
    		"rotX": 0.000438606163,
    		"rotY": 179.989929,
    		"rotZ": 358.898041,
    		"scaleX": 1.0,
    		"scaleY": 1.0,
    		"scaleZ": 1.0
    	  },
    	  "Nickname": "Ace",
    	  "Description": "Shovel Knight Playing Cards by MAX_STONE_1",
    	  "ColorDiffuse": {
    		"r": 0.713235259,
    		"g": 0.713235259,
    		"b": 0.713235259
    	  },
    	  "Locked": false,
    	  "Grid": true,
    	  "Snap": true,
    	  "IgnoreFoW": false,
    	  "Autoraise": true,
    	  "Sticky": true,
    	  "Tooltip": true,
    	  "GridProjection": false,
    	  "HideWhenFaceDown": true,
    	  "Hands": true,
    	  "CardID": 2803,
    	  "SidewaysCard": false,
    	  "CustomDeck": {
    		"28": {
    		  "FaceURL": "http://i.imgur.com/ERqjcC4.jpg",
    		  "BackURL": "http://i.imgur.com/FGgRaFo.jpg",
    		  "NumWidth": 10,
    		  "NumHeight": 7,
    		  "BackIsHidden": false,
    		  "UniqueBack": false
    		}
    	  },
    	  "XmlUI": "",
    	  "LuaScript": "",
    	  "LuaScriptState": "",
    	  "GUID": "d0b8f7"
    	}
      ],
      "GUID": "eddad3"
    }
    The deck itself seems to have a `DeckIDs` entry referencing the individual cards in the deck and a `CustomDeck` entry with data for each custom deck used. These might be redundant though, since each individual card in `ContainedObjects` also has that data. You'll have to test that.

    Since you have an individual image for each card, you'll likely want to set `NumWidth` and `NumHeight` to 1. I'm guessing `CardID` refers to the place in the grid the card would appear (eg 1 would be first card, 2 second card and so on, wrapping around to the start when it runs out of cards). You'll have to experiment with that.

  3. #3
    I've been through this and made https://github.com/tjakubo2/Decker exactly for that purpose - it's a (fairly thin) wrapper on spawnObjectJSON that lets you create cards and decks from image links and spawn them. Feel free to take a look.

  4. #4
    my_hat_stinks:

    Thanks for the suggestion. I didn't realize there were so many possible options for a deck.

    dzikakulka:

    I did see your Decker library. I wasn't sure if it was going to be supported going forward--should there be changes in Tabletop Simulator. It looks fairly straightforward to use.

  5. #5
    Quote Originally Posted by dzikakulka View Post
    I've been through this and made https://github.com/tjakubo2/Decker exactly for that purpose - it's a (fairly thin) wrapper on spawnObjectJSON that lets you create cards and decks from image links and spawn them. Feel free to take a look.
    I ended up using your library. Works like a charm. The one thing I can't figure out is how to give a card a name. They just have numbers associated with them when I search the deck.

  6. #6
    @RayH

    If you're creating single Card objects and aggregating them into a deck later, you can pass a table of parameters, including name, to its creation like
    Code:
    local card = Decker.Card(asset, row, col, {name = 'Some Name', desc = 'Some Description'})
    -- after spawning, card will have "Some Name" name and "Some Description" description
    
    -- you can do the same after card is created (and before it's spawned) like
    card:setCommon({name = 'Some Name', desc = 'Some Description'})
    -- same method applies to decks (setting its own properties, not of cards inside it)
    if you're starting out with a Deck object and want to name cards inside it, you should be able to do so like
    Code:
    local deck = Decker.AssetDeck(asset, num) -- or however you obtain the deck
    
    -- we can't directly modify stuff inside the deck, so lets get a copy of card from it, 3rd card here
    local card = deck.cardAt(3)
    card:setCommon({name = 'Some Name', desc = 'Some Description'})
    -- and we insert it into the deck from where it was copied, removing the old one first
    deck:remove(3):insert(card, 3)
    You can see what keys you can set in that table with name/desc here: https://github.com/tjakubo2/Decker#common-params-table
    If you set a key that's not present in this list, it is set directly in the resulting card/deck JSON, in case you wanted to change something more "advanced"

  7. #7
    Quote Originally Posted by dzikakulka View Post
    Code:
    card:setCommon({name = 'Some Name', desc = 'Some Description'})
    This is what I needed. Glad it was simple. Maybe it's me, but after making this deck loader in Lua, the simple things seem difficult. Part of that might be the TTS API. Like creating a input with createInput() and not being able to reference that input without looping though them all with getInputs(). Lack of trim() or split() in Lua.

    I appreciate your assistance and the time you took to make the Decker library.

    One more thing. I'm using #include Decker and have the Decker.ttslua file in my /Users/rayh/Documents/Tabletop Simulator folder. But, if I want to give this to someone else or put in the steam workshop, do I need to embed the Decker code with mine?

  8. #8
    Lua aims to have very minimal set of built in functions (often called "batteries not included"), but existing facilities make standard stuff like trim (with str:match), split (with str:gmatch) or interpolation (with str:gsub) easy once you get the hang of how it works. It's definitely a steeper entry than Python for example if you can't just grab some convenience library though.

    TTS API definitely often gets in the way. It's getting better with time, but there's still a lot of clunky parts, we juts have to live with it I guess.

    As far as "#include" goes (which is an Atom plugin feature), it basically inserts the file in your code before sending to TTS, and then folds it back up in one statement when you load scripts. You can just upload the save file using it and the "real" code on your save will have anything you #include'd embedded in it. So you can go ahead and just upload stuff with it no problem

  9. #9
    Great, I do notice that it merges the code. I got it uploaded to the Workshop. Now I'll see if breaks when other people try it.

    Thanks for the help.

Similar Threads

  1. JSON.decode a large JSON string takes forever
    By Xorbis in forum Scripting Bug Reports
    Replies: 6
    Last Post: 07-21-2019, 04:46 PM
  2. Replies: 9
    Last Post: 08-18-2018, 01:35 AM
  3. Help out an Amatuer?: Dynamic Buttons
    By Quto in forum Scripting
    Replies: 4
    Last Post: 12-08-2017, 06:50 PM
  4. Spawning a single card for an updated deck?
    By MarcusRaven in forum General Discussion
    Replies: 0
    Last Post: 07-02-2017, 07:45 AM
  5. Dynamic button oddities
    By GiantDwarf in forum Scripting
    Replies: 1
    Last Post: 04-26-2017, 08:15 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •