profectus-docs/assets/guide_recipes_save-progress.md.6956e9fc.js

23 lines
14 KiB
JavaScript
Raw Normal View History

import{_ as s,c as a,o as e,N as n}from"./chunks/framework.0799945b.js";const o="/assets/save-progress.2c9d1bae.png",u=JSON.parse('{"title":"Display Save Progress","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/save-progress.md","lastUpdated":1681388423000}'),t={name:"guide/recipes/save-progress.md"},l=n('<h1 id="display-save-progress" tabindex="-1">Display Save Progress <a class="header-anchor" href="#display-save-progress" aria-label="Permalink to &quot;Display Save Progress&quot;"></a></h1><p>This is a recipe to add a section to each save in the Saves Manager that will describe the amount of progress within that save. This can allow the player to more easily compare the saves to determine which is which. This would be in addition to the game version, last time played, and the name of the save itself, which can already be used for comparing saves without any configuration.</p><p><img src="'+o+`" alt="save progress display"></p><p>This recipe will involve modifying the <code>Save.vue</code> file within your project to include an extra component in the saves details. It will go over creating the new component, how to work with the save data object, and then displaying the component.</p><h2 id="creating-the-component" tabindex="-1">Creating the component <a class="header-anchor" href="#creating-the-component" aria-label="Permalink to &quot;Creating the component&quot;"></a></h2><p>Let&#39;s start with creating the coerced component. For this recipe we&#39;re going to make a couple assumptions about what this display should be. We&#39;ll assume the text will be more complex than displaying a single value. That is, at different stages of the game progress will be indicated by different metrics. We&#39;ll also assume it will be a single line of descriptive text - no images or anything else that would justify making a new .vue component. Breaking these assumptions is left as an exercise for the reader. But for now, with those assumptions in mind, we&#39;ll write our component (in the <code>&lt;script&gt;</code> tag in <code>Save.vue</code>) similar to this example:</p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> progressDisplay </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">computeComponent</span><span style="color:#A6ACCD;">(</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">computed</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">someCondition</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Just started</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">someOtherCondition</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">\`</span><span style="color:#C3E88D;">Early game; </span><span style="color:#89DDFF;">\${</span><span style="color:#82AAFF;">formatWhole</span><span style="color:#A6ACCD;">(someResourceValue)</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;"> resource name</span><span style="color:#89DDFF;">\`</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Unknown progress</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><p>This code will create a component that will simply render the returned text, and update as required. However, there&#39;s one significant complication in writing the code for these conditions and resource values: you&#39;re working with a potentially incomplete save data object.</p><h2 id="working-with-save-data" tabindex="-1">Working with save data <a class="header-anchor" href="#working-with-save-data" aria-label="Permalink to &quot;Working with save data&quot;"></a></h2><p>The save component is passed down a save data object, that works quite a bit differently than how most of your project accesses data. First off, you are typically working with the objects within a layer directly, but you can&#39;t here as you want the information from this specific save, not the currently loaded save. Structurally it&#39;ll be like the <code>player</code> object, where all computed values and non-persistent refs are stripped away, and refs are already unwrapped. However, unlike the <code>player</code> object, you don&#39;t know for certain any given property is there - saves can be corrupted or incomplete, or come from older versions of the game that simply had the data structured differently. You&#39;ll need to account for that appropriately.</p><p>For most cases (specifically where new game versions only added new data to the save data object, rather than change the meaning of existing data), you can use the <code>LayerData</code> type to get proper typing for a given layer. For example, a type safe check for whether a save has earned a milestone called &quot;nextSectionOfGame&quot; on a layer called &quot;main&quot; would look like this:</p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> ((save</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">?.</span><span style="color:#A6ACCD;">layers</span><span style="color:#89DDFF;">?.</span><span style="color:#A6ACCD;">main </span><span style="color:#89DDFF;font-style:italic;">as</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">LayerData</span><span style="color:#89DDFF;">&lt;typeof</span><span style="color:#A6ACCD;"> main</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">|</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">undefined</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">?.</span><span style="color:#A6ACCD;">nextSectionOfGame</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">earned </span><span style="color:#89DDFF;">??</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#A6ACCD;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Next section of game reached</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="displaying-the-component" tabindex="-1">Displaying the component <a class="header-anchor" href="#displaying-the-component" aria-label="Permalink to &quot;Displaying the component&quot;"></a></h2><p>The <code>Save.vue</code> template contains, amongst other things, an element that displays the details of the save. We&#39;ll be adding a new child within this element. You&#39;ll want to look near the bottom of the template for the element that looks like <code>&lt;div class=&quot;details&quot; v-if=&quot;save.error == undefined &amp;&amp; !isEditing&quot;&gt;</code>. Note that there are <em>two</em> divs with this CSS class, and we specifically want the one that&#39;s active when isEditing is <code>false</code>. You&#39;ll then want to add our new element inside this div, like so:</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">class</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">details</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">v-if</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">save.error == undefined &amp;&amp; !isEditing</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">class</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">button open</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">@click</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">emit(&#39;open&#39;)</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">h3</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">{{ save.name }}</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">h3</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">span</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">class</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">save-version</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">v{{ save.modVersion }}</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">span</span></span>
<span class="line"><span style="color:#89DDFF;"> &gt;&lt;</span><span style="color:#F07178;">br</span><span style="color:#89DDFF;"> /&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">v-if</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">currentTime</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">Last played {{ dateFormat.format(currentTime) }}</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">++ </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">v-if</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">progressDisplay</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;&lt;</span><span style="color:#F07178;">component</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">:is</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">progressDisplay</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> /&gt;&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span></code></pre></div><p>And there you have it! Your dev environment should now show the component in all its glory in the saves manager.</p>`,16),p=[l];function r(c,i,y,D,F,d){return e(),a("div",null,p)}const m=s(t,[["render",r]]);export{u as __pageData,m as default};