npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

zig-js

v1.6.15

Published

Embedding the ZIG client into your game is easy.

Downloads

1,799

Readme

zig-js

Embedding the ZIG client into your game is easy.

The library is available as an npm package. Install it and add it to your package.json using npm install --save zig-js. You can then import the library and access the zig functionality.

The examples in this document make heavy use of async/await to handle promises. await x(); y() is similar to x().then(() => y()). More information on async function on MDN.

Changelog

You can find an overview about recent changes here.

Embedding ZIG into your game

For a quick start on how to include the zig-js library in a game project using webpack, see our example project on github. The project also includes information on how to test your game integration locally.

Loading your game

Once the game has finished loading all assets and is ready to start, you can signal this by sending a gameLoaded message to the parent frame. To simplify things the ZIG client exposes a Messages object (of type GameMessageInterface). Only use the Zig.Client instance if the Zig.ready() promise resolves.

There are two game flow modes.

  • Single round game In this mode the game is controlled completely from the outside. You dont need to implement any game controls. This mode does not support things like re-buy or variable stake selection.

  • In-game purchase flow In this mode all controls are handled by the game itself. The game is responsible to show a play button and, if required, a variable stake selector. To enable this mode, you need to add purchaseInGame: true to the game settings defined in your outer.html file.

The supported game mode can be passed as a parameter to the gameLoaded call.

import {Zig} from "zig-js/zig/zig";

window.onload = async () => {
  // wait for your game to load
  await YourGame.loadAssets();

  // wait for Zig.Client to initialize. Only use Client after this
  await Zig.ready();

  // tell parent frame that the game finished loading
  const purchaseInGame = false;
  Zig.Client.Messages.gameLoaded(purchaseInGame);
};

Single round games

The flow for a single round game is described in this diagram.

Once the customer decides between a real game for money or a free demo game the parent frame sends a playGame or playDemoGame message back to the game. To listen for those events the Messages object exposes a registerGeneric method. Simply pass an object containing event handlers with the message types as keys.

Zig.Client.Messages.registerGeneric({
  playGame() {
    // the player would like to start a new game round.
    // call into your game code to begin a new round.
    YourGame.runGame();
  },

  playDemoGame() {
    // the player requested a demo ticket.
    // YourGame.runDemoGame()
  },
});

To buy a ticket, use the Zig.Client.buyTicket method. The method returns a Promise instance resolving to the ticket that was supplied by the backend system. This ticket includes all the information about the game you need to show to the customer.

interface Ticket {
    // Local id of the ticket
    // This id needs to be send back with a `settle` call.
    id: string;

    // Some identifying alphanumeric string that does not need to be
    // unique but should identify the ticket given other information like an
    // approximate time or customer number
    ticketNumber: string;

    // The amount of money the customer payed for this ticket.
    price: MoneyAmount;

    // The bet factor that was used when purchasing this ticket.
    betFactor: number;

    // The winning class of the ticket. Use this to extract the winnings
    // of this ticket. If the winnings are zero this was a loosing bet.
    winningClass: {
        winnings: MoneyAmount
    };

    // the decoded scenario object or undefined if the scenario
    // field could not be decoded. Basically `JSON.parse(atob(ticket.scenario))`
    decodedScenario?: any;

    // this field contains optional data from the integrating platform.
    // this can be used to add additional fields to the ticket payload, e.g. a
    // ticket id or ticket number which is valid in the integrating platform.
    customContent?: any;
}

interface MoneyAmount {
    amountInMinor: number;
    amountInMajor: number;
    currency: string;
}

After the customer plays the game, you might want to show a dialog containing the winnings for the purchased ticket. Once that dialog is closed by the user, you signal the end of the game round using gameFinished().

const YourGame = {
  async runGame() {
    // get the ticket
    const ticket = await Zig.Client.buyTicket();

    // show the progression + outcome to the customer
    await YourGame.play(ticket);

    // settle the ticket and add he winnings to the customers account
    await Zig.Client.settleTicket(ticket.id);

    // Show a dialog to the customers displaying the winnings
    await YourGame.showTicketWinnings(ticket);

    // tell the parent that the game has finish
    Zig.Client.Messages.gameFinished();
  },
};

In case of errors, you can use the error method on the Messages instance, to forward any value as an error object to the parent frame. The Zig.Client object will already handle errors for you, but you might want to wrap the call to your play method in a try/catch block like this. If you are using promises without await, you need to call .catch(...).

try {
  await YourGame.play(ticket);
} catch(err) {
  Zig.Client.interfaces.error(err);
  // YourGame.reset();
  return;
}

After sending an error to the parent frame you should always reset your game frontend. For more information see error handling section.

In-game start-button and variable stakes

If the game supports variable stakes and an in-game start-button, the order of operations slightly differs. You can see the complete game flow in this diagram.

First you need to tell the parent page that your game handles this so called in game purchase flow. You do this by passing true to the gameLoaded() call as described above.

// tell parent frame, that the game finished loading,
// and that we are running in 'in game purchase' mode.
const purchaseInGame = true;
Zig.Client.Messages.gameLoaded(purchaseInGame);

Once the player wishes to enter the game, the parent frame will send a prepareGame message containing a parameter that tells your game, if the player wishes to play a demo games or a series of real game. At this point, you'll show the play button and the stake selection, if you implement a variable stake game.

Zig.Client.Messages.registerGeneric({
  // [...]
  prepareGame(event) {
    // call your game to show/enable the stake selector.
    YourGame.showStakeSelector(event.demo);
  },
});

Once the player has selected the stake and you want the game to begin, the game needs to send a buy message containing the selected stake.

const YourGame = {
  selectedStake: 2,

  onStartGameClicked() {
    // request the parent to start the game with the given stake.
    Zig.Client.Messages.buy(YourGame.selectedStake);
  },
}

The integrating frame will validate the request, check the players balance, etc and call your game back with a normal playGame or playDemoGame message like in the single game round example above. You will not get the selected stake back in the message, so you need to hang onto the selected stake in your game while you are waiting for the game to start. In you playGame handler, you call the Zig.Client.buyTicket method with a second parameter containing the stake. The same is true for your playDemoGame handler:

await Zig.Client.buyTicket(null, {betFactor: YourGame.selectedStake})

After settling the ticket using settleTicket, you jump back to the stake selection screen without sending a gameFinished message. You only send a gameFinished message you want to leave your game using a special homescreen button.

Resume unplayed game In case that the user has an unplayed ticket, the integration will not call prepareGame but call playGame directly. In that case you can go ahead with requesting a ticket by calling Zig.Client.buyTicket without any extra paramters.

Cancel buy request After sending a buy message to the parent, the customer might choose to cancel the game or may not have enought money to play the game with the selected stake. In that case a cancelRequestStartGame will be send to the game. You can then show the stake selection screen again.

Zig.Client.Messages.registerGeneric({
  // [...]
  cancelRequestStartGame() {
    // call your game to show/enable the stake selector.
    YourGame.showStakeSelector();
  },
});

Error handling

In case of errors, you should delegate the error handling to the parent frame. The library will try to make sense of the error object and handle it appropriately. You should reset your game into the initial state after an error and expect a normal prepareGame or playGame message to start a new game round.

try {
  // ...
} catch(err) {
  Zig.Client.Messages.error(yourErrorObject);
  YourGame.reset();
}

Build and release this library

This part of the documentation is only relevant for developers of the zig client.

You can build the library using npm run shortcuts.

  • npm run release Will build a new stable release. This will be automatically used by all game frontends that include the library.

  • npm run beta Will release a beta build and push that as dev version to npm. While you are on a beta release, you can upload new versions without doing a real release.

  • npm run build-upload Uploads a new version into the dev channel, but only if you are currently on a beta release.