<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.3">Jekyll</generator><link href="https://jerryhuang.eu.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jerryhuang.eu.org/" rel="alternate" type="text/html" /><updated>2025-05-29T14:55:36+00:00</updated><id>https://jerryhuang.eu.org/feed.xml</id><title type="html">JerryHuang Blog</title><subtitle>随缘更新</subtitle><entry><title type="html">PGMMVJH的SteamworksApi文档集成调用文档</title><link href="https://jerryhuang.eu.org/2025/02/14/PGMMVJH%E7%9A%84SteamworksApi%E6%96%87%E6%A1%A3%E9%9B%86%E6%88%90%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3.html" rel="alternate" type="text/html" title="PGMMVJH的SteamworksApi文档集成调用文档" /><published>2025-02-14T16:00:00+00:00</published><updated>2025-02-14T16:00:00+00:00</updated><id>https://jerryhuang.eu.org/2025/02/14/PGMMVJH%E7%9A%84SteamworksApi%E6%96%87%E6%A1%A3%E9%9B%86%E6%88%90%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3</id><content type="html" xml:base="https://jerryhuang.eu.org/2025/02/14/PGMMVJH%E7%9A%84SteamworksApi%E6%96%87%E6%A1%A3%E9%9B%86%E6%88%90%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3.html"><![CDATA[<h1 id="pgmmvjh的steamworksapi文档集成调用文档">PGMMVJH的SteamworksApi文档集成调用文档</h1>

<p>本文档介绍了如何在JavaScript中调用Steam API。所有的Steam API方法都通过<code class="language-plaintext highlighter-rouge">Agtk.steam</code>对象进行访问，具体调用实例和参数说明如下。
具体的内容需要去看 <a href="https://partner.steamgames.com/doc/sdk/api?l=schinese#initialization_and_shutdown">Steamworks API 概览</a></p>

<hr />

<h2 id="方法调用">方法调用</h2>

<h3 id="agtksteamsteamapi_restarappifnecessarysteamappid"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamapi_restarappifnecessary(steamAppId)</code></h3>

<p>此方法用于检查Steam应用是否需要重新启动。（不推荐使用）</p>

<p><strong>参数</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">steamAppId</code> (Number): Steam应用的ID。</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Boolean</code>: 如果需要重新启动，返回<code class="language-plaintext highlighter-rouge">true</code>，否则返回<code class="language-plaintext highlighter-rouge">false</code>。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">steamAppId</span> <span class="o">=</span> <span class="mi">2692950</span><span class="p">;</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]steam初始化情况：</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamapi_restarappifnecessary</span><span class="p">(</span><span class="nx">steamAppId</span><span class="p">));</span>  <span class="c1">// 输出: true 或 false</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamapi_init"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamapi_init()</code></h3>

<p>此方法用于初始化Steam API。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li>无</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Boolean</code>: 返回<code class="language-plaintext highlighter-rouge">true</code>表示初始化成功，<code class="language-plaintext highlighter-rouge">false</code>表示初始化失败。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamapi_init</span><span class="p">();</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]steam初始化情况：</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">result</span><span class="p">);</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamapi_shutdown"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamapi_shutdown()</code></h3>

<p>此方法用于关闭Steam API。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li>无</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li>无</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamapi_shutdown</span><span class="p">();</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Steam API 已关闭</span><span class="dl">"</span><span class="p">);</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamuserstats_storestats"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamuserstats_storestats()</code></h3>

<p>此方法用于保存Steam用户的统计信息。
每次调用完成就解锁或者重置成就后需要调用这个。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li>无</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Boolean</code>: 返回<code class="language-plaintext highlighter-rouge">true</code>表示成功保存统计信息，<code class="language-plaintext highlighter-rouge">false</code>表示保存失败。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_storestats</span><span class="p">();</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>  <span class="c1">// 输出: true 或 false</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamfriends_getsteamusername"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamfriends_getsteamusername()</code></h3>

<p>此方法用于获取当前Steam用户的用户名。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li>无</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">String</code>: 当前Steam用户名。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">username</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamfriends_getsteamusername</span><span class="p">();</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]当前steam用户名:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">username</span><span class="p">);</span>  <span class="c1">// 输出: 当前Steam用户名</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamuserstats_getachievementstateachievementname"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamuserstats_getachievementstate(achievementName)</code></h3>

<p>检查一个成就是否已经解锁。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">achievementName</code> (String): 要检查的成就名称。</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Boolean</code>: 返回<code class="language-plaintext highlighter-rouge">true</code>表示已解锁成就，<code class="language-plaintext highlighter-rouge">false</code>表示未解锁。</li>
  <li>失败时：返回 null（例如 Steam 未初始化或用户未登录）。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]准备获取成就状态</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">achievementName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">NEW_ACHIEVEMENT_1_3</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">achievementstate</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_getachievementstate</span><span class="p">(</span><span class="nx">achievementName</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">achievementstate</span><span class="p">){</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]成就:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"> 状态:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementstate</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]成就:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"> 获取失败 请检查</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamuserstats_unlockedachievementachievementname"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamuserstats_unlockedachievement(achievementName)</code></h3>

<p>此方法用于解锁指定的Steam成就。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">achievementName</code> (String): 要解锁的成就名称。</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Boolean</code>: 返回<code class="language-plaintext highlighter-rouge">true</code>表示成功解锁成就，<code class="language-plaintext highlighter-rouge">false</code>表示解锁失败。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]准备解锁成就</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">achievementName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">NEW_ACHIEVEMENT_1_3</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">unlockResult</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_unlockedachievement</span><span class="p">(</span><span class="nx">achievementName</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">unlockResult</span> <span class="o">&amp;&amp;</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_storestats</span><span class="p">()){</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]解锁成就</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">成功</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]解锁成就</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">失败</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamuserstats_resetachievementachievementname"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamuserstats_resetachievement(achievementName)</code></h3>

<p>此方法用于重置指定的Steam成就。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">achievementName</code> (String): 要重置的成就名称。</li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Boolean</code>: 返回<code class="language-plaintext highlighter-rouge">true</code>表示成功重置成就，<code class="language-plaintext highlighter-rouge">false</code>表示重置失败。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]准备重置成就</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">achievementName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">NEW_ACHIEVEMENT_1_3</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">unlockResult</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_resetachievement</span><span class="p">(</span><span class="nx">achievementName</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">unlockResult</span> <span class="o">&amp;&amp;</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_storestats</span><span class="p">()){</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]重置成就</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">成功</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]重置成就</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">失败</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamuserstats_getachievements"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamuserstats_getachievements()</code></h3>

<p>获取所有的成就数组。</p>

<p><strong>参数</strong>:</p>
<ul>
  <li>无</li>
</ul>

<p><strong>返回值</strong>:
-成功时：返回一个成就数组，每个成就对象的结构如下：</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">interface</span> <span class="nx">Achievement</span> <span class="p">{</span>
  <span class="nl">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>      <span class="c1">// 成就名称</span>
  <span class="nl">unlocked</span><span class="p">:</span> <span class="nx">boolean</span><span class="p">;</span> <span class="c1">// 成就是否已解锁</span>
<span class="p">}</span>
</code></pre></div></div>
<p>失败时：返回 null（例如 Steam 未初始化或用户未登录）。</p>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]尝试获取所有成就信息</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">steamAchievements</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_getachievements</span><span class="p">();</span>

<span class="k">if </span><span class="p">(</span><span class="nx">steamAchievements</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]当前成就数量</span><span class="dl">"</span><span class="o">+</span><span class="nx">steamAchievements</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
  <span class="k">for </span><span class="p">(</span><span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">steamAchievements</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]Achievement: </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">steamAchievements</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">name</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">Status:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">steamAchievements</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">unlocked</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h3 id="agtksteamsteamuserstats_resetallstats"><code class="language-plaintext highlighter-rouge">Agtk.steam.steamuserstats_resetallstats()</code></h3>

<p>重置所有用户信息</p>

<p><strong>参数</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">resetAchievements</code> (Boolean) : 是否同时重置用户的成就。</li>
  <li>
    <ul>
      <li>如果为 true，则重置所有统计数据 并 重置成就。</li>
    </ul>
  </li>
  <li>
    <ul>
      <li>如果为 false，则仅重置统计数据，成就保持不变。</li>
    </ul>
  </li>
</ul>

<p><strong>返回值</strong>:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Boolean</code>: 返回<code class="language-plaintext highlighter-rouge">true</code>表示成功重置，<code class="language-plaintext highlighter-rouge">false</code>表示重置失败。</li>
</ul>

<p><strong>调用示例</strong>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]尝试获取所有成就信息</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">resetallstatsResult</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_resetallstats</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]重置所有成就信息：</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">resetallstatsResult</span><span class="p">);</span>
</code></pre></div></div>

<hr />

<h2 id="总结">总结</h2>

<p>以上方法通过<code class="language-plaintext highlighter-rouge">Agtk.steam</code>对象进行调用，可以轻松地实现Steam API的各项功能。调用时，请确保传入正确的参数，并根据返回值判断操作是否成功。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[PGMMVJH的SteamworksApi文档集成调用文档]]></summary></entry><entry><title type="html">关于PGMMVJH的SteamWorksApi支持</title><link href="https://jerryhuang.eu.org/2025/02/14/%E5%85%B3%E4%BA%8EPGMMVJH%E7%9A%84SteamWorks-api%E6%94%AF%E6%8C%81.html" rel="alternate" type="text/html" title="关于PGMMVJH的SteamWorksApi支持" /><published>2025-02-14T16:00:00+00:00</published><updated>2025-02-14T16:00:00+00:00</updated><id>https://jerryhuang.eu.org/2025/02/14/%E5%85%B3%E4%BA%8EPGMMVJH%E7%9A%84SteamWorks%20api%E6%94%AF%E6%8C%81</id><content type="html" xml:base="https://jerryhuang.eu.org/2025/02/14/%E5%85%B3%E4%BA%8EPGMMVJH%E7%9A%84SteamWorks-api%E6%94%AF%E6%8C%81.html"><![CDATA[<h1 id="关于pgmmvjh的steamworksapi支持">关于PGMMVJH的SteamWorksApi支持</h1>

<p>这个<code class="language-plaintext highlighter-rouge">Pixel Game Maker MV Player Open Source Edition JHVersion</code>是根据<code class="language-plaintext highlighter-rouge">Pixel Game Maker MV Player Open Source Edition</code>修改而来的版本，该版本添加了成就相关的Steamworks API的jsb绑定支持.</p>

<h2 id="下载替换">下载替换</h2>

<p>编译好的版本下载 <a href="https://github.com/VintageGameBoy/PGMMVJH/releases">PGMMVJH/releases</a></p>
<ul>
  <li>解压下载的<code class="language-plaintext highlighter-rouge">PGMMVJH.zip</code>压缩包</li>
  <li>打开<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>安装目录，使用<code class="language-plaintext highlighter-rouge">player-win</code>文件夹替换<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>安装目录中的<code class="language-plaintext highlighter-rouge">player-win</code>文件夹。</li>
  <li>检查<code class="language-plaintext highlighter-rouge">player-win</code>文件夹中的<code class="language-plaintext highlighter-rouge">steam_appid.txt</code>，修改为需要调试的游戏id，没有可以填<code class="language-plaintext highlighter-rouge">480</code>用于测试</li>
  <li>打开<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>安装目录的<code class="language-plaintext highlighter-rouge">resource</code>文件夹，使用<code class="language-plaintext highlighter-rouge">debugMenuRuntime.zip</code>和<code class="language-plaintext highlighter-rouge">runtime.zip</code>文件替换官方的文件</li>
</ul>

<blockquote>
  <p>480是官方案例中用于测试的游戏id</p>
</blockquote>

<h2 id="使用steamworks-js-api">使用Steamworks js Api</h2>
<p>所有api均在<code class="language-plaintext highlighter-rouge">Agtk.steam</code>对象下，详情请看github中的调用文档<a href="https://github.com/VintageGameBoy/PGMMVJH/tree/main/Player/doc/JHVersion/SteamInterfaceDesc.md">SteamInterfaceDesc</a></p>

<h3 id="初始化">初始化</h3>
<p>在<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>对象面板创建一个新的对象或者使用现有对象，添加其他运行动作。
选择执行脚本，填入下面的JS代码。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 查看您的可执行文件是否通过 Steam 启动 (可以忽略这一步)</span>
<span class="kd">var</span> <span class="nx">steamAppId</span> <span class="o">=</span> <span class="mi">2692950</span><span class="p">;</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]steam初始化情况：</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamapi_restarappifnecessary</span><span class="p">(</span><span class="nx">steamAppId</span><span class="p">));</span>  <span class="c1">// 输出: true 或 false</span>
<span class="c1">// 执行初始化</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamapi_init</span><span class="p">();</span>
<span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]steam初始化情况：</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">result</span><span class="p">);</span>
</code></pre></div></div>
<h3 id="触发成就解锁">触发成就解锁</h3>
<p>和上一步步骤相同，使用下面的JS代码。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]准备解锁成就</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">achievementName</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">NEW_ACHIEVEMENT_1_3</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">unlockResult</span> <span class="o">=</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_unlockedachievement</span><span class="p">(</span><span class="nx">achievementName</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">unlockResult</span> <span class="o">&amp;&amp;</span> <span class="nx">Agtk</span><span class="p">.</span><span class="nx">steam</span><span class="p">.</span><span class="nf">steamuserstats_storestats</span><span class="p">()){</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]解锁成就</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">成功</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
  <span class="nx">Agtk</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">[STEAM]解锁成就</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">achievementName</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">失败</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="使用调试参数单独进行调试">使用调试参数单独进行调试</h3>

<ul>
  <li>在steam中找到<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>的安装目录</li>
  <li>选择在安装目录下的<code class="language-plaintext highlighter-rouge">player-win</code>文件夹中的<code class="language-plaintext highlighter-rouge">player.exe</code>创建桌面快捷方式</li>
  <li>找到项目的目录下的<code class="language-plaintext highlighter-rouge">test.json</code>文件例如<code class="language-plaintext highlighter-rouge">C:/Users/Jerry/Documents/PGMMV/Project2/data/test.json</code></li>
  <li>现在修改刚刚创建的快捷方式属性中的目标属性如下所示
    <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"I:</span><span class="se">\S</span><span class="s2">teamLibrary</span><span class="se">\s</span><span class="s2">teamapps</span><span class="se">\c</span><span class="s2">ommon</span><span class="se">\P</span><span class="s2">ixel Game Maker</span><span class="se">\p</span><span class="s2">layer-win</span><span class="se">\p</span><span class="s2">layer.exe"</span> 0 C:/Users/Jerry/Documents/PGMMV/Project2/data/test.json zh_CN 0
</code></pre></div>    </div>
    <blockquote>
      <p>该方式可以脱离<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>调试Steamworks api<br />
每次有修改需要在<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>中点击<code class="language-plaintext highlighter-rouge">试玩游戏(F5)</code>等待<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>试玩窗口打开后关闭再启动快捷方式才能使用最新修改调试<br />
<strong>本方式仅为调试Steamworks api的无奈之举，直接在<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>中使用<code class="language-plaintext highlighter-rouge">试玩游戏(F5)</code>无法测试<code class="language-plaintext highlighter-rouge">Steamworks api</code></strong></p>
    </blockquote>
  </li>
</ul>

<h2 id="编译指南">编译指南</h2>

<p>拉取github中的代码 <a href="https://github.com/VintageGameBoy">JHPGMMV</a>
下载<a href="https://partner.steamgames.com/downloads/steamworks_sdk_161.zip">SteamWorks SDK</a></p>

<ul>
  <li>把压缩包解压后的<code class="language-plaintext highlighter-rouge">sdk/public/steam</code>复制到项目的<code class="language-plaintext highlighter-rouge">Player/Classes/External</code>目录</li>
  <li>把压缩包解压后的<code class="language-plaintext highlighter-rouge">sdk/redistrbutable_bin</code>复制到项目的<code class="language-plaintext highlighter-rouge">Player/Classes/External/steam</code>目录</li>
  <li>在项目的<code class="language-plaintext highlighter-rouge">Player/Classes/External/steam</code>下创建<code class="language-plaintext highlighter-rouge">steam_appid.txt</code>文件</li>
  <li>修改上一步创建的<code class="language-plaintext highlighter-rouge">steam_appid.txt</code>文件，填入你的steam游戏ID，没有可以填<code class="language-plaintext highlighter-rouge">480</code>用于测试</li>
</ul>

<blockquote>
  <p>480是官方案例中用于测试的游戏id<br />
SteamworksSDK访问协议<a href="https://partner.steamgames.com/documentation/sdk_access_agreement">Steamworks SDK Access Agreement</a><br />
更多版本的下载链接<a href="https://partner.steamgames.com/downloads/list">steamworks sdk downloads list</a></p>
</blockquote>

<p>打开<code class="language-plaintext highlighter-rouge">install</code>目录，使用<code class="language-plaintext highlighter-rouge">build_player_buildCache.bat</code>编译，成功后会在同目录下创建三个文件夹<code class="language-plaintext highlighter-rouge">player</code>、<code class="language-plaintext highlighter-rouge">debugMenuRuntime</code>、<code class="language-plaintext highlighter-rouge">runtime</code><br />
按照官方说明，替换编辑器中的文件夹.</p>

<h3 id="编译文件替换官方版本playerexe">编译文件替换官方版本player.exe</h3>

<ul>
  <li>打开<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>安装目录，使用<code class="language-plaintext highlighter-rouge">player</code>文件夹里面的内容替换<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>安装目录<code class="language-plaintext highlighter-rouge">player-win</code>中的内容。</li>
  <li>分别压缩上一步编译生成的<code class="language-plaintext highlighter-rouge">debugMenuRuntime</code>和<code class="language-plaintext highlighter-rouge">runtime</code>目录生成<code class="language-plaintext highlighter-rouge">debugMenuRuntime.zip</code>和<code class="language-plaintext highlighter-rouge">runtime.zip</code>文件</li>
  <li>打开<code class="language-plaintext highlighter-rouge">Pixel Game Maker</code>安装目录的<code class="language-plaintext highlighter-rouge">resource</code>文件夹，使用<code class="language-plaintext highlighter-rouge">debugMenuRuntime.zip</code>和<code class="language-plaintext highlighter-rouge">runtime.zip</code>文件替换官方的文件</li>
</ul>

<h2 id="项目的由来">项目的由来</h2>
<p>vueko花钱让我做一个pgmmv的成就系统，我制作了两套方案，其中一套经过商量决定开源。</p>

<p>购买游戏支持vueko <a href="https://store.steampowered.com/app/2692950">Welcome to Planet E1d0r4d0!</a></p>

<p>我的discord <a href="https://discord.gg/HPvHwXUVFt">discord</a></p>]]></content><author><name></name></author><summary type="html"><![CDATA[关于PGMMVJH的SteamWorksApi支持]]></summary></entry><entry><title type="html">C/C++头文件的保护</title><link href="https://jerryhuang.eu.org/2024/11/21/C%E5%A4%B4%E6%96%87%E4%BB%B6%E4%BF%9D%E6%8A%A4.html" rel="alternate" type="text/html" title="C/C++头文件的保护" /><published>2024-11-21T16:00:00+00:00</published><updated>2024-11-21T16:00:00+00:00</updated><id>https://jerryhuang.eu.org/2024/11/21/C%E5%A4%B4%E6%96%87%E4%BB%B6%E4%BF%9D%E6%8A%A4</id><content type="html" xml:base="https://jerryhuang.eu.org/2024/11/21/C%E5%A4%B4%E6%96%87%E4%BB%B6%E4%BF%9D%E6%8A%A4.html"><![CDATA[<h1 id="头文件的保护">头文件的保护</h1>

<h2 id="头文件防止重复引用">头文件防止重复引用</h2>
<p>#include指令的原理是复制一份文件到这个文件中，不可避免的，如果有多个头文件互相#include会导致重复声明的问题，所以需要一种方法来避免重复声明的问题。
在C++中有两种方式防止重复引用头文件 分别是：</p>
<h3 id="pragma-once预编译指令">#pragma once预编译指令</h3>
<p>这个指令可以防止#include指令重复复制同一个头文件到最终文件中。
使用方法很简单，只需要在头文件的前面添加<code class="language-plaintext highlighter-rouge">#pragma once</code></p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#pragma once
</span>
<span class="kt">void</span> <span class="nf">Log</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">message</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">InitLog</span><span class="p">();</span>
<span class="k">struct</span> <span class="nc">Player</span> <span class="p">{};</span>
</code></pre></div></div>

<h3 id="ifndef指令">#ifndef指令</h3>
<p>使用#ifndef指令判断一个标识符是否被声明，如果声明就不执行代码块中的代码。
这个防止重复引用的方法通常存在于老的代码中。</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifndef _LOG_H
#define _LOG_H
</span>
<span class="kt">void</span> <span class="nf">Log</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">message</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">InitLog</span><span class="p">();</span>
<span class="k">struct</span> <span class="nc">Player</span> <span class="p">{};</span>
<span class="cp">#endif _LOG_H
</span>
<span class="cp">#ifndef _LOG_H
</span><span class="c1">// 因为上面已经定义了_LOG_H</span>
<span class="c1">// 所以下面的代码不会声明</span>
<span class="cp">#define _LOG_H
</span><span class="kt">void</span> <span class="nf">Log</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">message</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">InitLog</span><span class="p">();</span>
<span class="k">struct</span> <span class="nc">Player</span> <span class="p">{};</span>
<span class="cp">#endif _LOG_H
</span></code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[头文件的保护]]></summary></entry><entry><title type="html">C语言保留字</title><link href="https://jerryhuang.eu.org/2024/11/21/C%E8%AF%AD%E8%A8%80%E4%BF%9D%E7%95%99%E5%AD%97.html" rel="alternate" type="text/html" title="C语言保留字" /><published>2024-11-21T16:00:00+00:00</published><updated>2024-11-21T16:00:00+00:00</updated><id>https://jerryhuang.eu.org/2024/11/21/C%E8%AF%AD%E8%A8%80%E4%BF%9D%E7%95%99%E5%AD%97</id><content type="html" xml:base="https://jerryhuang.eu.org/2024/11/21/C%E8%AF%AD%E8%A8%80%E4%BF%9D%E7%95%99%E5%AD%97.html"><![CDATA[<h1 id="c语言保留字">C语言保留字</h1>
<p>其实这篇文章没啥看头的，是网上搜的随手粘贴汇总</p>

<p>1999年12月16日，ISO推出了C99标准，该标准新增了5个C语言关键字：
<code class="language-plaintext highlighter-rouge">inline</code>| <code class="language-plaintext highlighter-rouge">restrict</code>| <code class="language-plaintext highlighter-rouge">_Bool</code> |<code class="language-plaintext highlighter-rouge">_Complex</code>| <code class="language-plaintext highlighter-rouge">_Imaginary</code>（注意bool 从来不是C语言的关键字）</p>

<p>2011年12月8日，ISO发布C语言的新标准C11，该标准新增了7个C语言关键字：
<code class="language-plaintext highlighter-rouge">_Alignas</code>| <code class="language-plaintext highlighter-rouge">_Alignof</code>| <code class="language-plaintext highlighter-rouge">_Atomic</code>| <code class="language-plaintext highlighter-rouge">_Static_assert</code>| <code class="language-plaintext highlighter-rouge">_Noreturn</code>| <code class="language-plaintext highlighter-rouge">_Thread</code>| <code class="language-plaintext highlighter-rouge">_local</code>| <code class="language-plaintext highlighter-rouge">_Generic</code></p>

<h2 id="原关键字">原关键字</h2>

<table>
  <thead>
    <tr>
      <th>保留字</th>
      <th>作用</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>auto</td>
      <td>指定变量的存储类型，是默认值</td>
    </tr>
    <tr>
      <td>break</td>
      <td>跳出循环或switch语句</td>
    </tr>
    <tr>
      <td>case</td>
      <td>定义switch中的case子句</td>
    </tr>
    <tr>
      <td>char</td>
      <td>定义字符型变量或指针</td>
    </tr>
    <tr>
      <td>const</td>
      <td>定义常量或参数</td>
    </tr>
    <tr>
      <td>continue</td>
      <td>在循环语句中，回到循环体的开始处重新执行循环</td>
    </tr>
    <tr>
      <td>default</td>
      <td>定义switch中的default子句</td>
    </tr>
    <tr>
      <td>do</td>
      <td>定义do-while语句</td>
    </tr>
    <tr>
      <td>double</td>
      <td>定义双精度浮点数变量</td>
    </tr>
    <tr>
      <td>else</td>
      <td>定义枚举类型</td>
    </tr>
    <tr>
      <td>enum</td>
      <td>声明外部变量或函数</td>
    </tr>
    <tr>
      <td>extern</td>
      <td>声明外部变量或函数</td>
    </tr>
    <tr>
      <td>float</td>
      <td>定义浮点型变量或指针</td>
    </tr>
    <tr>
      <td>for</td>
      <td>定义for语句</td>
    </tr>
    <tr>
      <td>goto</td>
      <td>定义goto语句</td>
    </tr>
    <tr>
      <td>if</td>
      <td>定义if语句或if-else语句</td>
    </tr>
    <tr>
      <td>int</td>
      <td>定义整型变量或指针</td>
    </tr>
    <tr>
      <td>long</td>
      <td>定义长整型变量或指针</td>
    </tr>
    <tr>
      <td>register</td>
      <td>指定变量的存储类型是寄存器变量，Turbo c中用自动变量代替</td>
    </tr>
    <tr>
      <td>return</td>
      <td>从函数返回</td>
    </tr>
    <tr>
      <td>short</td>
      <td>定义短整型变量或指针</td>
    </tr>
    <tr>
      <td>signed</td>
      <td>定义有符号的整型变量或指针</td>
    </tr>
    <tr>
      <td>sizeof</td>
      <td>获取某种类型的变量或数据所占内存的大小，是运算符</td>
    </tr>
    <tr>
      <td>static</td>
      <td>指定变量的存储类型是静态变量，或指定函数是静态函数</td>
    </tr>
    <tr>
      <td>struct</td>
      <td>定义结构体类型</td>
    </tr>
    <tr>
      <td>switch</td>
      <td>定义switch语句</td>
    </tr>
    <tr>
      <td>typedef</td>
      <td>为数据类型定义别名</td>
    </tr>
    <tr>
      <td>union</td>
      <td>定义无符号的整型或字符型变量或指针</td>
    </tr>
    <tr>
      <td>unsigned</td>
      <td>定义无符号的整型变量或数据</td>
    </tr>
    <tr>
      <td>void</td>
      <td>定义空类型变量或空类型指针，或指定函数没有返回值</td>
    </tr>
    <tr>
      <td>volatile</td>
      <td>变量的值可能在程序的外部被改变</td>
    </tr>
    <tr>
      <td>while</td>
      <td>定义while或do-while语句</td>
    </tr>
  </tbody>
</table>

<h2 id="c99新增关键字">c99新增关键字</h2>

<p><code class="language-plaintext highlighter-rouge">_Bool</code>：布尔类型
以前的c中的bool都是程序员自己定义的。
#define bool _Bool
#define false 0
#define true 1
_Bool大小为1byte</p>

<p><code class="language-plaintext highlighter-rouge">_Complex</code>：复数类型
float _Complex、double _Complex、long double _Complex
float _Complex fCex = 1.0f + 1.0if; //实数 虚数 一起赋值
实部的获取crealf，虚部的获取cimagf</p>

<p><code class="language-plaintext highlighter-rouge">_Imaginary</code>：虚数类型
float _Imaginary、double _Imaginary、long double _Imaginary
因为_Complex(复数类型)里面已经包含虚数了，所以部分编译器都只实现了_Complex(复数类型)而没有实现_Imaginary(虚数类型)。</p>

<p><code class="language-plaintext highlighter-rouge">inline</code>：内联
编译器接受建议的话，会在调用处展开内联函数，减少跳转、换页操作，提高效率。
适合简单函数。不能定义可改变的static变量。</p>

<p><code class="language-plaintext highlighter-rouge">restrict</code>：限定指针
只用于限定指针；该关键字用于告知编译器，所有修改该指针所指向内容的操作全部都是基于(base on)该指针的，即不存在其它进行修改操作的途径；这样的后果是帮助编译器进行更好的代码优化，生成更有效率的汇编代码。</p>

<h2 id="c11-新增关键字">C11 新增关键字</h2>
<p><code class="language-plaintext highlighter-rouge">_Alignas</code>：内存对齐指示符
以前往往通过编译器的编译参数指定内存对齐方式。</p>

<p><code class="language-plaintext highlighter-rouge">_Alignof</code>：对齐处理操作符
函数 aligned_alloc()，以及 头文件 <stdalign.h>。
对齐内存有利于提高程序运行效率，内存访问效率。
alignof(Foo) //值为4，对齐长度
sizeof(Foo) //结构体的总大小：12</stdalign.h></p>

<p><code class="language-plaintext highlighter-rouge">_Atomic</code>：原子操作
_Atomic int i; //原子类型的变量
atomic_store(&amp;i,12); //stdatomic.h中的宏</p>

<p><code class="language-plaintext highlighter-rouge">_Generic</code>:泛型
_Generic((var), type1:…, type2: …, ……, default:…)
#define GENERAL_ABS(x) _Generic((x),int:abs,float:fabsf,double:fabs)(x) 根据类型不同调用不同的函数，类似函数模板。</p>

<p><code class="language-plaintext highlighter-rouge">_Noreturn</code>：指定该函数不返回到其调用点。
_Static_assert：静态断言
在编译时刻进行，断言表达式必须是在编译时期可以计算的表达式</p>

<p><code class="language-plaintext highlighter-rouge">_Thread_local</code>：限定了变量不能在多线程之间共享</p>]]></content><author><name></name></author><summary type="html"><![CDATA[C语言保留字 其实这篇文章没啥看头的，是网上搜的随手粘贴汇总]]></summary></entry><entry><title type="html">Nginx配置acme自动更新ssl证书</title><link href="https://jerryhuang.eu.org/2024/11/21/Nginx%E9%85%8D%E7%BD%AEacme%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0ssl%E8%AF%81%E4%B9%A6.html" rel="alternate" type="text/html" title="Nginx配置acme自动更新ssl证书" /><published>2024-11-21T16:00:00+00:00</published><updated>2024-11-21T16:00:00+00:00</updated><id>https://jerryhuang.eu.org/2024/11/21/Nginx%E9%85%8D%E7%BD%AEacme%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0ssl%E8%AF%81%E4%B9%A6</id><content type="html" xml:base="https://jerryhuang.eu.org/2024/11/21/Nginx%E9%85%8D%E7%BD%AEacme%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0ssl%E8%AF%81%E4%B9%A6.html"><![CDATA[<h1 id="nginx配置acme自动更新ssl证书">Nginx配置acme自动更新ssl证书</h1>
<p>参考了这些链接的内容</p>

<p><a href="https://cloud.tencent.com/developer/article/2335528">使用acme.sh 更新ssl证书</a></p>

<p><a href="https://github.com/acmesh-official/acme.sh/wiki/说明">acme.sh官方wiki文档</a></p>

<p><a href="https://zhuanlan.zhihu.com/p/266494063">知乎acme.sh 说明</a></p>

<p>2024年3月份的时候亚信调整了ssl的规则，所以不再使用腾讯云签发的免费证书，改用acme.sh自动更新脚本
<a href="https://letsencrypt.org/zh-cn/getting-started/">Let’s Encrypt官方</a>
下面记录一下过程</p>

<h2 id="安装">安装</h2>
<p>先安装。</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 安装并使用自己的邮箱</span>
curl https://get.acme.sh | sh <span class="nt">-s</span> <span class="nv">email</span><span class="o">=</span>jerryhuang@outlook.jp
<span class="c"># 或者用wget</span>
wget https://get.acme.sh | sh <span class="nt">-s</span> <span class="nv">email</span><span class="o">=</span>jerryhuang@outlook.jp
</code></pre></div></div>
<p>已安装的就更新</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--upgrade</span>
</code></pre></div></div>

<p>添加自动更新</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--upgrade</span> <span class="nt">--auto-upgrade</span>
</code></pre></div></div>

<h2 id="配置腾讯云">配置腾讯云</h2>
<p>我们使用dns的验证方式，需要添加一个子用户。
先转到<code class="language-plaintext highlighter-rouge">访问管理</code>选择<code class="language-plaintext highlighter-rouge">策略</code>
添加一个策略，用于更新域名dns。</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="p">{</span><span class="w">
            </span><span class="nl">"action"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                </span><span class="s2">"dnspod:DescribeRecordFilterList"</span><span class="p">,</span><span class="w">
                </span><span class="s2">"dnspod:DescribeRecordList"</span><span class="p">,</span><span class="w">
                </span><span class="s2">"dnspod:CreateRecord"</span><span class="p">,</span><span class="w">
                </span><span class="s2">"dnspod:DeleteRecord"</span><span class="w">
            </span><span class="p">],</span><span class="w">
            </span><span class="nl">"effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"allow"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"resource"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                </span><span class="s2">"*"</span><span class="w">
            </span><span class="p">]</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.0"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>创建一个只编程方式访问的子用户，然后添加刚刚创建的策略。
记录保存 SecretId 和 SecretKey。</p>

<h2 id="申请证书">申请证书</h2>
<p>将获取到的 SecretId 和 SecretKey 导入环境变量中，以便 acme.sh 调用。</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">Tencent_SecretId</span><span class="o">=</span><span class="s2">"&lt;Your SecretId&gt;"</span>
<span class="nb">export </span><span class="nv">Tencent_SecretKey</span><span class="o">=</span><span class="s2">"&lt;Your SecretKey&gt;"</span>
</code></pre></div></div>
<blockquote>
  <p>记得这个不要泄露！</p>
</blockquote>

<p>然后用came申请证书，例如：</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--issue</span> <span class="nt">--dns</span> dns_tencent <span class="nt">-d</span> example.com <span class="nt">-d</span> <span class="k">*</span>.example.com
</code></pre></div></div>
<p>出现网络问题的可以尝试添加<code class="language-plaintext highlighter-rouge"> --server letsencrypt</code></p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--server</span> letsencrypt <span class="nt">--issue</span> <span class="nt">--dns</span> dns_tencent <span class="nt">-d</span> example.com <span class="nt">-d</span> <span class="k">*</span>.example.com
</code></pre></div></div>
<p>运行后，acme.sh 将自动为您的域名申请证书，并将证书文件保存在~/.acme.sh/example.com/目录下，并且会自动为您的域名配置证书自动续期任务，无需手动续期。</p>
<blockquote>
  <p>现在默认生成ECDSA加密的证书，想生成兼容性更好的rsa需要使用<code class="language-plaintext highlighter-rouge">--keylength 2048</code></p>
</blockquote>

<h2 id="设置证书路径和自动重载nginx">设置证书路径和自动重载Nginx</h2>
<p>不要直接访问acme.sh的路径，得把文件复制输出到一个地方并且重启nginx</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--install-cert</span> <span class="nt">-d</span> example.com <span class="se">\</span>
<span class="nt">--key-file</span>       /www/wwwroot/acme_cert/example.com.key  <span class="se">\</span>
<span class="nt">--fullchain-file</span> /www/wwwroot/acme_cert/example.cer <span class="se">\</span>
<span class="nt">--reloadcmd</span>     <span class="s2">"/etc/init.d/nginx reload"</span>
</code></pre></div></div>
<blockquote>
  <p>(一个小提醒, 这里用的是 <code class="language-plaintext highlighter-rouge">service nginx force-reload</code>, 不是 <code class="language-plaintext highlighter-rouge">service nginx reload</code>, 据测试, reload 并不会重新加载证书, 所以用的 force-reload)
宝塔安装的可能要用<code class="language-plaintext highlighter-rouge">/etc/init.d/nginx restart</code>或<code class="language-plaintext highlighter-rouge">/etc/init.d/nginx reload</code>
Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer ，而非 <code class="language-plaintext highlighter-rouge">/etc/nginx/ssl/&lt;domain&gt;.cer</code> ，否则 SSL Labs 的测试会报 Chain issues Incomplete 错误。
–install-cert命令可以携带很多参数, 来指定目标文件. 并且可以指定 reloadcmd, 当证书更新以后, reloadcmd会被自动调用,让服务器生效.
详细参数请参考: https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc
值得注意的是, 这里指定的所有参数都会被自动记录下来, 并在将来证书自动更新以后, 被再次自动调用.</p>
</blockquote>

<h3 id="查看已安装证书信息">查看已安装证书信息</h3>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--info</span> <span class="nt">-d</span> example.com
</code></pre></div></div>

<h3 id="遇到timeout之类的问题">遇到timeout之类的问题</h3>
<p>遇到timeout需要使用网络代理来处理更新。
<a href="https://github.com/acmesh-official/acme.sh/issues/3842">切换服务器的命令</a></p>

<h2 id="杂项">杂项</h2>

<p>关闭自动更新</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--upgrade</span> <span class="nt">--auto-upgrade</span>  0
</code></pre></div></div>

<p>出错查看日志</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--issue</span>  .....  <span class="nt">--debug</span>
</code></pre></div></div>
<p>或者</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh <span class="nt">--issue</span>  .....  <span class="nt">--debug</span>  2
</code></pre></div></div>

<p>检查linux环境变量</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="nv">$Tencent_SecretId</span>
<span class="nb">echo</span> <span class="nv">$Tencent_SecretKey</span>
</code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[Nginx配置acme自动更新ssl证书 参考了这些链接的内容]]></summary></entry><entry><title type="html">C#容易忽视的拆装箱问题</title><link href="https://jerryhuang.eu.org/2024/04/22/C-%E5%AE%B9%E6%98%93%E5%BF%BD%E8%A7%86%E7%9A%84%E6%8B%86%E8%A3%85%E7%AE%B1%E9%97%AE%E9%A2%98.html" rel="alternate" type="text/html" title="C#容易忽视的拆装箱问题" /><published>2024-04-22T16:00:00+00:00</published><updated>2024-04-22T16:00:00+00:00</updated><id>https://jerryhuang.eu.org/2024/04/22/C#%E5%AE%B9%E6%98%93%E5%BF%BD%E8%A7%86%E7%9A%84%E6%8B%86%E8%A3%85%E7%AE%B1%E9%97%AE%E9%A2%98</id><content type="html" xml:base="https://jerryhuang.eu.org/2024/04/22/C-%E5%AE%B9%E6%98%93%E5%BF%BD%E8%A7%86%E7%9A%84%E6%8B%86%E8%A3%85%E7%AE%B1%E9%97%AE%E9%A2%98.html"><![CDATA[<h1 id="c容易忽视的拆装箱问题">C#容易忽视的拆装箱问题</h1>
<p>在值类型的拆装箱中，有些问题容易被忽视</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">interface</span> <span class="nc">IAngle</span>
<span class="p">{</span>
    <span class="k">void</span> <span class="nf">MoveTo</span><span class="p">(</span><span class="kt">int</span> <span class="n">degress</span><span class="p">,</span> <span class="kt">int</span> <span class="n">minutes</span><span class="p">,</span> <span class="kt">int</span> <span class="n">seconds</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">struct</span> <span class="nc">Angle</span> <span class="p">:</span> <span class="n">IAngle</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="kt">int</span> <span class="n">_Degress</span><span class="p">;</span>
    <span class="k">private</span> <span class="kt">int</span> <span class="n">_Minutes</span><span class="p">;</span>
    <span class="k">private</span> <span class="kt">int</span> <span class="n">_Seconds</span><span class="p">;</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">MoveTo</span><span class="p">(</span><span class="kt">int</span> <span class="n">degress</span><span class="p">,</span> <span class="kt">int</span> <span class="n">minutes</span><span class="p">,</span> <span class="kt">int</span> <span class="n">seconds</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">_Degress</span> <span class="p">=</span> <span class="n">degress</span><span class="p">;</span>
        <span class="n">_Minutes</span> <span class="p">=</span> <span class="n">minutes</span><span class="p">;</span>
        <span class="n">_Seconds</span> <span class="p">=</span> <span class="n">seconds</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">override</span> <span class="kt">string</span> <span class="nf">ToString</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">return</span> <span class="n">_Degress</span><span class="p">.</span><span class="nf">ToString</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
    <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Angle</span> <span class="n">angle</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Angle</span><span class="p">();</span>
        <span class="n">angle</span><span class="p">.</span><span class="nf">MoveTo</span><span class="p">(</span><span class="m">25</span><span class="p">,</span> <span class="m">30</span><span class="p">,</span> <span class="m">88</span><span class="p">);</span>
        <span class="c1">//#Expamle 1</span>
        <span class="kt">object</span> <span class="n">objectangle</span> <span class="p">=</span> <span class="n">angle</span><span class="p">;</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(((</span><span class="n">Angle</span><span class="p">)</span><span class="n">objectangle</span><span class="p">).</span><span class="nf">ToString</span><span class="p">());</span>

        <span class="c1">//#Expamle 2</span>
        <span class="p">((</span><span class="n">Angle</span><span class="p">)</span><span class="n">objectangle</span><span class="p">).</span><span class="nf">MoveTo</span><span class="p">(</span><span class="m">28</span><span class="p">,</span> <span class="m">30</span><span class="p">,</span> <span class="m">88</span><span class="p">);</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(((</span><span class="n">Angle</span><span class="p">)</span><span class="n">objectangle</span><span class="p">).</span><span class="nf">ToString</span><span class="p">());</span>

        <span class="c1">//#Expamle 3</span>
        <span class="p">((</span><span class="n">IAngle</span><span class="p">)</span><span class="n">angle</span><span class="p">).</span><span class="nf">MoveTo</span><span class="p">(</span><span class="m">28</span><span class="p">,</span> <span class="m">30</span><span class="p">,</span> <span class="m">88</span><span class="p">);</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(((</span><span class="n">IAngle</span><span class="p">)</span><span class="n">angle</span><span class="p">).</span><span class="nf">ToString</span><span class="p">());</span>

        <span class="c1">//#Expamle 4</span>
        <span class="p">((</span><span class="n">IAngle</span><span class="p">)</span><span class="n">objectangle</span><span class="p">).</span><span class="nf">MoveTo</span><span class="p">(</span><span class="m">28</span><span class="p">,</span> <span class="m">30</span><span class="p">,</span> <span class="m">88</span><span class="p">);</span>
        <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(((</span><span class="n">Angle</span><span class="p">)</span><span class="n">objectangle</span><span class="p">).</span><span class="nf">ToString</span><span class="p">());</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Print:</span>
<span class="c1">// 25</span>
<span class="c1">// 25</span>
<span class="c1">// 25</span>
<span class="c1">// 28</span>
</code></pre></div></div>
<p>在上面的代码中 使用IAngle接口创建了Angle结构，然后在Main函数中使实例化使用了Angle中的方法三次
最后代码输出的结果让人疑惑</p>

<p>在Expamle1中装箱了Angle类型的实例为 object
然后在Console.WriteLine里产生了拆箱操作，此时输出的是obj的副本</p>

<p>Expamle2里使用了拆箱，产生了拷贝，然后调用了拷贝的值里面的方法
原有的objectangle并未被修改，被修改的是拆箱操作时候创建的值拷贝，运行完后已经被抛弃(赋值给_)</p>

<p>Expamle3里产生了装箱操作，也产生了拷贝</p>

<p>Expamle4里强制转换是向引用类型转换，不会产生拷贝，输出了预期的结果</p>

<p>具体查看下图</p>

<p><img src="/image/20240423/405945010549.png" alt="405945010549.png" /></p>]]></content><author><name></name></author><summary type="html"><![CDATA[C#容易忽视的拆装箱问题 在值类型的拆装箱中，有些问题容易被忽视 interface IAngle { void MoveTo(int degress, int minutes, int seconds); } struct Angle : IAngle { private int _Degress; private int _Minutes; private int _Seconds; public void MoveTo(int degress, int minutes, int seconds) { _Degress = degress; _Minutes = minutes; _Seconds = seconds; } public override string ToString() { return _Degress.ToString(); } } class Program { static void Main() { Angle angle = new Angle(); angle.MoveTo(25, 30, 88); //#Expamle 1 object objectangle = angle; Console.WriteLine(((Angle)objectangle).ToString()); //#Expamle 2 ((Angle)objectangle).MoveTo(28, 30, 88); Console.WriteLine(((Angle)objectangle).ToString()); //#Expamle 3 ((IAngle)angle).MoveTo(28, 30, 88); Console.WriteLine(((IAngle)angle).ToString()); //#Expamle 4 ((IAngle)objectangle).MoveTo(28, 30, 88); Console.WriteLine(((Angle)objectangle).ToString()); } } // Print: // 25 // 25 // 25 // 28 在上面的代码中 使用IAngle接口创建了Angle结构，然后在Main函数中使实例化使用了Angle中的方法三次 最后代码输出的结果让人疑惑 在Expamle1中装箱了Angle类型的实例为 object 然后在Console.WriteLine里产生了拆箱操作，此时输出的是obj的副本 Expamle2里使用了拆箱，产生了拷贝，然后调用了拷贝的值里面的方法 原有的objectangle并未被修改，被修改的是拆箱操作时候创建的值拷贝，运行完后已经被抛弃(赋值给_) Expamle3里产生了装箱操作，也产生了拷贝 Expamle4里强制转换是向引用类型转换，不会产生拷贝，输出了预期的结果 具体查看下图]]></summary></entry><entry><title type="html">Hello,jekll!</title><link href="https://jerryhuang.eu.org/2024/04/08/Hello_jekll.html" rel="alternate" type="text/html" title="Hello,jekll!" /><published>2024-04-08T16:00:00+00:00</published><updated>2024-04-08T16:00:00+00:00</updated><id>https://jerryhuang.eu.org/2024/04/08/Hello_jekll</id><content type="html" xml:base="https://jerryhuang.eu.org/2024/04/08/Hello_jekll.html"><![CDATA[<h1 id="hellojekll">Hello,jekll!</h1>

<p>hello,world!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Hello,jekll! hello,world!]]></summary></entry></feed>