Skip to content

Commit

Permalink
Merge pull request #80 from Ladysnake/blabber-layout
Browse files Browse the repository at this point in the history
Add documentation and editor support for Blabber's custom layouts
  • Loading branch information
Pyrofab authored Oct 28, 2023
2 parents 7a9c47b + 631ab2f commit 2a67784
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 8 deletions.
8 changes: 5 additions & 3 deletions _sass/parts/details.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ details {
&:hover {
background-color: var(--accent-background-color);
}
}

h5, h6 {
font-size: inherit;
h5, h6 {
font-size: inherit;
margin-top: 1em;
margin-bottom: 1em;
}
}
}
10 changes: 10 additions & 0 deletions wiki/blabber/dialogue.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
"description": "A dialogue to be given to a player",
"type": "object",
"properties": {
"layout": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The type of layout used for the default screen",
"enum": ["blabber:classic", "blabber:rpg"]
}
}
},
"start_at": {
"description": "The entrypoint for this dialogue",
"type": "string"
Expand Down
18 changes: 18 additions & 0 deletions wiki/blabber/dialogue_generator/blabber-dialogue.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@
* @property {?DialogueAction} [action]
* @property {?DialogueChoice[]} [choices]
*/
/**
* @typedef {Object} DialogueLayout
* @property {?string} [type]
*/
/**
* @typedef {Object} DialogueData
* @property {?Object.<string, DialogueState>} [states]
* @property {?string} [start_at]
* @property {?boolean} [unskippable]
* @property {?DialogueLayout} [layout]
*/

export default class BlabberDialogue {
Expand Down Expand Up @@ -63,6 +68,19 @@ export default class BlabberDialogue {
return !!this.data.unskippable;
}

/**
*
* @param {string} [layout]
* @returns {?string}
*/
layout(layout) {
if (layout !== undefined) {
this.data.layout = {type: layout};
this.markDirty();
}
return this.data.layout?.type;
}

/**
* @returns {string[]}
*/
Expand Down
5 changes: 5 additions & 0 deletions wiki/blabber/dialogue_generator/dialogue-editing.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import BlabberDialogue from "./blabber-dialogue.js";
const exportButton = document.getElementById('dialogue-export');
const startInput = document.getElementById('dialogue-start-at');
const unskippableInput = document.getElementById('dialogue-unskippable');
const dialogueLayoutInputs = document.querySelectorAll('input[name=dialogue-layout]');
const choiceEditor = document.querySelector('.dialogue-choice-editor');
const stateList = document.getElementById('dialogue-state-list');

Expand All @@ -24,6 +25,9 @@ import BlabberDialogue from "./blabber-dialogue.js";
startInput.disabled = true;
startInput.addEventListener('change', e => dialogue.startAt(e.target.value));
unskippableInput.addEventListener('change', e => dialogue.unskippable(e.target.value));
dialogueLayoutInputs.forEach((e) => e.addEventListener('change', (ev) => {
dialogue.layout(document.querySelector('input[name=dialogue-layout]:checked').value);
}))

const textFormatSelect = document.getElementById('dialogue-text-format');

Expand Down Expand Up @@ -81,6 +85,7 @@ import BlabberDialogue from "./blabber-dialogue.js";
}

unskippableInput.checked = dialogue.unskippable();
dialogueLayoutInputs.forEach((e) => e.checked = e.value === dialogue.layout());
startInput.value = dialogue.startAt();
}

Expand Down
2 changes: 2 additions & 0 deletions wiki/blabber/dialogue_generator/dialogue-init.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import BlabberDialogue from "./blabber-dialogue.js";
e.preventDefault();

const unskippable = document.getElementById('dialogue-unskippable').checked;
const layout = document.querySelector('input[name=layout]:checked').value;
const textFormat = textFormatInputs.find((it) => it.checked)?.value;

if (![filenameField, startStateField, endStateField].every((e) => validateIdentifierField(e))) {
Expand All @@ -55,6 +56,7 @@ import BlabberDialogue from "./blabber-dialogue.js";
const startState = startStateField.value;
const endState = endStateField.value;
dialogue.filename = filenameField.value;
dialogue.layout(layout);
dialogue.unskippable(unskippable);
dialogue.startAt(startState);
dialogue.data.states = {
Expand Down
12 changes: 12 additions & 0 deletions wiki/blabber/dialogue_generator/dialogue.scss
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ input[type=text] {
}
}

.dialogue-layout-selection {
display: inline-flex;
flex-direction: row;
align-items: center;
padding-right: 1em;
gap: 0.2em;
label {
margin-bottom: 0;
margin-right: 2em;
}
}

& > * {
display: flex;
flex-direction: column;
Expand Down
11 changes: 10 additions & 1 deletion wiki/blabber/dialogue_generator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ <h3>Create a dialogue</h3>
</label>
</div>
<fieldset id="dialogue-text-format">
<legend>Which format should this editor use for texts? </legend>
<legend>Which format should this editor use for texts?</legend>
<span class="option">
<input id="literal-text" type="radio" name="text-format" value="literal"/><label for="literal-text"><span aria-hidden="true" class="icon">📃</span>Literal Text <i>(Easier for playing around)</i></label>
</span>
Expand All @@ -42,6 +42,15 @@ <h3>Create a dialogue</h3>
<input id="json-text" type="radio" name="text-format" value="json"/><label for="json-text"><span aria-hidden="true" class="icon">💻</span>Raw JSON <i>(See also <a href="https://minecraft.wiki/w/Raw_JSON_text_format">the wiki page {%include svg/external-link.svg%}</a>, or <a href="https://minecraft.tools/en/json_text.php">a generator {%include svg/external-link.svg%}</a>)</i></label>
</span>
</fieldset>
<fieldset>
<legend>What layout do you want your dialogue to use for regular states?</legend>
<span class="option">
<input id="layout-classic" type="radio" name="layout" value="blabber:classic" checked/><label for="layout-classic">Classic <i>(full screen, good for long texts)</i></label>
</span>
<span class="option">
<input id="layout-rpg" type="radio" name="layout" value="blabber:rpg"/><label for="layout-rpg">RPG <i>(reduced size, good for NPC dialogues with short choices)</i></label>
</span>
</fieldset>
<div class="option">
<input type="checkbox" id="dialogue-unskippable" checked/>
<label for="dialogue-unskippable">Can this dialogue be skipped? <i>(e.g. with the escape key)</i></label>
Expand Down
1 change: 1 addition & 0 deletions wiki/blabber/dialogue_generator/main-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ <h3>Global Properties</h3>
<div class="menu">
<!-- <label for="dialogue-filename-input">File name</label><input id="dialogue-filename-input" type="text"/>-->
<label for="dialogue-unskippable">Skippable?</label><span class="yes-no-container"><input type="checkbox" class="yes-no-input" id="dialogue-unskippable"/><label for="dialogue-unskippable" class="btn btn-xs btn-yes">{% include svg/checked-box.svg %} Yes</label><label for="dialogue-unskippable" class="btn btn-xs btn-no">{% include svg/unchecked-box.svg %} No</label></span>
<label>Layout</label><span class="dialogue-layout-selection"><input type="radio" id="dialogue-layout-classic" name="dialogue-layout" value="blabber:classic" checked/><label for="dialogue-layout-classic">Classic</label><input type="radio" id="dialogue-layout-rpg" name="dialogue-layout" value="blabber:rpg"/><label for="dialogue-layout-rpg">RPG</label></span>
<label for="dialogue-start-at">Starting state</label><select title="Starting state selector; requires at least one state to exist" id="dialogue-start-at"></select>
<label for="dialogue-text-format">Editor text format</label>
<span>
Expand Down
Binary file added wiki/blabber/example-dialogue-screen-rpg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 34 additions & 4 deletions wiki/blabber/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ Like that:

![Example Dialogue Screen](example-dialogue-screen.png){:.rounded}

Or like that:

![Example Alt Dialogue Screen](example-dialogue-screen-rpg.png){:.rounded}

You get to choose per-dialogue.

## How it works

### Commands
Expand Down Expand Up @@ -59,14 +65,32 @@ We can fix this by adding an action to the `end_success` state; a command action

Here's the JSON file corresponding to what we just described:

{% capture summary %}<h4 id="basic-dialogue-json">basic-dialogue.json</h4>{% endcapture %}
{% capture summary %}<h4 id="basic-dialogue-json" class="no_anchor">basic-dialogue.json</h4>{% endcapture %}
{% capture example_json %}
```json
{% include_relative basic-dialogue.json %}
```
{% endcapture %}
{% include details.liquid summary=summary content=example_json %}

#### Layout

As noted in [the previous section](#how-it-looks), you can choose if your dialogue uses the classic layout, or the RPG
layout (first and second screenshot, respectively).
The JSON looks like this (goes at the top level, replace `"blabber:classic"` with `"blabber:rpg"` for the alternative look):

{% capture summary %}<h5 id="simple-layout-json" class="no_anchor">Simple layout JSON</h5>{% endcapture %}
{% capture example_json %}
```json
{
"layout": {
"type": "blabber:classic"
}
}
```
{% endcapture %}
{% include details.liquid summary=summary content=example_json %}

#### Conditional choices

So what if you want to add requirements for specific dialogue paths? You could always make a separate dialogue file
Expand All @@ -92,7 +116,7 @@ Note that you should avoid the hidden option with choices that can enable or dis

Here is an example of conditional choices in JSON:

{% capture summary %}<h5 id="grayed-out-choice-json">Grayed out choice</h5>{% endcapture %}
{% capture summary %}<h5 id="grayed-out-choice-json" class="no_anchor">Grayed out choice JSON</h5>{% endcapture %}
{% capture example_json %}
```json
{
Expand All @@ -110,7 +134,7 @@ Here is an example of conditional choices in JSON:
```
{% endcapture %}
{% include details.liquid summary=summary content=example_json %}
{% capture summary %}<h5 id="hidden-choice-json">Hidden choice</h5>{% endcapture %}
{% capture summary %}<h5 id="hidden-choice-json" class="no_anchor">Hidden choice JSON</h5>{% endcapture %}
{% capture example_json %}
```json
{
Expand Down Expand Up @@ -288,12 +312,18 @@ and the latest CCA version in the [appropriate repository](https://github.com/On

### API

Everything is currently done with 2 methods:
The two most relevant methods are as follow:
- `Blabber#startDialogue(ServerPlayerEntity, Identifier)`: starts the dialogue with the given id for the given player
- `Blabber#registerAction`: registers an action for use in dialogues, 2 overloads available:
- `registerAction(Identifier, DialogueAction)`: registers a simple action that takes no additional configuration from the dialogue description file.
- `registerAction(Identifier, Codec<? extends DialogueAction)`: registers an action type. The codec is used to create new dialogue actions based on the action `value` specified in the dialogue description file.

#### Custom layouts

It is possible to register your own custom layout with its completely custom screen by calling `BlabberScreenRegistry#register`
in your client entrypoint. The API is however marked unstable, as the layout system is susceptible to being refactored to allow arbitrary data being passed to the screen
(contributions welcome).

### JSON Schema

The schema for Blabber dialogue files is available here: [dialogue.schema.json](dialogue.schema.json)

0 comments on commit 2a67784

Please sign in to comment.