<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[The PBBG Blog]]></title><description><![CDATA[Persistent Browser-Based Games]]></description><link>https://blog.pbbg.com/</link><image><url>https://blog.pbbg.com/favicon.png</url><title>The PBBG Blog</title><link>https://blog.pbbg.com/</link></image><generator>Ghost 3.0</generator><lastBuildDate>Tue, 07 Apr 2026 09:56:25 GMT</lastBuildDate><atom:link href="https://blog.pbbg.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Game Mechanics - Part I (Game Loop)]]></title><description><![CDATA[They key thing that lead me to look into this approach and which ultimately swayed me to go with it, was that for the great majority of idle games...]]></description><link>https://blog.pbbg.com/game-mechanics-part-i/</link><guid isPermaLink="false">63d9205c1b9ddb05e8a76f29</guid><category><![CDATA[Game Development]]></category><category><![CDATA[Game Design]]></category><category><![CDATA[Game Mechanics]]></category><category><![CDATA[Math]]></category><dc:creator><![CDATA[Vincent Rye]]></dc:creator><pubDate>Wed, 01 Feb 2023 14:02:37 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2023/02/Game-Mechanics---Part-I---Game-Loop.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.pbbg.com/content/images/2023/02/Game-Mechanics---Part-I---Game-Loop.png" alt="Game Mechanics - Part I (Game Loop)"><p><strong>Foreword</strong></p>
<!--kg-card-end: markdown--><p>This is the first article in a series of articles on the subject of game mechanics for PBBGs. In each article I will take up one interesting "take" or "example" of a game mechanic which I hope can serve as inspiration to you as a game developer.</p><p>In this first article, we're going to cover what I've have found to be an very cost efficient way to process game progression when dealing with a multitude of characters across an entire player base.</p><!--kg-card-begin: markdown--><p><strong>Introduction</strong></p>
<!--kg-card-end: markdown--><p>I am currently working on a project where I had to ensure progression was occurring on an ongoing basis with a system where each player could have anywhere from 1 to 30 characters. One character at first and progressively more and more as you continue to play the game. In my initial approaches, I calculated player progression every 6 seconds. But when I had to deal with character progression, the number of calculations increased significantly. Trying to scale this up to an estimate active player base of about 300 players within a couple of months became tricky.</p><p>I am personally very fond of idle games that run on a 6 second game loop, so that was my initial approach. I tried to tweak this to longer durations but it didn't seem to solve the core of the problem: too many processed actions per player in a short time span.</p><p>I realized that in idle games with a 6-second tick, players never watch every tick go by, but instead the combination of those ticks over a longer period of time yields enough resources and progression to allow meaningful interaction within the game. The idea of a 6-second tick gives players a sense of constant progression, but increasing the tick speed to a minute and offsetting the rewards would not work for me.</p><p>To address this, I came up with a solution. Each character has a progress value that gets incremented by 1 every 6 seconds. I run a separate query to check which characters have built up enough progression points to go above the threshold for their current activity (in my project it was various types of jobs). Any character that returns as eligible to complete their job gets processed and moved onto the next job, removing the threshold value from their current progress value.</p><p>I took it further by adding individual stages within each job and storing the character progression on the job model itself. I even allowed jobs to be attended by multiple characters, which allowed jobs to stay idle until multiple characters signed up to participate. Any job progression not achieved on the 6-second turns is progressed toward a buffer stored on the character, which players can use to speed up jobs or perform extra duties.</p><!--kg-card-begin: markdown--><p><strong>Step by Step</strong></p>
<!--kg-card-end: markdown--><p>Here is a breakdown in sequence of the approach I took for calculating this:</p><ol><li>Calculate how much time has passed since last tick. Divide that by your tick speed and call that value for "TicksToProcess". I added this approach so that in case of any potential server lag, players would not loose any progression.</li><li>Increment all active jobs "ProgressValue" by the value stored in "TicksToProcess".</li><li>Increment all idle characters "IdleValue" by the value stored in "TicksToProcess".</li><li>Do a database query to check for any active jobs that has it's progress greater than the threshold for completion and/or any stage within that job that has reached the threshold greater for it's completion. I went with stages due to the nature of the game design, but this is not required.</li><li>I then process each completed job/stage and reduce from the "ProgressValue" the amount consumed (the threshold value).</li><li>At this point in time, I then decided to go with updating the active job to whatever the next job is set to, and the cycle begins anew.</li></ol><p>Its worth it to note that the processing of each of the completed jobs can be abstracted away into being calculated by other processors. I went with NodeJS and a system of workers which communicate through a queue system. This allowed me my main node instance to stay free of clutter and focus solely on handling communication to all clients and dealing with the very minor database input/output as described in point #1, 2, 3 &amp;4.</p><p>Optional: On points #3 &amp; 4, you can add limiting factors such as only active players who has been online in the last 12 hours, or you can implement an action system where players have to increase their daily actions regularly)</p><!--kg-card-begin: markdown--><p><strong>PRO'S &amp; CON'S</strong></p>
<!--kg-card-end: markdown--><p>There are several benefits from this approach, here are some:</p><ul><li>Minimizes calculations needed to track player and character progression.</li><li>Offers a constant sense of progression for players, as they see something happening all the time.</li><li>Flexibility to allow players to participate in jobs and progress through stages at their own pace.</li><li>Potential to add further customization through individual stages within each job.</li><li>Allows for multiple characters to participate in jobs, which could lead to new gameplay opportunities.</li></ul><p>However there are also some negative aspects of this:</p><ul><li>May be confusing for some players to understand the concept of a 6-second tick.</li><li>Could limit players who want to actively participate and see progression in real-time. </li><li>The separate queries for character progression could potentially slow down the overall game performance. There are ways to counter this through intelligent database design so as to not having the tables locked down by tons of processed jobs.</li><li>The added complexity of individual stages and multiple characters participating in jobs could be challenging to implement and balance.</li></ul><!--kg-card-begin: markdown--><p><strong>Summary</strong></p>
<!--kg-card-end: markdown--><p>I believe this approach works well in my above circumstance, however it might not work well for all games and this specific implementation may not be what is right for your game.</p><p>They key thing that lead me to look into this approach and which ultimately swayed me to go with it, was that for the great majority of idle games you're not reliant on watching the monitor for every 6 second tick to go by, and most of the time "playing" the game you're actively doing something else in your life.</p><p>From this fact I extracted the concept of hiding the actual progression through a plain increment of numbers and allowed to minimize the amount of processing to be done every single turn, and decreases the number of completed functions to run from "# of Characters" multiplied by "# of players" every 6 seconds into a couple of jobs per player every minute. I further expanded upon this and allowed more difficult jobs to require more than one character decreasing the amount of records to update every 6 seconds in my database.</p><p>I hope this mechanic and this train of though has been an interesting read for you and hope you find usefulness in it for your future endeavors.</p><p>																												Vincent Rye</p><!--kg-card-begin: markdown--><p><strong>Afterword</strong></p>
<!--kg-card-end: markdown--><p>This article was one in the first of many to come on the subject of game mechanics. The next article will cover how to implement rarities into your game and an unique twist on it.</p><p>If you have any particular game mechanic you want me to cover feel free to reach out to me either in the PBBG Discord (Vuy), or send me an email on opusvrye@gmail.com</p><p>Opus Vrye is an idle incremental PBBG in development that is set in the Steampunk theme, with both active and passive aspects. It's currently in a very early development phase, but with the majority of all mechanics and features already detailed out.</p>]]></content:encoded></item><item><title><![CDATA[PBBG - Monetization]]></title><description><![CDATA[Before we go into the subject of Monetization it is important we need to look at the concept of Exchange.]]></description><link>https://blog.pbbg.com/pbbg-monetization/</link><guid isPermaLink="false">6320822495ba243402a148ec</guid><category><![CDATA[Monetization]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Game Mechanics]]></category><dc:creator><![CDATA[Vincent Rye]]></dc:creator><pubDate>Wed, 14 Sep 2022 16:49:39 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2022/09/Beautiful_Fantasy_Golden_Coins_with_Green_Dollar_Bills_digit_0.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2022/09/Beautiful_Fantasy_Golden_Coins_with_Green_Dollar_Bills_digit_0.jpg" alt="PBBG - Monetization"><p>Greetings everyone, today we’re going to have a look at Monetization in PBBGs and my own personal views and experiences with the subject.</p><!--kg-card-begin: markdown--><p><strong>Exchange</strong></p>
<!--kg-card-end: markdown--><p>Before we go into the subject of Monetization it is important we need to look at the concept of Exchange. Exchange in this sense is the concept of giving something that is valuable and exchanging it with something else of value. This is most often seen as a product or service given in return for money.</p><p>The majority of PBBG Games you will find online are free to play and if not entirely free, they are free to a rather large extent. Many of these games have options that allow the player to exchange money for in-game content and this is what we’re going to discuss today.</p><p>One of the reason that Monetization plays an integral part of many PBBGs games is because the developer have to maintain at very least the upkeep of the server costs and very often they involve some sort of multiplayer aspect that require these servers to be strong enough to be able to deal with providing that gaming experience to you. Secondarily for a rather large extent of PBBG Developers it is an additional activity that they allocate time for and they want to see some return on the investment of what little precious time they have left to invest into the project.</p><!--kg-card-begin: markdown--><p><strong>Pay to Win (P2W)</strong></p>
<!--kg-card-end: markdown--><p>Next we get into the famous subject of p2w, which is a rather scorned subject and in some cases rightfully so. When you’re dealing with multiplayer games and you sell direct power to players it instantly turns into a p2w game, which results in the players which have money and the willingness to spend it on your game, taking a superior position in comparison to the rest. The “game” moves away from a great combination of mechanics, graphics and interplay of players into “who has dumped the most money into the game”, and very soon your game doesn’t exist anymore.So how does one implement monetization into your game in a way that it does not become an outright p2w game? There are several different ways and here are some of them:<br></p><ul><li>You sell something that doesn’t interfere directly with game play, such as cosmetics. This can be having a different title, a different icon, a different type of text or some fancy looking equipment.</li><li>If you’re doing an idle game, you can sell “automation”, meaning you can sell to those players who choose to pay for longer and longer idle time between when they have to login to press buttons. This approach doesn’t give you directly an advantage over non-paying players because they can technically still login more often and keep up with the progression of the paying player.</li><li>In some cases you can get away with selling experience boosts and leveling speed, however this only works when you have a hard cap put in place for maximum level. This allows the players which want to rush through the content the ability to do so. It doesn’t directly alter the balance of things because the non-paying players will inevitably reach the same level, just slower.</li><li>You can sell the option to rush through an idle activity in an active manner in order to achieve the gains earlier. An example of this would be an idle feature where your player automatically goes through and clears all the monsters in a dungeon. You can then offer the player the option to manually go through at a greater pace that same set dungeon to achieve the rewards faster. The only down side to this is that you have to put a cap on how many dungeons can be completed in a day to avoid making this another p2w approach.</li></ul><!--kg-card-begin: markdown--><p><strong>Tradable Premium Currency</strong></p>
<!--kg-card-end: markdown--><p>To the above bullet points I want to add another mechanism that doesn’t entirely do away with the p2w approach but to a rather large extent does dull down the negative effect of it. This is done through player economy and trading. I’ve personally seen this work great in a couple of games I’ve played and I will give you a rundown of how this works.</p><p>The approach goes like this:</p><ol><li>You enable a premium currency to be purchased by players. (Often this is called Credits or Tokens)</li><li>This currency serves as the intermediary for every paid feature you implement.</li><li>This currency then gets made tradable with other players, either directly or through some sort of marketplace.</li></ol><p>Once you’ve enabled the above approach it balances out a lot of the otherwise p2w features that you choose to implement. This works because when you allow the player to introduce premium currency into the game through direct payment and make it tradable you directly put in the worth of that currency into the hands of the players. This makes the players directly influencing how much this premium currency is worth to them. To give you a very real example that demonstrates what I mean:</p><p>“Player A” buys 10 Premium Currency, which we will call “Credits”. With these 10 credits, he can either purchase one month of boost to leveling speed and gold drops (let us say 10% boost), or he can take these 10 credits and sell them to “Player B” against some gold here and now.</p><p>What happens is that either way he has achieved a greater potential in the game, and to some extent he has paid to win that game, but at the same time when he chooses to sell these credits to “Player B”, you have put the “Player B” in a position where he has traded some of his current gold for a one month boost!</p><p>“Player A” wins naturally no matter what, but the rest of the non-paying players that buy these currency wins too because they get to experience those same set of premium features without having to cough up with actual money. Best of all, they get to control how much they want to cough up with to experience these features. This puts the non-paying players in control of the value of this premium currency and not the developer.</p><p>I personally like this approach very much because it forces the developer to put attention on creating a great game that players like to play, that is interesting and feature rich. In that way when the developer does a great job at catering to all the players, the interest in the game will go high and you will achieve a more balanced p2w approach than outright buying wealth and power.</p><p>Great examples of these that I have played are Queslar, Elethor, Lyrania &amp; IQRPG.</p><p>Both Queslar and Elethor have a sort of “VIP” system where you spend Premium Currency in order to achieve a percentage boost in experience and in-game income. These bonuses are minor and the boost percentages hover around 5-10%, however still worthwhile for those who want to either pay directly for it with money or offer some of their hard earned in game currency in exchange for these boosts. </p><p>However pretty much in all of them you have the option to spend those premium currencies to extend the duration you can be away from the game before you start to slow down your progress. In some of them you can buy fancy titles and special cool icons that make the game a bit more interesting to play, all of which are great examples of non p2w approaches.</p><!--kg-card-begin: markdown--><p><strong>My Viewpoint</strong></p>
<!--kg-card-end: markdown--><p>Speaking as a player that have personally thrown a decent amount of money into paying for premium currency in such games as above, I have firsthand experienced the benefits of this approach from a player point of view and I respect the need to have monetization implemented in games for them to be sustainable, but at the same time when you have games that are implementing a free to play path, remember that the game would not exist without the volume of players participating in the game and making it enjoyable for everyone including the people who choose to spend money on the game. </p><p>Going back to the subject of exchange that I clearly delineated at first I would like to expand upon that by saying that while you’re not paying for a game and giving exchange in form of real money like you do with some modern game releases where you pay upfront for the cost of the game, you do give back exchange in terms of being part of the player base and playing the game itself. This is mostly prevalent in multiplayer games where it couldn’t even be played without a substantial amount of players partaking in the multiplayer features of the game.</p><p>The balancing between both those paths are therefore of great importance to create a viable game and it would not survive without non-paying players and paying players alike. They each contribute in their own way to the longevity of the game itself and the creation and expansion thereof.</p><p>Hope you liked this short overview of Monetization in PBBGs and how I’ve experienced it done right and how I would like to see players experiencing PBBGs in terms of monetization and how it relates to gameplay.</p><p>																												Vincent Rye</p><p></p><hr><p>Next up I will be writing a short blog post on the subject of AI Generated Game Art! Below are just some of the content I've been generating. Stay tuned for more! <br>(Side Note: This Article's Header is AI generated Art too!)<br></p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.pbbg.com/content/images/2022/09/Female-Healer.png" width="2560" height="2560" alt="PBBG - Monetization"></div><div class="kg-gallery-image"><img src="https://blog.pbbg.com/content/images/2022/09/Male-Warrior.png" width="2560" height="2560" alt="PBBG - Monetization"></div><div class="kg-gallery-image"><img src="https://blog.pbbg.com/content/images/2022/09/Female-Sorcerer.png" width="2560" height="2560" alt="PBBG - Monetization"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.pbbg.com/content/images/2022/09/Male-Guard.png" width="2560" height="2560" alt="PBBG - Monetization"></div><div class="kg-gallery-image"><img src="https://blog.pbbg.com/content/images/2022/09/Female-Archer.png" width="512" height="512" alt="PBBG - Monetization"></div></div></div></figure>]]></content:encoded></item><item><title><![CDATA[The State of PBBG 2022 Survey Results]]></title><description><![CDATA[At last we have the results of our annual survey conducted in February. With 130 responses, we came in just under last year but with a lot less marketing. This year we also modified a bunch of the questions to refine them in an effort to create a more accurate picture of the PBBG landscape.]]></description><link>https://blog.pbbg.com/2022-state-of-pbbg/</link><guid isPermaLink="false">62ad28e895ba243402a1487f</guid><category><![CDATA[State of PBBG]]></category><category><![CDATA[Meta/Community]]></category><dc:creator><![CDATA[Christopher Graves]]></dc:creator><pubDate>Sat, 18 Jun 2022 23:05:49 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2022/06/state_of_pbbg_survey.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2022/06/state_of_pbbg_survey.png" alt="The State of PBBG 2022 Survey Results"><p>At last we have the results of our annual survey conducted in February. With 130 responses, we came in just under last year but with a lot less marketing. This year we also modified a bunch of the questions to refine them in an effort to create a more accurate picture of the PBBG landscape.</p><p>As always, <a href="https://docs.google.com/spreadsheets/d/15w7cAncbSBXYL4WVoAkotstoDH4PL6OgsgZPlKV99pc/edit?usp=sharing">here is the link</a> to the raw data if you'd like to crunch it yourself. If you'd like to help us create a better survey, please join us on the <a href="https://chat.pbbg.com">PBBG Discord</a> server.</p><p>This year's data crunching came to us by our resident benevolent data helper, @rodrigo.borges#4172 on Discord. Thanks! Without further ado, I present the results of this year's survey;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>How long have you been playing PBBGs?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-1.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>What additional platforms to browsers are important to you when starting a new game?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-2.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>How many PBBG games are you currently playing?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-3.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>What single player features will make you MORE likely to play a new game?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-4.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>How often do you prefer to interact with your games?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-5.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>How often do you like your game reset?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-6.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>What best represents how complicated do you prefer your games?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-7.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>What multiplayer features will make you more likely to play a new game?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-8.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>What best represents your preferences for premium currency in a game?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-9.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>What customizable features of a game do you enjoy most?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-10.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>How graphical do you prefer your games?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2022/06/image-11.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"><figcaption>What community resources do you use/are a member of?</figcaption></figure><p>And this year, our data expert has put together correlated charts to help understand what some of the groups of people prefer.</p><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2022/06/image-12.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2022/06/image-13.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2022/06/image-14.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2022/06/image-15.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2022/06/image-16.png" class="kg-image" alt="The State of PBBG 2022 Survey Results"></figure><p>That's all folks, see you next year!</p>]]></content:encoded></item><item><title><![CDATA[Game Review - Planes of Tlessa]]></title><description><![CDATA[Planes of Tlessa is a non-idle fantasy combat crafter game where you can roam around a global map, create a kingdom and wage war with other players. On the surface this may seem a bit tired, but the particular concoction of this has a fairly fresh feel.]]></description><link>https://blog.pbbg.com/game-review-planes-of-tlessa/</link><guid isPermaLink="false">60d4987c6878724fc3386085</guid><category><![CDATA[Game Review]]></category><category><![CDATA[Marketing]]></category><dc:creator><![CDATA[Christopher Graves]]></dc:creator><pubDate>Mon, 28 Jun 2021 17:36:36 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/06/planes_of_tlessa.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/06/planes_of_tlessa.png" alt="Game Review - Planes of Tlessa"><p>In the last game we reviewed, we played a Sci-Fi idle/management game called <a href="https://blog.pbbg.com/gamereview-spacealpha-net/">SpaceAlpha.net</a>. Today, we're reviewing something pretty opposite – an active, fantasy MMO called Planes of Tlessa. This was recently released at time of writing, so the game has probably changed significantly if you're reading this in the future. As such, <strong>any balance issues that are planned to be fixed will be omitted from the review</strong>.</p><p>[<em>See all of our future livestreams by <a href="https://twitch.tv/pbbgsite">following the pbbgsite channel on Twitch</a>!]</em></p><p><strong>As always, this game review contains spoilers for in-game content.</strong></p><p>Game: <a href="https://planesoftlessa.com/">https://planesoftlessa.com/</a><br>Discord: <a href="https://discord.gg/DJPzzU95">https://discord.gg/DJPzzU95</a></p><hr><!--kg-card-begin: markdown--><h1 id="concept">Concept</h1>
<!--kg-card-end: markdown--><p>Planes of Tlessa is a non-idle fantasy combat crafter game where you can roam around a global map, create a kingdom and wage war with other players. On the surface this may seem a bit tired, but the particular concoction of this has a fairly fresh feel. All players get to do both combat and crafting, so the specialization lies with what you do the crafting in. You can also do enchanting, which has its own level entirely.</p><p>One thing about Planes of Tlessa is that it's a real <em>grind</em>. Purposefully. Leveling from 1 - 10 (out of 999) takes about a week of active play. If playing an active game that is a grind isn't your cup of tea, I would probably steer away. But for those that do like that, this will definitely scratch that itch.</p><p>Since the game is non-idle, most actions have a 10 second cooldown timer before you can do anything again.</p><!--kg-card-begin: markdown--><h2 id="score710">Score: 7/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="controluiintuitiveness">Control, UI, Intuitiveness</h1>
<!--kg-card-end: markdown--><p>This was pretty hard to judge overall, since the game is still so new. There's no logo yet, the UI is pretty barebones, and there are some bugs here and there that sort of get in the way. One of the major inhibitors I see (which may as well be fixed soon) is that the main game screen doesn't remember your monster or item selections. So if you want to do anything else in the game, you have to open those in a separate tab. It's certainly doable, and I have no doubt that it will be fixed in the future, but at time of writing that's a big barrier to usability.</p><p>The item screens are really just walls of text, it's very difficult to differentiate between important factors for items. It's literally <em>hard to read</em>. There's 4 big boxes for items, one for the basic info, the base stats, the prefix and another for the suffix. A lot of it is duplicated information that is really far apart on the screen.</p><p>The kingdom management screens feel a bit scattered as well, the requirements are only partially shown for upgrading each building on the main menu. Population required is missing, which is a pretty main part of your upgrade path. Attacking another kingdom is even more confusing and even disjointed.</p><p>Traveling around the map is pretty intuitive, and the menus also have a really cool style. So big win there!</p><p>Overall, UI is probably PoT's main weakness. The developer is aware of these problems and will likely fix them as time goes on.</p><!--kg-card-begin: markdown--><h2 id="score410">Score: 4/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="gamemechanics">Game Mechanics</h1>
<!--kg-card-end: markdown--><p>Alright, the meat and potatoes of the game. The core mechanic here is pretty simple; fight things, get better stuff, fight bigger things. It's done in a fairly intuitive manner, and dying is absolutely a thing, though it seems to only cost you 20 seconds of revive time. From where I'm at, I don't see any special sauce here. A small departure from the normal formula is that you also get spells that can heal you or deal more damage, so you basically get 4 weapon slots instead of 2 for each hand. Every time you attack, there is a 10 second timer until the next time you can fight again.</p><p>You also have crafting, from which you can choose what item type you want to craft. Anything you can wear, you can also craft, which is pretty cool. I believe the idea is that end-game gear should come from the items that players can craft. And it being an active-only grind game, that is some serious time commitment to get there.</p><p>The Kingdoms you can create on the map are a nice addition to the repetitive grinding of combat/crafting. Anyone can make a kingdom on a blank spot on the map. You can create more kingdoms, but after the first it will cost a decent fee to create. Once you do create one, you can upgrade various buildings to give you more defense or production at that location. In addition to buildings, there are military units that can be recruited and used to attack other players. The limiting factor here, which is a bonus in my opinion, is that you have to be physically in your kingdom in order to administer it. Travelling around the map from kingdom to kingdom to upgrade everything in turn <strong>really</strong> breaks up the monotony and makes for a fun loop.</p><p>There's a map you can move around on featuring a couple of interesting locations that allows you to do adventures, which are 10-30 minute quests that net some nice equipment, and allow you to visit the player market. But you <strong>must</strong> be physically on one of those places in order to be able to visit it, just like with kingdoms. It's best if you park your kingdoms around these points of interest.</p><p>It's worth noting that there are references to events happening on 'The Surface Plane', so I can guess that there will be some huge recursive-esque changes in the mechanics of the game in time.</p><!--kg-card-begin: markdown--><h2 id="score710">Score: 7/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="replayability">Replayability</h1>
<!--kg-card-end: markdown--><p>I find myself going back to play PoT so I can keep the grind up and keep upgrading my kingdom. Moving across the map from place to place so I can do my daily duties is enough to keep me occupied while doing other things. I don't think I could concentrate on it full-time, but it's a great companion to something that you will concentrate on. Being still so new, I think there are some big features that are planned, so I gave this a slightly higher score otherwise.</p><!--kg-card-begin: markdown--><h2 id="score810">Score: 8/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="importantfactors">Important Factors</h1>
<!--kg-card-end: markdown--><p><strong>Catch-up mechanic</strong>; To my knowledge, there is no catch-up mechanics here. Since it's an active game, progressing largely relies on your ability to play more. However there isn't a massive competitive edge here quite yet, so being behind the curve isn't going to crush your experience. However if competition becomes a large part of the gameplay, there will have to be some sort of catch up implemented to not chase off new players.</p><p><strong>Premium currency;</strong> There isn't any! In fact, the developer is so against paid currency that trying to buy anything in the game with IRL money is strictly forbidden.</p><p><strong>Launch reset;</strong> It has already launched, so there is no reset!</p><!--kg-card-begin: markdown--><h2 id="score710">Score: 7/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="community">Community</h1>
<!--kg-card-end: markdown--><p>The community is still pretty darn small, it's hard to determine how good or bad it is yet. The players that are there are generally supportive and positive, so that's a definite good seed that can be fostered into a really strong and happy group of players.</p><!--kg-card-begin: markdown--><h2 id="score610">Score: 6/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="funfactor">Fun Factor</h1>
<!--kg-card-end: markdown--><p>Honestly, my main cup of tea isn't non-idle games. But I still found this game quite fun - the migration from place to place breaks up the repetition that you'll find in most PBBGs mixed with a really good feeling when you do finally level up (since they're so sparse) is awesome! The bones here are fantastic, and I can absolutely see this really start to take off in the near future.</p><!--kg-card-begin: markdown--><h2 id="score810">Score: 8/10</h2>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Game Review - Elethor]]></title><description><![CDATA[Elethor, despite it’s problems, is a very good PBBG and is still in it’s infancy, the open release is just 4 months in as of this date. [...] I suggest PBBG enthusiasts to give this game a try, at least a week.]]></description><link>https://blog.pbbg.com/game-review-elethor/</link><guid isPermaLink="false">6092ab5c6878724fc3385f94</guid><category><![CDATA[Game Review]]></category><category><![CDATA[Guest]]></category><dc:creator><![CDATA[Christopher Graves]]></dc:creator><pubDate>Thu, 20 May 2021 00:25:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/05/elethor.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="guestreview">GUEST REVIEW</h2>
<img src="https://blog.pbbg.com/content/images/2021/05/elethor.png" alt="Game Review - Elethor"><p>Today we're featuring a guest review from our <a href="http://reddit.com/r/pbbg">subreddit</a> by Athith1996. It has been slightly modified with approval.<br>
<a href="https://elethor.com/">Game link</a><br>
<a href="https://discord.gg/KX2eEb26rP">Game Discord link</a></p>
<!--kg-card-end: markdown--><hr><p>I have some thoughts on this PBBG called Elethor that I’ve been playing for a long time. This is gonna be a long post so bear with me.<br></p><h2 id="about-the-game">About the game</h2><p><br>This is an action/tick based PBBG. Its set in a futuristic, almost post-apocalyptic world with rifles and guns as weapons instead of the overused sword, spear, etc. The plot is simple; you have to kill different monsters and progress in the questline. There are 2 main actions you can do - killing monsters and mining. You get some base actions everyday around 1200 but the actions will be unlimited as long as you can refresh regularly. 600 combat actions is equal to 1 hour so 1200 actions means 2 hours, after which you have to refresh and you’ll get back 1200 actions. If you don’t refresh you go into a fatigued state where the actions take more time to perform. For example you’ll only do 240 combat actions instead of 600 per hour. You can buy more actions if you don’t want to check in every 2-3 hours by paying premium currency. Also you can get more actions through in game quests. So this isn’t P2W at all - paying for actions this way only makes your life easier. The main aim of the game is to get better equips and increase your combat/mining levels (They are the only 2 things to level up). There’s also rankings for killing monsters of each type in addition to daily, weekly, combat and mining rankings. No PVP as of now. There’s also corporations which are some sort of guilds.</p><hr><h2 id="positives">Positives</h2><p><strong>1. Great modern UI -</strong> The game is smooth and easy to handle. Its obvious the dev has spent a lot of time in making the UI as good as possible and it doesn't feel like we're back in the 2000s.</p><p><br><strong>2. Developer -</strong> The dev is dedicated and listens to players. He comes to chat daily at a specific time to see what players are talking about in chat. Though some of his decisions may make some players angry but overall he is a good guy. I attribute some of his unlikeable decisions to the mods that he consults before he decides them.</p><p><br><strong>3. Player base -</strong> The players are generally supportive to newbies and help them answer their queries. The mods rarely answer them and don't show up in chat regularly. But if there's something serious going on they come to chat in help not just on boring days.</p><p><br><strong>4.Uniqueness-</strong> This game is very unique and there aren’t many cliché elements. It’s different in terms of UI, plot, progressions, etc.</p><hr><h2 id="things-that-might-stop-you-from-playing-this-game">Things that might stop you from playing this game<br></h2><p><strong>1. Highly Market based -</strong> This game is heavily dependent on market. Only way to earn significant amount of gold is by selling stuff (ores especially) on the market. Even the materials used for crafting equips you’ll have to get from the market as it is just easier . You can still progress without using the market but the difference is very large. If you don't like trading or checking the market daily to get an idea of prices, etc. then this isn't the game for you. Don’t get me wrong there are still some people playing who haven’t used the market at all but they are happy to be behind others or don’t care about it . They just enjoy the game. But if you are a bit competitive and don’t like to trade then this isn’t the game for you.</p><p><br><strong>2. Masteries -</strong> If you are thinking to try out this game then I suggest you do this fast. Masteries are something like skills and they level up using time. You can only level up one skill at a time. If you choose a particular mastery to level up it gains 12 points a hour and there are 5 levels to a skill. Some skills take longer time to level up. If my calculations are right it will take you around 500 days to fully level up current masteries. There’s no other way to speed up or gain more master xp. Only time will level up. So the older players have a massive advantage and they will always be ahead of you. There’s no way to catch up unless top players quit or forgot to add another mastery when one finishes leveling up but this rarely happens. So the first thing to do when playing the game is saving enough gold to buy your first mastery/skill as time is important.<br></p><p><strong>3. Rankings -</strong> There's some problems in daily actions /weekly actions rankings that may confuse new players. The daily rankings are bugged and you see the players having more actions than its possible in a day. For a new player who is active, refreshes regularly and gets the highest density mining action possible, the only way he can see how he’s doing against others is through daily rankings. But it's bugged and he gets confused. It'll take around a month for a new player to get into any of the rankings and only if they play actively.</p><p><strong>4. VIP needed to vote</strong> The dev conducted polls to know which update should be in the next patch and only VIP players voted. This pissed some f2p players off but I remain neutral about this as long as the update is good.</p><hr><p><strong>Bugs Abusing and Rollback</strong></p><p><br>Recently there was a rollback of about 6 days due to a player abusing a bug which duplicated (duped) gold and materials (mats). Apparently this started months ago but the old abusers didn’t abuse it that much. They might’ve xtraded the duped gold out we will never know. A player found out about the bug on April 19th and he wrecked havoc on the market , bought out all the ores, materials, etc. and spread the duped gold. Also there was lots of gold being sold on the xtraders market due to this. Dev found out and the only way to cure the economy was a rollback. The abuser was on discord and he helped with the rollback but he got banned anyway. Other old abusers got banned too. But the xtraders were the most hit because they traded on another website and dev wasn’t responsible for those trades so some of them lost millions/billions of gold. Many players quit mostly xtraders. But this affected the regular active players too and the compensation wasn’t much just extra actions which the active players didn’t need because they refresh regularly. The dev said he will discuss with mods about extra experience gain but we didn’t get any notification about that. The extra actions stayed for about 4-5 days but it didn’t offset the losses occurred. There were some problems with VIP purchases and such. Also there were some new visual bugs like masteries not showing to be leveling up. One of the VIP players I know who isn’t a xtrader had this visual/cache bug. He went to Discord about this but there wasn’t any reply for a while as the dev was on vacation and wasn’t online. One of the mods replied later, but by this time the player had already raised a dispute on PayPal but he was ready to drop it if it gets solved. The mod notified him with a permaban because you get banned if you refund purchases. If the mod had only checked his profile he would’ve understood it was a purely visual bug and we can still see the mastery leveling up, only he couldn’t. But he resorted to threatening with permaban which isn’t explained clearly in the games TOS. So the player didn’t understand what was going on even after the dev came later and said he’ll sort it out but no one gave any explanation to him that it was a harmless bug. After a day it wasn’t resolved and he left the game. He got banned later because purchases were refunded. Such a simple matter and the dev lost a paying player. If only the mod could’ve communicated better, its imperative to inform about permabans but why do that first instead of assuring the player that it will be resolved, it’s like the mod doesn’t care about the player at all. It’s their job to assure the player that everything will be solved but no, just threatening the player about his actions. Even other players were assuring the guy that it’ll be resolved but the damn mod ruined it all. He 100% left because of the mod and unclear communication. I feel annoyed because it was so unnecessary. The developer was on a vacation at this time so props to him for quickly resolving the issue and banning the abusers but more transparency and communication would’ve been appreciated.</p><p><strong>Corporation Events</strong></p><p>The new update on 5/5/2021 was a huge one. It introduced a new thing to level up called fame. Also corporation (corp) events and corp buffs were released. As of now fame can be leveled up by doing corp events. Currently there’s one corp event which takes place from Thursday to Saturday. It’s called “Charitable Giving” and corp members have to donate various stuff for points. The average points earned by the corp will result in being awarded fame points/exp. Then there’s corporation buffs which the corp creator or any member with permissions can level up. The buffs are either combat or mining related. With these new things the game got more competitive. Everyone wants to join a corp - scratch that, everyone wants to join a corp with powerful members. Before there were some members in corp who were inactive for like 3-4 days and others also didn’t mind but now those members are a liability and are being kicked out because they will lower down the average points earned for corp events. Also there were many lone wolfs before, now everyone is pressured into joining a corp because now the huge advantages that a corp offers cannot be ignored. Overall a very good update, more stuff to do and strategize for, the corp events also act as a sink for materials and ores. </p><hr><p>Thanks for reading the whole thing, the review came out longer than I imagined it to be. Elethor, despite it’s problems, is a very good PBBG and is still in it’s infancy, the open release is just 4 months in as of this date. There are around 330 players online everyday and I expect it to increase after the latest update. I suggest PBBG enthusiasts to give this game a try, at least a week.</p>]]></content:encoded></item><item><title><![CDATA[Making Egg Trainer 7]]></title><description><![CDATA[In today's article, we're going to have a look a poll that I released to see what people want from the MERN-template. I'm sure there will be some surprises.]]></description><link>https://blog.pbbg.com/making-egg-trainer-7/</link><guid isPermaLink="false">604d8e5a6878724fc3385b5d</guid><dc:creator><![CDATA[Kayne Ruse]]></dc:creator><pubDate>Sat, 15 May 2021 02:23:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/03/article-7.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/03/article-7.png" alt="Making Egg Trainer 7"><p>In today's article, we're going to have a look a poll that I released to see what people want from the MERN-template. I'm sure there will be some surprises, so let's begin.</p><p>The poll asked people to rank features from least important (1) to most important (5) for a PBBG.</p><h3 id="the-results">The Results</h3><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/03/image.png" class="kg-image" alt="Making Egg Trainer 7"></figure><p>The chat system is kind of leaning towards the positive, but there's also plenty of push back. This, I think means that I should continue with my initial plans for including one, but not to stress too much over it.</p><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/03/image-5.png" class="kg-image" alt="Making Egg Trainer 7"></figure><p>Interestingly, the opposite seems to be true for the news feed system - a lot of responses are middle to low importance. Well, the news feed system already exists (and was one of the first things I implemented), so I think I'll leave it for now.</p><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/03/image-6.png" class="kg-image" alt="Making Egg Trainer 7"></figure><p>This isn't much of a surprise - I knew moderation tools would be needed, as they are for any multiplayer game. </p><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/03/image-7.png" class="kg-image" alt="Making Egg Trainer 7"></figure><p>This is a surprise. It seems payment systems are split roughly between the two extremes. I've used PayPal in the original build of Egg Trainer, but I don't want to force people into one specific payment provider (stripe is supposed to be really good for developers). I may instead host some tutorials on installing your favourite option in the documentation wiki.</p><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/03/image-8.png" class="kg-image" alt="Making Egg Trainer 7"></figure><p>I don't know about you, but this seems like a very big "meh" to me. Not every game needs energy systems. I wonder if I should include an optional backend for this at all?</p><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/03/image-9.png" class="kg-image" alt="Making Egg Trainer 7"></figure><p>I don't know about you, but this seems like a very big "hell yeah" to me. It seems a lot of games need a leaderboard - which makes sense, since these are multiplayer games at heart, and people love competition. I'm actually considering writing a modding tutorial where I walk the developer through creating their own leaderboard backend.</p><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/03/image-10.png" class="kg-image" alt="Making Egg Trainer 7"></figure><p>I don't really know what to make of this one. It's an obvious "yes", but I also shouldn't have grouped four different things together. I suppose this could be called the "economy backend".</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/03/image-11.png" class="kg-image" alt="Making Egg Trainer 7"><figcaption>Remember the Yip Yips from Sesame Street?</figcaption></figure><p>Well. Documentation and tutorials got a resounding "yes". Thankfully, I've already began working on them using github's wiki feature. Hopefully by the time this article releases, there will be a lot of content there to help you out.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/03/image-12.png" class="kg-image" alt="Making Egg Trainer 7"><figcaption>How the heck?</figcaption></figure><p>OK, so I threw this one in as a lark. I was not expecting... this. Exactly half of people said yes, so I will need to include some sort of styling template or tutorial at some point; most things in the client already have CSS class names. I'll definitely have to make this optional, since half of the people said no.</p><h3 id="misc-feedback">Misc. Feedback</h3><p>The final section was optional for people to give their honest, and anonymous thoughts. Let's have a look at them.</p><blockquote>For me, the main barrier for this product right now is working with you. Your overall arrogance takes away any motivation to be your client. This is not meant as mean, but sincere feedback. Offering something for other people goes beyond the product and the creator's ego.</blockquote><p>This is very true. My ego can sometimes overtake me. If that stands between my tool and a user that needs it, then I really need to sort this out. Hopefully, they'll be willing to look past my own flaws, or at least be interested in using the project without my interference.</p><blockquote>I don't know what MERN templating is.</blockquote><p>Totally valid - I haven't been super clear as to what the MERN-template is or what it's purpose is, partially because I didn't know myself. But I know now that the template is a game engine written from scratch to support a very niche type of game.</p><blockquote>You’re code is shit, your picture on GitHub. You look like some fat fuck</blockquote><p>Oh wow. Your comments cut so deep. And your grammar is devastating. How will I ever recover?</p><blockquote>Security is the MOST important thing. Database security, account security for players, and checks to prevent hacking or manipulation of data.</blockquote><p>Absolutely. I'm going to discuss security holes in the wiki, eventually, as there are things like the default admin account that need to be seen to. I highly recommend anyone to do their research on how to harden a server if they're going to use the template in production as well.</p><blockquote>Love the project if you're on discord and would like some help or to discuss this template further please do get in touch. I'm a student currently looking to do some opensource work to expand my portfolio. Always loved PBBG's. I'm &lt;username&gt; on discord or throw me an email at &lt;email&gt;</blockquote><p>Thank you! I'm going to contact you after I finish writing. Also, for anyone who wants to contact <em>me</em> about the project, or about anything at all, I always include my business email in the end section below!</p><h3 id="conclusion">Conclusion</h3><p>So, after gathering feedback and processing it, here are the features, from most important to least important, filtered through my own needs and wants.</p><ol><li>Full Documentation</li><li>Chat System with Strong Moderation Tools</li><li>Modding Tutorials, Namely Leaderboards</li><li>Styling Templates And Generators</li><li>Economy Support</li><li>Payment System Tutorials</li></ol><p>If you think I made a mistake, or interpreted the results wrong, that's totally fine! Feel free to contact me either on Discord (Ratstail91#6600), or via my business email below.</p><p><em><em>My name is Kayne Ruse of KR Game Studios, you ca</em>n find me on the net as Ratstail91, trying to get my tongue unstuck from a pole like in the movies.</em></p><ul><li><em>Egg Trainer Website: <a href="https://eggtrainer.com/">https://eggtrainer.com/</a></em></li><li><em>MERN-template repo: <a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a></em></li><li>auth-server repo: <a href="https://github.com/krgamestudios/auth-server">https://github.com/krgamestudios/auth-server</a></li><li><em>news-server repo: <a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a></em></li><li><em>chat-server repo: <a href="https://github.com/krgamestudios/chat-server">https://github.com/krgamestudios/chat-server</a></em></li><li><em>Business Inquiries: krgamestudios@gmail.com</em></li></ul>]]></content:encoded></item><item><title><![CDATA[The Evolution of Elethor's Infrastructure]]></title><description><![CDATA[<p>An application's infrastructure is typically designed around its needs. In an ideal world (and most blog posts), those needs are outlined clearly before any work starts, and everything scales smoothly and automagically. In the <em>real</em> world, however, it almost never plays out that way. It didn't for my game Elethor.</p>]]></description><link>https://blog.pbbg.com/the-evolution-of-elethors-infrastructure/</link><guid isPermaLink="false">603da33e6878724fc33858f6</guid><dc:creator><![CDATA[Caleb]]></dc:creator><pubDate>Fri, 30 Apr 2021 00:00:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/05/elethor-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/05/elethor-1.png" alt="The Evolution of Elethor's Infrastructure"><p>An application's infrastructure is typically designed around its needs. In an ideal world (and most blog posts), those needs are outlined clearly before any work starts, and everything scales smoothly and automagically. In the <em>real</em> world, however, it almost never plays out that way. It didn't for my game Elethor.</p><p><a href="https://elethor.com">Elethor</a> is an idle RPG PBBG set in an alternate future. Players log in occasionally to craft items, upgrade their items, interact with the market, chat with other players, etc. Activities typical in a PBBG. The actions in Elethor are server-sided and tick-based. Every 6 seconds, players who have actions fight monsters and get drops. Every 60 seconds (on average), players gather ore from resource nodes. This is also relatively typical, although some games run their actions as HTTP requests, meaning players need to logged in with an active tab for their actions to tick.</p><p>I am the solo dev for Elethor, a passion project that has gotten more traction than I anticipated. It also broke in ways I hadn't anticipated. As a full-stack developer at my day job I dabble in a bit of everything, but devops and infrastructure are easily my weakest points. So take this all with a grain of salt. Or two. I'm learning as I go.</p><p>This is my infrastructure story. So far.</p><h2 id="phase-1">Phase 1</h2><p>Phase 1 started as it probably does for most projects.</p><p>All the game code ran on one server, and the database lived on another server. <a href="https://www.digitalocean.com/">DigitalOcean</a> is my provider, and I utilize their managed database servers. As I mentioned earlier I'm not a devops guy, so the less I have to worry about, especially with crucial game data, the better.</p><p>The services include:</p><ul><li><a href="https://www.postgresql.org/">Postgres</a> as the database (managed by DO).</li><li>PHP (<a href="https://laravel.com/">Laravel</a>), what the back-end is written in.</li><li>A NodeJS server for websockets. I receive data from the client via HTTP requests, but utilize websockets to send events to the client.</li><li><a href="https://laravel.com/docs/8.x/horizon">Laravel Horizon</a>, a queue processing service to handle queueing and executing actions.</li><li><a href="https://redis.io/">Redis</a> for caching and as storage for the queue processing service and notification system.</li><li><a href="https://vuejs.org/">VueJS</a> as the front end.</li></ul><p>It's a bit convoluted, but the combined components perform well without major bottlenecks.</p><h3 id="deployment">Deployment</h3><p>Luckily I had experience using <a href="https://github.com/deployphp/deployer">Deployer</a>, so integrating it with Elethor was a breeze. This automated a majority of my deployment tasks into one script, making it impossible to make silly mistakes (like not invalidating a cache, or forgetting to cache-bust assets). Manual deployments should be avoided at all costs.</p><h3 id="database-vs-cache">Database vs Cache</h3><p>The database is the primary source of truth for all data. The cache holds information that either changes infrequently or in very specific instances <em>and</em> is extremely heavy to collect in the first place.</p><p>For example, players can equip up to 16 different pieces of gear. Each piece of gear has a tier, reinforcements, energizements, and all these numbers play into their stats that are calculated every single fight. This data is spread out across several tables for each item, making for heavy queries--especially at every 6 seconds per player.</p><p>However, the equipment state only changes when a player equips / unequips / upgrades an item. Therefore I store the player's equipment in the cache, and invalidate it on those events. This cuts the number of database queries by an extraordinary amount, and hitting the Redis server once only costs RAM to store it and a bit of network lag.</p><p>An example of something <em>not</em> to cache is the volatile and constantly changing market data, however. It's better to optimize the queries, fetching a fresh copy when needed, than to continually invalidate the cache.</p><h3 id="but-it-wasn-t-enough-">But it wasn't enough...</h3><p>With everything but the database running on the same server, things quickly bottlenecked. Even after doubling my server size twice within a few hours after launch, there were still lag problems.</p><h2 id="phase-2">Phase 2</h2><p>Optimizing the existing combat actions was the next step. After closely analyzing my code I found I was making almost 50 database queries per combat action. Too many.</p><p>Some of these were N+1 queries that needed optimized. Others were variables I was using in multiple places, so I instead opted to create a new class, fetch the data once, and grab the data from the class rather than the database. In other places, I was manipulating the data in the database in several places, so I refactored to only manipulating the data within the class and then committing the final bit of data to the database.</p><p>I managed to get the number of database queries down to 8 per job, and only 3 of those were updating existing data. This got my action processing time from 250-300ms down to 120-150ms. Still long, but <em>significantly</em> faster.</p><h2 id="phase-3">Phase 3</h2><p>Separating out services is the best way to horizontally scale an application. Luckily for me I already utilize Laravel Horizon for action queueing, which lends itself nicely to being split off.</p><p>I created another server (we'll call it Server#2) to process fighting actions (the ones that run every 6 seconds) exclusively. The other queued jobs would still be handled on the primary server.</p><p>Splitting out the fighting actions' consistently heavy load keeps the primary server load at 50% of max a majority of the time, only spiking during patch releases or peak hour times.<br>Currently the main problem on Server#2 is the network lag time of reaching out to the Redis server for cache. It's still <em>significantly </em>faster than hitting the DB directly, but I hit it often enough during each fight action that the network time is the primary slowdown.</p><p>Ideally I would fix this problem by grouping together my Redis calls up front rather than spreading them throughout the code, however that will require a major refactor.</p><p>It's things like this that I can't imagine ever anticipating while developing this game in beta with 30-40 active players.</p><h2 id="phase-4">Phase 4</h2><p>I'm not here yet, but I have plans on how to improve the infrastructure. At this point, I can horizontally scale combat actions easily, which is my primary server usage. However at that point, upgrading servers (and deploying code) gets a bit trickier to manage.</p><p>The biggest thing I will tackle is most likely the network traffic of requesting resources from the cache and the database. This might mean setting up a Redis cluster, it might mean lumping my Redis requests together, it's not for sure at this point. But I'm confident as soon as I scale the servers and do some marketing, new problems will show up as more players arrive.</p><h2 id="questions-i-asked">Questions I Asked</h2><h3 id="serverless">Serverless?</h3><p>Serverless is great for quickly scaling up an application and handling unpredictable server loads.</p><p>Serverless can also be incredibly expensive for maintaining that scale.</p><p>One of the benefits of running an idle game is that the game load is incredibly predictable. I know players can only perform one combat action every 6 seconds, and these actions run 24/7 around the clock. My server usage is extremely level for days at a time.</p><p>The server I run the fighting actions on costs me $80/month. It processes anywhere from 80-120 "actions" per second.</p><p>To process the same actions (again, <em>just</em> combat actions) on AWS Lambda (a popular serverless provider) would be about 210m jobs per month on average. This would cost ~$2,000/month on the cheap side.</p><p>I opted to use a dedicated server.</p><h3 id="kubernetes">Kubernetes?</h3><p>My dev environment is all Docker containers and it's a joy to work with. My experience with Docker pretty much ends there, and I'd rather spend my time developing new features for the game than altering the server infrastructure with tools I'm unfamiliar with.</p><p>Not to say I'll never go with Kubernetes, but it's not an active plan I'm pursuing.</p><h2 id="closing-thoughts">Closing Thoughts</h2><p>This has easily been the best learning experience (as far as code goes) of my entire life. Being thrown into the fire with hundreds of players screaming when buttons take too long to click forces you to learn and adapt quickly.</p><p>It's also been incredibly difficult. I'm reaching the point where posts about "scaling architecture" on Medium don't cut it anymore. I'm not scaling a brand new application where I can design it the way I want. I can't just throw "Kubernetes" at the problem and fix it. Elethor is a real-life application with real users that needs 100% up-time. Taking it down for a week to change the way the servers work isn't an option.</p><p>That said, you can only plan so far. Given a month before launch, I would never have anticipated the problems I've faced nor had the foresight to prepare. Premature optimization is a real problem, and I'd rather have a shipped product that needs fixed than a shiny prototype that hasn't seen the light of day.</p><h2 id="your-questions">Your Questions</h2><p>What did I miss?<br>What did I glaze over too quickly that you'd like to hear more about?</p><p>Leave a comment and let's start a discussion! Chances are you're not the only person wondering, so give back to the community a bit and ask your question!</p>]]></content:encoded></item><item><title><![CDATA[Game Review - SpaceAlpha.net]]></title><description><![CDATA[<p>As the very first game review for the PBBG.com blog, I feel it's my duty to make sure that I review a game that has enough meat to really dig into. I thought about doing a deep review of some of the larger, more predominant games in the community;</p>]]></description><link>https://blog.pbbg.com/gamereview-spacealpha-net/</link><guid isPermaLink="false">6052d7636878724fc3385c25</guid><category><![CDATA[Game Review]]></category><category><![CDATA[SpaceAlpha.net]]></category><dc:creator><![CDATA[Christopher Graves]]></dc:creator><pubDate>Wed, 14 Apr 2021 16:43:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/03/spacealpha.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/03/spacealpha.png" alt="Game Review - SpaceAlpha.net"><p>As the very first game review for the PBBG.com blog, I feel it's my duty to make sure that I review a game that has enough meat to really dig into. I thought about doing a deep review of some of the larger, more predominant games in the community; but I recently had a chance to do one of our <a href="https://www.youtube.com/watch?v=Xvjb3UxFkhE">livestreams</a> [disclaimer: this is one of the first livestreams, please forgive the audio problems] on a great Sci-Fi PBBG known as <a href="https://spacealpha.net/">SpaceAlpha.net</a>. Coincidentally, that's also their URL. </p><p>[<em>See all of our future livestreams by <a href="https://twitch.tv/pbbgsite">following the pbbgsite channel on Twitch</a>!]</em></p><p><strong>As always, this game review contains spoilers for in-game content.</strong></p><p>Game: <a href="https://SpaceAlpha.net/">https://SpaceAlpha.net/</a><br>Discord: <a href="https://discord.gg/ZhffMmY">https://discord.gg/ZhffMmY</a></p><hr><!--kg-card-begin: markdown--><h1 id="concept">Concept</h1>
<!--kg-card-end: markdown--><p>SpaceAlpha is a Sci-Fi PBBG where you inhabit one of many planets orbiting a star. When starting out, you can choose your 'galaxy', which is more choosing which star your planet will orbit. Right out of the gate there's a lot of uniqueness, specifically you get to change the look of your planet and can choose from a LONG list of potential planet layouts. Want a planet with large orange continents and tons of maroon mountains? Want island chains and purple water? It's the planetary equivalent of a character creation screen. Don't like it? Change it all later!</p><p>In general, your goal is to spawn more 'Units', train them into specialties and wage war with your solar neighbors. Because.... what else are you going to do with billions of anonymous Units? You may get some serious <a href="https://trimps.github.io/">Trimps </a>vibes, mixed with some good 'ole long-term PvP. The concepts aren't novel, but SpaceAlpha gives enough spice between to make this worth playing.</p><!--kg-card-begin: markdown--><h2 id="score710">Score: 7/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="controluiintuitiveness">Control, UI, Intuitiveness</h1>
<!--kg-card-end: markdown--><p>Most PBBGs are about the information and the fun mechanics. They usually skimp a lot on graphics, or leave it entirely up to the community to enhance their UI (looking at you, Talibri and <a href="https://www.pendoria.net">Pendoria</a>). I mean, that's what sort of makes this genre iconic. However, SpaceAlpha's creator has decided to invest a lot of energy into the user interface. Once you get the first few strokes down, where everything is makes sense and is organized well. The popups are movable and don't block anything behind it, so you can easily multitask with larger displays. The actual graphics are hand-drawn and create a really quirky, under-stated humor to the game. It's all business in the numbers and graphs, but when it comes down to literally growing your new population from the ground and training them to be industrial workers, it has a certain self-aware aspect that is tastefully injected into the monotony we expect from idle games. Not to go without mention the charts and tables with numbers in them to make math nerds go weak in the knees. It's a min/max haven, built-in.</p><p>But that's not all, this PBBG features <em>sound</em>. The holy grail of instant-abandon-if-done-wrong feature. The sounds, in my most humble opinion, only add to the aforementioned quirky attitude. They're not high bitrate, Hans Zimmer scores meant to invoke your inner champion... they're lower quality and other-worldly in a way that completely matches the overall tone of the game in a way you really wouldn't expect. When you start training some of your new Units, there's a little creature's disgruntled mumbling that sounds off that gives you that 'I did a thing!' small kick for something super normal.  Not only that, there's a sound that plays when <em>a ship is traveling close to your planet</em>. Not quite sure how they managed to calculate that, but it can serve as a super useful feature for when one of your neighbors is sending their entire attacking fleet to enslave the Units of someone else, leaving them vulnerable to attack.</p><p>The only reason I didn't rate it a 10/10 is because the initial interface for quests and some of the sub-menus isn't perfectly intuitive, but this is a subjective perspective. I loosely had the voice of the creator in my ear when first starting out in our <a href="https://twitch.tv/pbbgsite">livestream</a>, but there are a few key windows I would have to stumble on over time.</p><!--kg-card-begin: markdown--><h2 id="score910">Score: 9/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="gamemechanics">Game Mechanics</h1>
<!--kg-card-end: markdown--><p>Everyone's favorite eyeroll, but this is definitely worth mentioning. SpaceAlpha has two distinct <strong>seamless</strong> modes; Micro and Macro.</p><p>Micro mode is all about population and planet control. You train your Units to be farmers, that literally grow new Units from the ground. From there, your untrained units need to be trained in some sort of specialty to <em>do</em> anything. Workers to generate income, soldiers to fight and defend, engineers to staff your facilities, scientists to staff your research, assassins to merc the poor sap nearby, and doctors to take care of your populace, etc. There's an aspect of planetary management you have to account for; sickness running through the population is mitigated by doctors, pollution generated by your facilities, and deforestation created by cutting trees to get coal to power your various ambitions. On top of that, you can force your Units to work in different modes on a scale from 'chilling' to 'NON-STOP'. This lets you really take cater to your schedule – online you work them non-stop then change back to a relaxed work schedule to make up the effort you expended beforehand while you're offline. Your empire has a happiness scale that determines how effective all of your Units are at their job, which can fluctuate with sickness, being overworked or being TOO unemployed (slackers), that can all be mitigated once the onset happens.</p><p>Macro mode is more about domination and PvP. The game features a Galaxy view that shows other planets and transiting fleets, which you have to upgrade using money to see farther and farther out. A clever and thematic gate to PvP, it takes some time to be able to see other players orbiting. There's a keyword there though, '<em>orbiting'</em>. As time goes on, the closest planets will orbit the star at a different rate than you, giving you access to quickly travel to nearby planets during certain time periods. So an abandoned planet with good resources will eventually orbit closer to me, making the trip faster. It also plays heavily into PvP, when you need to make successive strikes quickly along with your alliance. An experienced player will see what's up, but you can close the window as small as possible by playing the waiting game. There's also uncolonized planets that you can spread your (actual) seed on and claim as your own, adding to the complexity of both macro (defending now multiple planets) and micro (population and pollution management in multiple locations).</p><p>There's only one issue that I have so far with regards to Micro vs Macro. There's nothing specifically driving you toward the Macro play. You could build your planet and make sure you don't ruin it via pollution and deforestation, and never have a reason to join an alliance and go out murdering millions of other Units in the galaxy. Other than Slaves, which turn the game up from 1 to 11 really quickly – but you can buy those in the market much easier than you can actually capture them. The drawback could be mitigated by more players and more marauding enemies, so take this criticism with a grain of salt.</p><!--kg-card-begin: markdown--><h2 id="score810">Score: 8/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="replayability">Replayability</h1>
<!--kg-card-end: markdown--><p>The replayability here is pretty high due to the population control mechanics and PvP. However, at the start of the game, there is very little consequence to going idle for a couple of days at a time. No one really attacks you, and it takes a while before you're able to really tussle with anyone. Like, weeks at peak performance. This is definitely a 'set your defenses and attack during opportunity' type of game. You definitely can YOLO your way into a conflict and just hope for the best, but from my experience that is almost definitely a path to blowing away several million Units in one action.</p><!--kg-card-begin: markdown--><h2 id="score810">Score: 8/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="importantfactors">Important Factors</h1>
<!--kg-card-end: markdown--><p><strong>Catch-up mechanic</strong>; <em>Turns</em>. "But this is an idle game!" Yeah, not those turns. One of the great mechanics here is that you accrue 'turns' in game over time, which you can use to speed up almost everything, including Unit generation. It's one of the best examples of casual:hardcore gap fixing I've seen to date. I can NOT play for long hours and get the same boost in game as someone who is constantly playing. In addition, you can upgrade your generation of such turns and increase your capacity -- giving it an almost stand-alone mechanic.</p><p><strong>Premium currency</strong>. Yes, there is premium currency in the game that can be purchased through Dogecoin. As of the moment of writing, you can spend premium currency on refreshing your turns, but in the near future that will be phased out and changed to cosmetic-only features as the creator has told me.</p><p><strong>Launch reset.</strong> At time of writing, there will be no reset once the game launches. The creator is adamant about the philosophy of a persistent (and parallel) universe.</p><!--kg-card-begin: markdown--><h2 id="score910">Score: 9/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="community">Community</h1>
<!--kg-card-end: markdown--><p>Full disclosure, I started out playing the game as a streamer trying to advertise the game. The community was largely attentive and supportive by sending me some starter stuff to get going. After the stream, the community has continued to be a kind and pro-active group of players that are just there to have some fun. I've been really impressed with the attitude, the geographic diversity, and the complete absence of toxicity. The developer does a good job of fostering positivity by being really active in the <a href="https://discord.gg/ZhffMmY">Discord</a> to keep that energy going. The total number of players is pretty small, however, so that's the only reason it doesn't get a perfect score here.</p><!--kg-card-begin: markdown--><h2 id="score910">Score: 9/10</h2>
<!--kg-card-end: markdown--><hr><!--kg-card-begin: markdown--><h1 id="funfactor">Fun Factor</h1>
<!--kg-card-end: markdown--><p>This category is entirely subjective, and more about my entire experience in the game... which could obviously differ from yours substantially. I really enjoy the playful attitude that perfectly meshes with the PBBG genre, mesh that with a really well designed (and stable) UI, and you get a really phenomenal experience. The community helps to bring everything together and add extra dimension.</p><p>If you're looking to get into a bigger game early on the development process, this is what you're looking for!</p><!--kg-card-begin: markdown--><h2 id="score810">Score: 8/10</h2>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Making Egg Trainer 6]]></title><description><![CDATA[In this article, we're going to explore the concept of JSON web tokens, and how I've implemented them in the MERN-template. ]]></description><link>https://blog.pbbg.com/making-egg-trainer-6/</link><guid isPermaLink="false">604a4b206878724fc3385994</guid><dc:creator><![CDATA[Kayne Ruse]]></dc:creator><pubDate>Wed, 31 Mar 2021 04:00:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/03/article-6.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/03/article-6.png" alt="Making Egg Trainer 6"><p>In this article, we're going to explore the concept of <a href="https://en.wikipedia.org/wiki/JSON_Web_Token">JSON web tokens</a> (or JWTs for short), and how I've implemented them in the MERN-template. If you're coming here from previous articles, you should know that this authentication method has replaced the "key" system outlined in "Making Egg Trainer 2" - such is the nature of evolving software.</p><h3 id="background">Background</h3><p>First, I should outline what lead me to JWTs. I decided that the login/logout system of the MERN-template deserved it's own <a href="https://en.wikipedia.org/wiki/Microservices">microservice</a> treatment, to match the <a href="https://github.com/krgamestudios/news-server">news-server</a> and <a href="https://github.com/krgamestudios/chat-server">chat-server</a>. This has come to be called the <a href="https://github.com/krgamestudios/auth-server">auth-server</a> (I also seem to have a thing for four-lettered words).</p><p>At first I had the chat logic running through the MERN-template to "reserve" a player's name in the chat-server, but once the auth-server needed separating I knew this wouldn't suffice. One of the developers in the awesome PBBG discord recommended I research JWTs, and I fell in love (with the JWT, not the person).</p><h3 id="premise">Premise</h3><p>JWTs, are an interesting concept; basically, you begin with a "payload", which is what you want to encode in the token.</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  "id": "4",
  "username": "Ratstail91",
  "privilege": "administrator",
  "exp": "600"
}</code></pre><figcaption>"exp" will actually be much larger than this.</figcaption></figure><p>You also need a header containing the algorithm information.</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  "alg":"HS256",
  "typ":"JWT"
}</code></pre><figcaption>I didn't know the algorithm used until now.</figcaption></figure><p>Then, you combine the header and payload, converting both to <a href="https://en.wikipedia.org/wiki/Base64">base64</a> and separating them with a period.</p><figure class="kg-card kg-code-card"><pre><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywidXNlcm5hbWUiOiJSYXRzdGFpbDkxIiwicHJpdmlsZWdlIjoiYWRtaW5pc3RyYXRvciIsImlhdCI6MTYxNTQ4MjgwMiwiZXhwIjoxNjE1NDgzNDAyfQ</code></pre><figcaption>This makes sense when decoded.</figcaption></figure><p>Finally, you hash this string using the algorithm identified by the header, and add that to the end (separated by another period).</p><figure class="kg-card kg-code-card"><pre><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywidXNlcm5hbWUiOiJSYXRzdGFpbDkxIiwicHJpdmlsZWdlIjoiYWRtaW5pc3RyYXRvciIsImlhdCI6MTYxNTQ4MjgwMiwiZXhwIjoxNjE1NDgzNDAyfQ.G-pTYEnP5kSzOad72FmGBSKW53a6GNaUqb_1i0A070U</code></pre><figcaption>An actual JSON web token generated by the auth-server.</figcaption></figure><p>The beauty of this is that you can decode it easily for the payload information (such as username, account privilege, and any other information stored within), and you can also ensure that it hasn't been altered by a malicious party, thanks to the hashed information - if the hash doesn't match, then there's a problem.</p><p>Also, there's a concept called <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">public key cryptography</a> that I am not currently using, but will likely end up using by the end of this process. It's a bit too advanced to cover in this article though. just know that it's just as valid for JWTs as what I'm currently using. Maths is fun!</p><h3 id="refresh-tokens">Refresh Tokens</h3><p>So, now that we have a token that proves our identity, we need to keep it super secure to ensure that nobody can steal it. The problem with this is that no system is ever 100% secure...</p><p>To resolve this, I've added an "exp" field to the payload, defining the number of seconds since Jan 1st 1970 (also called <a href="https://en.wikipedia.org/wiki/Unix_time">unix time</a>). This lets me simply reject any tokens that are too old. By default, the auth-server gives tokens about 10 minutes of validity.</p><p>Again, you've probably noticed a problem - if tokens are only valid for 10 minutes, then the user will always be logged out automatically when it expires. I wish i had come up with some brilliant solution for this, but I'm just using the same technique everyone else does; I split the token into two tokens: the access token and the refresh token.</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywidXNlcm5hbWUiOiJSYXRzdGFpbDkxIiwicHJpdmlsZWdlIjoiYWRtaW5pc3RyYXRvciIsImlhdCI6MTYxNTQ4MjgwMiwiZXhwIjoxNjE1NDgzNDAyfQ.G-pTYEnP5kSzOad72FmGBSKW53a6GNaUqb_1i0A070U",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywidXNlcm5hbWUiOiJSYXRzdGFpbDkxIiwicHJpdmlsZWdlIjoiYWRtaW5pc3RyYXRvciIsImlhdCI6MTYxNTQ4MjgwMiwiZXhwIjoxNjE4MDc0ODAyfQ.o2ZI8Dlgv95gx2EcFDIwdklNcZ7varcwWGXdGer0BCE"
}</code></pre><figcaption>I've already invalidated this refresh token - no hacking allowed!</figcaption></figure><p>The basics concept is simple - the access token is used for general communication with the game's network of servers, and when it expires, you ping the auth-server again with the refresh token to get another token pair. This way, the access token which gets shared around can only be stolen for up to 10 minutes at most.</p><p>This does mean that if you steal the refresh token (which doesn't expire at all), you'll be able to refresh token pairs continuously. Thankfully, the auth-server actually checks the database for existing refresh tokens before issuing new pairs. If the player simply sends a valid logout request, then that refresh token is deleted and refreshing the access token is impossible. Security is fun!</p><h3 id="implementation">Implementation</h3><p>Here's the tricky part.</p><p>I spent several days fiddling with cookies, JWTs and the like trying to get some solution that worked smoothly and securely. Finally, I ended up with this <a href="https://github.com/krgamestudios/MERN-template/blob/9b6c5af09dbf4064818a63a79fd4d060e67682a3/client/components/utilities/token-provider.jsx">react provider as the result</a>.</p><p>What's going on here is way more complex than i wanted for an intermediate difficulty tool - so lets go through it together to understand what's happening.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">ReactDOM.render(
	&lt;TokenProvider&gt;
		&lt;App /&gt;
	&lt;/TokenProvider&gt;,
	document.querySelector('#root')
);</code></pre><figcaption>TokenProvider</figcaption></figure><p>React has a concept called "<a href="https://reactjs.org/docs/context.html">Context</a>", which is a way to provide global utilities or information through out an application without requiring that the user pass down props from parent to child. Contexts have "Providers" which are what actually provide the information to the render tree. just above you can see the token Provider wrapping the MERN-template's client application.</p><pre><code class="language-jsx">import React, { useState, useEffect, createContext } from 'react';
import decode from 'jwt-decode';

export const TokenContext = createContext();

const TokenProvider = props =&gt; {
	...

	return (
		&lt;TokenContext.Provider value={...}&gt;
			{props.children}
		&lt;/TokenContext.Provider&gt;
	)
};

export default TokenProvider;</code></pre><p>Here's the simplest breakdown of the token Provider. You can see the file creates and exports a context, then wraps the TokenProvider's children with the context's provider member. I've omitted stuff from the body and from the argument "value".</p><pre><code class="language-jsx">{
  accessToken,
  refreshToken,
  setAccessToken,
  setRefreshToken,
  tokenFetch,
  getPayload: () =&gt; decode(accessToken)
}</code></pre><p>Here are the arguments to the providers "value" argument that I omitted. The first four are actually easy - they're just the result of <code><a href="https://reactjs.org/docs/hooks-state.html">useState</a></code> - these are the actual accessToken and refreshToken that are used throughout the program.</p><p>The last argument is <code>getPayload</code>, which simply wraps a call to decode the access token - literally just a way to get the contents of the tokens.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import React, { useContext, useRef } from 'react';
import { Redirect } from 'react-router-dom';

import { TokenContext } from '../utilities/token-provider';

const LogIn = props =&gt; {
	//context
	const authTokens = useContext(TokenContext);

	//misplaced?
	if (authTokens.accessToken) {
		return &lt;Redirect to='/' /&gt;;
	}
    ...</code></pre><figcaption>Login uses the auth tokens to check if the user is already logged in, and redirects them to the homepage if they are.</figcaption></figure><p>Here's snippet from <code><a href="https://github.com/krgamestudios/MERN-template/blob/main/client/components/pages/login.jsx">login.jsx</a></code>, showing the usage of the contexts. By using the react hook <code>useContext</code>, and passing in <code>TokenContext</code> you gain access to the "value" argument that was passed to the created context's provider above.</p><h3 id="tokenfetch">tokenFetch</h3><p>OK, last big section, I think.</p><p>There's one member of the context value that I skipped over earlier - tokenFetch. This is a wrapper function around the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"><code>fetch()</code> API</a>. It's purpose is to refresh the token pair when the access token is expired - and do so invisibly to the user.</p><p>It should be noted that tokenFetch is only used for functions where it is appropriate - namely where the user is already logged in. Other times, just using <code>fetch()</code> is enough.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">//wrap the default fetch function
const tokenFetch = async (url, options) =&gt; {
	//use this?
	let bearer = accessToken;

	//if expired (10 minutes, normally)
	const expired = new Date(decode(accessToken).exp * 1000) &lt; Date.now();

	if (expired) {
		...
	}

	//finally, delegate to fetch
	return fetch(url, {
		...options,
		headers: {
			...options.headers,
			'Authorization': `Bearer ${bearer}`
		}
	});
};</code></pre><figcaption>tokenFetch, broken down.</figcaption></figure><p>Here, lets look at what happens when the token is NOT expired. Basically, the accessToken's value is stored in <code>bearer</code>, the expiry boolean is checked, and finally fetch is called, with the <code>Authorization</code> header injected (<code>bearer</code> is an argument for <code>Authorization</code>).</p><p>Straight forward; this is what should normally happen.</p><pre><code class="language-jsx">//ping the auth server for a new token
const response = await fetch(`${process.env.AUTH_URI}/token`, {
	method: 'POST',
	headers: {
		'Content-Type': 'application/json',
		'Access-Control-Allow-Origin': '*'
	},
	body: JSON.stringify({
		token: refreshToken
	})
});

//any errors, throw them
if (!response.ok) {
	throw `${response.status}: ${await response.text()}`;
}

//save the new auth stuff (setting bearer as well)
const newAuth = await response.json();

setAccessToken(newAuth.accessToken);
setRefreshToken(newAuth.refreshToken);
bearer = newAuth.accessToken;
</code></pre><p>However, if the token IS expired, this happens first - a POST request to the auth-server carrying the refresh token in it's body. Then, if that response went OK, it retrieves the new <code>accessToken</code> and <code>refreshToken</code>, sets them and sets <code>bearer</code> to the value of the new access token. Finally, it proceeds with tokenFetch's original task.</p><p>I should also mention that there's a bugfix inside the expired block - if the user is trying to log out, (by pinging <code>${process.env.AUTH_URI}/logout</code>), then the process intercepts this and sends it's own logout message. This only happens when the user is trying to log out with an expired <code>authToken</code>.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">const [accessToken, setAccessToken] = useState('');
	const [refreshToken, setRefreshToken] = useState('');

	//make the access and refresh tokens persist between reloads
	useEffect(() =&gt; {
		setAccessToken(localStorage.getItem("accessToken") || '');
		setRefreshToken(localStorage.getItem("refreshToken") || '');
	}, [])

	useEffect(() =&gt; {
		localStorage.setItem("accessToken", accessToken);
		localStorage.setItem("refreshToken", refreshToken);
	}, [accessToken, refreshToken]);</code></pre><figcaption>Let's stick the token's declaration here for completeness. They're stored in localStorage.</figcaption></figure><h3 id="conclusion">Conclusion</h3><p>Don't you just love technical articles?</p><p>The JWTs are powerful, because they contain all of the authority that the player needs to play the game. They also carry information such as the admin status, so administrators can access the admin panel and do... admin stuff. This is also the reason you can no longer easily modify the content of the news-server, sorry!</p><p>Only my user account has admin privileges on the auth server... so if you want to try and modify the news-server's content, you can request an auth token pair using this:</p><pre><code class="language-REST">POST https://dev-auth.eggtrainer.com/auth/login HTTP/1.1
Content-Type: application/json

{
	"email": "kayneruse@gmail.com",
	"password": "helloworld"
}</code></pre><p>Using this, you send another request like this to the news server:</p><pre><code class="language-REST">POST https://dev-news.eggtrainer.com/news HTTP/1.1
Content-Type: application/json
Authorization: Bearer XXX

{
	"title": "Hello World",
	"author": "Kayne Ruse",
	"body": "Lorem ipsum."
}</code></pre><p>Replace XXX with your new accessToken. The full APIs for the auth and news servers are available in their README files.</p><ul><li><a href="https://github.com/krgamestudios/auth-server">https://github.com/krgamestudios/auth-server</a></li><li><a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a></li></ul><p>GET request to the news-server should work as they always have (except "titles" was changed to "metadata" - always check the latest docs!). Software is fun!</p><p><em><em>My name is Kayne Ruse of KR Game Studios, you ca</em>n find me on the net as Ratstail91, trying to decrypt the Voynich Manuscript using brute force.</em></p><ul><li><em>Egg Trainer Website: <a href="https://eggtrainer.com/">https://eggtrainer.com/</a></em></li><li><em>MERN-template repo: <a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a></em></li><li>auth-server repo: <a href="https://github.com/krgamestudios/auth-server">https://github.com/krgamestudios/auth-server</a></li><li><em>news-server repo: <a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a></em></li><li><em>chat-server repo: <a href="https://github.com/krgamestudios/chat-server">https://github.com/krgamestudios/chat-server</a></em></li><li><em>Business Inquiries: krgamestudios@gmail.com</em></li></ul>]]></content:encoded></item><item><title><![CDATA[Making Egg Trainer 5]]></title><description><![CDATA[<p><em>In this article, it's best that you read in the voice of Sir David Attenborough, as we're exploring some of the lore behind certain creatures. No, this isn't a fluff article because I ran out of things to write about. I wouldn't do that. At all.</em></p><p><em>Special thanks to my</em></p>]]></description><link>https://blog.pbbg.com/making-egg-trainer-5/</link><guid isPermaLink="false">603cfbac6878724fc3385778</guid><dc:creator><![CDATA[Kayne Ruse]]></dc:creator><pubDate>Mon, 15 Mar 2021 13:00:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/03/article-5.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/03/article-5.png" alt="Making Egg Trainer 5"><p><em>In this article, it's best that you read in the voice of Sir David Attenborough, as we're exploring some of the lore behind certain creatures. No, this isn't a fluff article because I ran out of things to write about. I wouldn't do that. At all.</em></p><p><em>Special thanks to my artist HighLanderPony for some of the Tikuma lore.</em></p><h3 id="taxonomy">Taxonomy</h3><p>They're very strange, these creatures of Egg Trainer - they can interbreed with each other regardless of shape and size, and even produce offspring that do not resemble the parent creatures at all. And stranger still, they all come from eggs. They also seem to have "elemental types" and "rarities" which affect the shape and hatching time of their eggs. Listed here are just a handful of these strange, marvelous creatures, and their common behaviors.</p><h3 id="slink">Slink</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/03/article-1.png" class="kg-image" alt="Making Egg Trainer 5"><figcaption>Slink, and the psychic egg</figcaption></figure><p>The slink is quite possibly the ultimate ambush predator. It's cute, furry head draws in those unsuspecting of it's true nature, while it's lithe body and venomous fangs make short work of those who stray too close. It's deceptive nature certainly earns it a place among the psychic types.</p><p>Due to the thin layer of fuzz that covers their bodies, they can survive quite well in colder climates, where snake-like creatures (and those who prey on them) are hard to come by. Meanwhile, it's cat-like head and seemingly affectionate behaviors sometimes lead to it being kept as pets in some more remote parts of the world - however, the practice of defanging and devenoming a slink is quite painful for the creature, and modern experts implore would-be owners to leave the handling of the dangerous creatures to experts.</p><h3 id="pixi">Pixi</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/03/article-2.png" class="kg-image" alt="Making Egg Trainer 5"><figcaption>Pixi, with the fae egg</figcaption></figure><p>Pixis are a nuisance no matter where they appear. Growing to the size of a human hand, they can often squeeze into nooks and crannies, and set up nests that are a hazard to one's safety. A nest of pixis is best dispatched quickly and efficiently, before the effects of "fae dust" take hold. If the well known properties of fae dust takes hold, your best option is to strap down the affected object to prevent it from floating away.</p><p>Low in intelligence, they nonetheless feature in many a child's bedtime story, where their mischievous natures are the cause of grief to some medieval settlement. Some stories, however attribute more than their fair share of sense to them, with one notable story bearing a protagonist who is half-pixi, granting him supernatural powers.</p><h3 id="tikuma">Tikuma</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/03/article-3.png" class="kg-image" alt="Making Egg Trainer 5"><figcaption>Tikuma, with the fire egg</figcaption></figure><p>Similar in appearance to a floating tiki head, this quick tempered creature burns with spiritual flames when threatened. It usually lays dormant in the sands or grounds around places of worship; treasure hunters often provoke it while attempting to alleviate it of its precious, and valuable, forehead jewel. Said jewel can be one of several kinds of gems, and is linked to the primary color of it's flame.</p><p>Certain times of the year are celebrated as holy among the peoples where Tikuma reside. At these times, many Tikuma gather from across the lands to reproduce in what can only be called a dance ritual. Massive burning circular structures fill the skies, while the people sing traditional songs to praise the creatures above. In the morning, the people climb the hills and mountains to find vast arrays of fire eggs stacked neatly in nests of soil.</p><h3 id="predatore">Predatore</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/03/article-4.png" class="kg-image" alt="Making Egg Trainer 5"><figcaption>Predatore, and the metal egg</figcaption></figure><p>This rare and beautiful bird of prey has seen dwindling numbers in recent years, due to the encroachment of human habitation. Coming in a vast variety of crystalline colors, this rocky bird has no difficulty flying despite it's weight. The forests and mountains that make up it's home dictate the colors of it's feathers, based on the minerals in the ground. </p><p>Predatores live extremely long lives, but they only lay one egg at a time, and care for the young for several years. This hampers conservation efforts that have been trying to boost their numbers. There does seem to be a light at the end of the tunnel though, as introducing specific kinds of rare stones into one's environment will often grant the offspring a duller, more stealthy sheen.</p><h3 id="season-long">Season Long</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/03/article-5-1.png" class="kg-image" alt="Making Egg Trainer 5"><figcaption>Season Long (fall foliage), and the dragon egg</figcaption></figure><p>At last, we come to the master of the skies, the true emperor of all it sees, and protector of the seasons - the Season Long. This creature is so in tune with it's environment, any imbalances to nature cause this dragon to enter a ceaseless rage. Few in number, they're the only one on this list to bear the "mythic" rarity. The discovery of a previously unknown Season Long often makes headlines around the world - the last such discovery was twenty years ago.</p><p>It's horns are in fact living trees, which sprout new foliage in the spring and wilt in the fall, in preparation for winter. "To be granted a springtime flower" is said to be blessed by a Season Long, as the flowers that bloom in the springtime are believed to be a panacea when brewed into a tea.</p><h3 id="conclusion">Conclusion</h3><p>It's not every day you come across one of these creatures, and it's best to leave their care and maintenance to experts. In recent times, individuals known as "Egg Trainers" have appeared, who have seemingly mastered the art of training these beautiful beasts to fight. Whether you aspire to join their ranks, or wish to admire them from the sidelines, I implore you to remember, these creatures are living beings, and deserve just as much respect as your fellow man. Alas, I fear my pleas will fall on deaf ears.</p><p><em><em>My name is Kayne Ruse of KR Game Studios, you can find me on the net as Ratstail91, </em>often pretending to narrate nature documentaries.</em></p><p><em>Egg Trainer Website: <a href="https://eggtrainer.com/">https://eggtrainer.com/</a></em></p><p><em>MERN-template repo: <a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a></em></p><p><em>news-server repo: <a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a></em></p><p><em>chat-server repo: <a href="https://github.com/krgamestudios/chat-server">https://github.com/krgamestudios/chat-server</a></em></p><p><em>Business Inquiries: krgamestudios@gmail.com</em></p>]]></content:encoded></item><item><title><![CDATA[Making Egg Trainer 4]]></title><description><![CDATA[In this article, we'll go over the creatures, how they're designed, developed and implemented. We'll also talk about moves and their effects, and we might also touch on the items further down.]]></description><link>https://blog.pbbg.com/making-egg-trainer-4/</link><guid isPermaLink="false">60325cdb6878724fc33855db</guid><dc:creator><![CDATA[Kayne Ruse]]></dc:creator><pubDate>Mon, 08 Mar 2021 13:00:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/02/article-4.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/02/article-4.png" alt="Making Egg Trainer 4"><p>Phew, the last few articles have been pretty technical, so lets have a nice gameplay-focused one today.</p><p>We'll go over the creatures, how they're designed, developed and implemented. We'll also talk about moves and their effects, and we might also touch on the items further down.</p><h3 id="premise">Premise</h3><p>Egg Trainer allows you to buy and hatch eggs, train the creatures inside, and battle them against real life opponents. Each creature has a set number of moves, as well as species-specific statistics (try saying that three times fast). On top of that, genetics and training play into a specific creature's final stats.</p><p>If this sounds like Pokemon, you're right on the money - it was heavily inspired by it.</p><h3 id="basics">Basics</h3><p>The basic creature concept begins with an idea - this can be something as simple as a pun, or for a lot of the common creatures, can be something like a fusion of two animals. We have an internal document called "thumbnails.png" which actually lists a number of ideas, simply by outlining their silhouettes.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pbbg.com/content/images/2021/02/thumbnails-1.png" class="kg-image" alt="Making Egg Trainer 4"><figcaption>thumbnails.png, with some mythic concepts blanked out - green are already illustrated</figcaption></figure><p>(I've removed some mythic concepts because I want to keep the mythics under wraps.)</p><p>They're divided along their types and rarities - common, uncommon, rare and mythic. There's no evolution in this game, so what you see is what you get. Not all of the creatures have been planned, or even illustrated yet - we're still deep in development.</p><p>Each week, my artist or I chooses a concept on the thumbnails document to begin working on. We brainstorm a name for the creature, some backstory/lore, and my artist begins illustrating that creature. They share the line art throughout to ensure I'll like the final result, and finally they usually deliver at the end of the week, at which point we discuss more ideas or concepts, or even alter existing ones (you'll notice that the rare dragon is pink, for example - that one was originally drawn in the fairy row, for instance).</p><p>Some ideas do get outdated or rejected entirely (like the protog, which was replaced by the puggy), but generally we're not far enough through development to throw too much away.</p><h3 id="elements">Elements</h3><p>First, lets discuss the creatures' elemental types. There are 10 elements in Egg Trainer, ranging from the classic fire-water-grass triangle, to more unusual types like fae and dragon. Each type has a number of strengths and weaknesses. Below is a JSON array defining those strengths and weaknesses (outer is attacker, inner is defender):</p><pre><code class="language-json">{
	"fire": {
		"water": 0.5, "grass": 2, "dark": 2
	},
	"water": {
		"fire": 2, "grass": 0.5, "light": 2
	},
	"grass": {
		"fire": 0.5, "water": 2, "fae": 2
	},
	"psychic": {
		"fighting": 2, "metal": 0.5
	},
	"fighting": {
		"psychic": 2, "fae": 0.5
	},
	"metal": {
		"fae": 2, "water": 0.5
	},
	"fae": {
		"dark": 2, "light": 0.5
	},
	"light": {
		"dark": 2, "dragon": 0.5
	},
	"dark": {
		"dragon": 2, "fire": 0.5
	},
	"dragon": {
		"fire": 2, "psychic": 2, "fae": 0.5, "dark": 0.5
	}
}</code></pre><p>The strengths and weaknesses are strictly 2x and 0.5x at the moment, but these can in theory be tweaked later during development or even post launch. I'd like the exact balancing of elemental types, creatures, etc. to be publicly available knowledge, so that no one person has an inside advantage against another (maybe a fan-driven wiki would be good?).</p><h3 id="moves">Moves</h3><p>Next, let's look at moves. There's about 20 moves so far, so I won't post them all - let's look at a few examples instead.</p><pre><code class="language-json">{
	"tackle": {
		"name": "Tackle",
		"description": "The user charges into the target.",

		"type": "physical",
		"element": "fighting",

		"damage": 5,
		"value": 10
	},

	"firespit": {
		"name": "Fire Spit",
		"description": "The user spits fire at their opponent.",

		"type": "physical",
		"element": "fire",

		"damage": 15,
		"value": 10,

		"meta": {
			"signature": "spitty"
		}
	},

	"meteor": {
		"name": "Meteor",
		"description": "The user summons a fireball from the sky.",

		"type": "magical",
		"element": "fire",

		"damage": 10,
		"value": 10
	},
	...
}</code></pre><p>It's another JSON structure! The keys are unchanging references to specific moves - these are what are used in the creature structures. They have a name (which can be different from the key), a description, a type (either physical or magical), and an element (one of the 10 listed above). Magical and Physical will eventually have an impact, based on other contextual elements of the battle. Physical typed moves use the creature's strength, while magical typed attacks use the creature's power - and they may have other contextual effects. I'd like certain elements to lean towards one over the other, but it's not essential.</p><p>Finally, they each have a base damage value and cost value (here called "value" - that needs fixing). These need to be balanced later in development, during beta testing.</p><p>There's also the "meta" structure, which contains contextual information, which may be absent. For example, if a move is a signature of a specific creature (or specific type), then it is listed here ("fire spit" is the signature of "spitty"). Tools can be used later to double check consistency.</p><p>The meta structure will also contain any serialized effect functions that moves may have (such as boosting stats in certain whether, etc). This can be done by saving the JavaScript code as text, and deserializing it - strange, but it works.</p><h3 id="species">Species</h3><p>The "species" of a creature is a large determining factor of what that creature can do, and even what it is. The species structure also contains the egg data about that species in particular.</p><pre><code class="language-json">{
	
	"spitty": {
		"name": "Spitty",
		"element": "fire",
		"description": "A llama-like creature with fire-infused wool. It spits fire at anything that annoys it.",

		"egg": {
			"rarity": "common",
			"value": 200
		},

		"stats": {
			"health": 10,
			"speed": 10,
			"physicalAttack": 10,
			"physicalDefense": 10,
			"magicalAttack": 10,
			"magicalDefense": 10
		},

		"moves": [ "tackle", "firespit", "babyeyes" ],

		"frontImage": "spitty.png"
	},
	"whalephant": {
		"name": "Whalephant",
		"element": "water",
		"description": "A majestic deep-sea creature, known for never forgetting. It has a prehensile nose.",

		"egg": {
			"rarity": "common",
			"value": 200
		},

		"stats": {
			"health": 10,
			"speed": 10,
			"physicalAttack": 10,
			"physicalDefense": 10,
			"magicalAttack": 10,
			"magicalDefense": 10
		},

		"moves": [ "splash", "watercannon", "babyeyes", "babyfat", "thunderclap" ],

		"frontImage": "whalephant.png"
	},
	...
}</code></pre><p>The structure (which currently only contains the 9 common creatures, but we're cutting it down anyway) also use JSON. It's JSON all the way down!</p><p>Each creature has a display name, it's element (creatures only ever have one element), a description, the egg data (such as it's rarity and that egg's cost... which probably should be moved to an external structure), the stats block, a list of moves stored in an array, and the image file name (named frontImage, because I originally thought there'd be more than one).</p><p>The stats block contain the base stats for that specific species - it's health, speed, physical attack, physical defense, magical attack and magical defense. The moves are just a list of keys, referencing the keys from the previous section.</p><p>Again, these all have dummy stats, which will be balanced later in the game's development, when combat is working.</p><h3 id="creatures">Creatures</h3><p>Again, I've fallen into technical talk, but at least you know what goes into creating a specific species of creature. In general, I want to design a well-rounded roster, with rarer creatures having slightly stronger stats, but with openings for counter play from lower rarities.</p><p>So lets look at the structure for individual creatures (pseudocode this time, because the real thing is ugly SQL):</p><pre><code class="language-pseudocode">creature:
    profileId
    nickname
    species
    geneticPoints:
    	health
        speed
        strength
        power
    trainingPoints:
    	health
        speed
        strength
        power
    trainingFinish
    trainingType
    breeding</code></pre><p>The profileId simply references which profile owns the creature. The Nickname is a field for storing a custom name, but was never implemented (I'm not sure why). Then you have the species of the creature, indicating a lot about it (such as some of it's stats, and it's moves, etc.)</p><p>Next, you have it's genetics - these don't change throughout a creature's life, but they do largely carry down from parents to children. The process as thus:</p><ul><li>Take 1 random stat from the mother</li><li>Take 1 random stat from the father</li><li>Take 1 random stat from either parent</li><li>Randomize the last stat</li></ul><p>Which creature is the mother and father is largely unimportant (the creatures don't have genders). The genetic stats can be between 0 and, I think 15? But that may change.</p><p>The next part is training - each creature has a set number of points (16, to be exact) that they can allocate between their stats to customize them (each time you allocate to a specific stat, it takes a number of minutes equal to that stat's new value).</p><p>"trainingFinish" is the finish time of the training, and is null if the creature isn't training. The "trainingType" is which stat is being trained (health, speed, power or strength). Finally, breeding is if this creature is breeding or not.</p><p>The creature's purchased moves are stored in their own database table.</p><h3 id="eggs">Eggs</h3><p>Players buy eggs from the in-game shop using in-game coins. They then hatch these eggs over a period of time, using an incubator. Players have one incubator to begin with, and can buy more as they progress. This is a basic limit on the number of creatures that can enter the ecosystem at a time, based on the number of players.</p><p>Each egg has a specific element and rarity, which can be determined simply by looking at it. However what kind of creature hatches from that egg is randomly chosen from that element and rarity, so you can theoretically have more than one creature in a specific thumbnails.png slot (this will come way later in development).</p><p>Apart from this, the eggs also hold genetic data which is passed onto the hatched creature.</p><h3 id="items">Items</h3><p>There are two types of items - normal items and premium items. Normal items can be purchased using in-game coins, while premium items require microtransactions to obtain. Their data is stored separately, but generally they're identical in structure.</p><pre><code class="language-json">{
	"potion": {
		"name": "Potion",
		"type": "consumable",
		"value": 50,
		"sprite": "potion.png",
		"description": "For healing creatures during battles. Single use.",

		"shop": "constant",

		"meta": {
			"effect": "heal",
			"value": 10
		}
	},
    ...
}</code></pre><p>Here we see a potion object, with an immutable key that can be referenced elsewhere, a name, the type (types are "static" and "consumable"), the value (in in-game coins), the sprite file name, the description (which honestly, should be placed under the name), the "shop" value (which, while unimplemented, will be either "constant" or "rotate"), and a contextual meta structure.</p><p>The meta field contains things like the effect of the item ("heal", "hatch", etc.) and any other values needed by that item. There is also a "minQuanity" and "maxQuantity" field in the item's body that needs to be moved to the meta structure (you must have between 1 and 2 incubators, currently).</p><pre><code class="language-json">{
	"goldenapple": {
		"name": "Golden Apple",
		"type": "consumable",
		"value": 199,
		"sprite": "goldenapple.png",
		"description": "For healing creatures during battles. Single use.",

		"shop": "constant",
		"premium": true,

		"meta": {
			"effect": "heal",
			"value": 10
		}
	},
    ...
}</code></pre><p>Here, you can see a premium item - this is what you pay for with real money. The fields are largely the same; in fact, golden apples are duplicates of potions. The only difference is the "premium" field, which is set to "true", and the "value" field, which list the price in cents, AUD. (I'm currently using Australian dollars because I was inexperienced with PayPal's API first time round - I'm hoping to change it to USD.)</p><p>Premium items are theoretically how I'll support the game's development costs. Consumable items will be single-use for each combat - you can only use one potion for the entire battle. This is what makes golden apples desirable - they're essentially an extra potion. My intent is not to create a pay-to-win situation, but rather a risk-vs-reward situation: should you spend your entire move to use a premium item, and potentially risk other elements of the battle?</p><h3 id="conclusion">Conclusion</h3><p>Wow, another massive article over. Hopefully you understand what goes into making a specific species of creature, as well as what makes up the creatures in general. Also, the items were a bonus throw-in. This did become technical with JSON structures again, but hopefully JSON is understandable by most readers (and I hopefully explained each one well enough).</p><p><em>My name is Kayne Ruse of KR Game Studios, you can find me on the net as Ratstail91, usually researching something. Have you ever heard of the <a href="https://en.wikipedia.org/wiki/MDA_framework">MDA framework</a>?</em></p><p><em>Egg Trainer Website: <a href="https://eggtrainer.com/">https://eggtrainer.com/</a></em></p><p><em>MERN-template repo: <a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a></em></p><p><em>news-server repo: <a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a></em></p><p><em>Business Inquiries: krgamestudios@gmail.com</em></p>]]></content:encoded></item><item><title><![CDATA[Making Egg Trainer 3]]></title><description><![CDATA[This article is the basis of the tutorial. So it's a good starting place.]]></description><link>https://blog.pbbg.com/making-egg-trainer-3/</link><guid isPermaLink="false">602a4af06878724fc33854c8</guid><dc:creator><![CDATA[Kayne Ruse]]></dc:creator><pubDate>Mon, 01 Mar 2021 13:14:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/02/article-3.png" medium="image"/><content:encoded><![CDATA[<h2 id="setup-tutorial">Setup Tutorial</h2><img src="https://blog.pbbg.com/content/images/2021/02/article-3.png" alt="Making Egg Trainer 3"><p>Hello! This article is being used as the template for the setup tutorial for the MERN-template. So if you haven't already, I recommend you download the MERN-template from here:</p><p><a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a></p><p>You can read the latest version of the setup tutorial under <a href="https://github.com/krgamestudios/MERN-template/blob/main/docs/setup-tutorial.md">docs/setup-tutorial.md</a></p><p>Remember: This project isn't ready for deployment yet - it still has bugs galore.</p><h3 id="the-what-template">The What-Template?</h3><p>MERN can stand for a few things, but in this case it means "MariaDB, Express, React and Nodejs". This are a series of technologies commonly used to create websites.</p><p>I determined that I might want to reuse some parts of the website I was planning to make, so I wrote the template first, to make it easier to reuse. Then, I released it so other people could use it too.</p><h3 id="requirements">Requirements</h3><p>There are some requirements for this template, such as required software and a dedicated email. Software needed includes:</p><ul><li>git</li><li>Nodejs</li><li>MariaDB</li><li>Docker</li><li>docker-compose</li></ul><p>You'll also need an email address - if you use google, you'll need to enable "<a href="https://support.google.com/accounts/answer/6010255?hl=en#zippy=%2Cif-less-secure-app-access-is-off-for-your-account%2Cif-less-secure-app-access-is-on-for-your-account">less secure apps</a>" so external apps can access it. I've only used this site with google so far, but feel free to experiment with other mail hosts.</p><h3 id="setting-up-development">Setting Up Development</h3><p>For development, you'll need Nodejs and MariaDB installed and working. Remember to run <code>npm install</code> in the git repo after cloning.</p><p>First, run <code>sql/create_database.sql</code> on your mariaDB instance - this will create a database called <code>template</code> and a user called `template`@`%`. You can of course mess with this, but everything else here assumes you do so consistently.</p><p>Next, copy <code>.envdev</code> into <code>.env</code>, then fill out <code>.env</code> with your details. Here's a breakdown of each field and what they mean:</p><pre><code>WEB_PROTOCOL=http      # are you using HTTP or HTTPS?
WEB_ADDRESS=localhost  # what is your web domain?
WEB_PORT=3000          # what port is the game running on?</code></pre><p>The first two are used mainly for the email validation link at the moment - but they should still be configured correctly. <code>WEB_PORT</code> is used to specify which port the game operates on - when you reach the webpack stage, you won't access this port directly.</p><pre><code>MAIL_SMTP=smtp.example.com             # SMTP server
MAIL_USERNAME=foobar@example.com       # Email to be used
MAIL_PASSWORD=foobar                   # Password of that email account
MAIL_PHYSICAL=42 Placeholder Ave, USA  # Your physical mailing address</code></pre><p>Now, I've use exclusively google for this - and it shows. The first argument is usually set to <code>smtp.gmail.com</code>. The second is to your email account (a fake one is set in the code, <code>signup@WEB_ADDRESS</code>, but google overwrites this). The third is the plain text password for this account (so you should almost certainly use a dedicated email for this). The fourth is actually included in the validation email itself - it's a legal requirement of the USA's <a href="https://en.wikipedia.org/wiki/CAN-SPAM_Act_of_2003">CAN-SPAM</a> act of 2003, which goes over my head just a little (I try to appease as many jurisdictions as possible).</p><pre><code>DB_HOSTNAME=127.0.0.1         # Database address
DB_DATABASE=template          # database name
DB_USERNAME=template          # database user
DB_PASSWORD=pikachu           # database password
DB_TIMEZONE=Australia/Sydney  # database timezone</code></pre><p>This is fairly simple - but if you tinkered in <code>sql/create_database.sql</code>, do so here as well. <code>127.0.0.1</code> just means "this machine", of course. The timezone is my own timezone, but can be set to <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">any of these values</a> (I think - haven't tested them).</p><pre><code>SESSION_SECRET=secret
SESSION_ADMIN=adminsecret</code></pre><p>Finally, these are crucial in production - so much so that they're completely randomized by the configure script. Here, however, you can set them to anything. <code>SESSION_SECRET</code> is used by <code>express-session</code> to save user session details, while <code>SESSION_ADMIN</code> is used as a sort of password for the administrator accounts.</p><p>Finally, it's time to run <code>npm run dev</code>. This will begin the server in dev mode - it'll use the <code>concurrently</code> library to run both client and server in the same window, so you don't need two monitor terminals. If all goes well, the server should start pretty quickly, though the client will take a moment to compile.</p><p>When they're both ready, you can access <code>http://localhost:3001/</code> in a browser (NOT 3000) and the template site should load.</p><p>At this stage, your brand new website will call out to the <code>dev-news</code> server for news postings, so you'll get some lorem ipsum, and possibly other content (it's a publicly available server - don't blame me!).</p><p>The server should've created a default administration account (and outputted the email and password). By logging in with this, you can access <code>http://localhost:3001/admin</code> and post to or edit existing news posts.</p><p>From here, you can now start exploring and fiddling with the code. Feel free to contribute any changes via pull requests on github; I'm likely to accept them if they improve the overall experience. Even the docs are subject to updates, so check back if you need to.</p><h3 id="setting-up-deployment">Setting Up Deployment</h3><p>In a perfect world, deploying to a server would be as easy as:</p><pre><code>git clone https://github.com/krgamestudios/MERN-template.git
npm run configure
sudo docker-compose up --build</code></pre><p>Sadly, this isn't a perfect world. So let's instead break down what I did for the tentative deployment.</p><p>First, you'll need a server with a domain name. I personally pointed both <code>dev.eggtrainer.com</code> and <code>news.eggtrainer.com</code> at the same server (You might be able to separate the news server later - that's why there's two URLs). I'm using linode for this, but be aware that linode blocks email access until you open a ticket requesting permission to use emails from their servers. It's easy - just don't abuse their goodwill. I ended up using debian as the OS, but anything that runs node and docker should work.</p><p>Then, I installed git, node (for npm) and docker-compose on the new server. Then I cloned the MERN-template into the server. Note that I didn't install mariaDB or run <code>npm install</code> - docker-compose handles these.</p><p>Next I ran <code>npm run configure</code>, which takes in a number of arguments and spits out a number of config files. Here's the default prompts:</p><pre><code>Project Name (template): 
Project Web Address (example.com): 
Project Mail SMTP (smtp.example.com): 
Project Mail Username (foobar@example.com): 
Project Mail Password (foobar): 
Project Physical Mailing Address (&lt;empty&gt;): 
Project Database Username (template): 
Project Database Password (pikachu): 
News Name (news): 
News Web Address (news.example.com): 
News Database Username (news): 
News Database Password (charizard): 
News Query Key (&lt;random&gt;): 
Database Root Password (password): 
Database Timezone (Australia/Sydney): 
Support Email (foobar@example.com):</code></pre><p>These should generally be fairly self-explanatory, except the values in the parentheses can changed based on previous entries. If you make a mistake here, just re-run this. This script produces three files:</p><ul><li>docker-compose.yml</li><li>Dockerfile</li><li>setup.sql</li></ul><p><code>setup.sql</code> is invoked by <code>Dockerfile</code> to create the database if it doesn't already exist, and <code>docker-compose.yml</code> invokes <code>Dockerfile</code>, among a number of other built-in containers (mariaDB and news-server). This will update regularly so check back often. If you want to delete any files created by configure, just run <code>npm run clean</code>.</p><p>Finally, it's time to run <code>sudo docker-compose up --build</code>. You might actually need to run it several times, killing the first attempts, as I haven't weeded out certain bugs yet. Remember - it's only in alpha, and not ready for prime time just yet.</p><p>You now have a self-contained MERN-template container, mariaDB container, news-server container and <a href="https://traefik.io/">traefik</a> container.</p><h3 id="troubleshooting">Troubleshooting</h3><p><strong>Deploying the project didn't work?</strong></p><p>Try again. There are timing issues between the different containers that I still need to sort out. If it still doesn't work after 5-ish attempts, keep reading.</p><p><strong>Sequelize throws an error that a certain field is missing?</strong></p><p>If you just upgraded the template, try checking if any changes to the sequelize models have occurred. If so, you'll have to go into the mariaDB container and alter the database directly.</p><h3 id="conclusion">Conclusion</h3><p>OK, that's enough technical jargon and mumbo jumbo for a while. Next time, I promise we'll look at some actual design elements of Egg Trainer - things I've previously implemented, and things I plan to implement. You deserve it after two fully technical articles.</p><p><em>My name is Kayne Ruse of KR Game Studios, you can find me on the net as Ratstail91, usually tweaking someone's configuration files without their permission.</em></p><p><em>Egg Trainer Website: <a href="https://eggtrainer.com/">https://eggtrainer.com/</a></em></p><p><em>MERN-template repo: <a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a></em></p><p><em>news-server repo: <a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a></em></p><p><em>Business Inquiries: krgamestudios@gmail.com</em></p>]]></content:encoded></item><item><title><![CDATA[Making Egg Trainer 2]]></title><description><![CDATA[We're having a look at the news server. If you're familiar with a tool like cURL, you can follow along and play around with the live demo.]]></description><link>https://blog.pbbg.com/making-egg-trainer-2/</link><guid isPermaLink="false">601f74706878724fc3385222</guid><dc:creator><![CDATA[Kayne Ruse]]></dc:creator><pubDate>Mon, 22 Feb 2021 16:30:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/02/article-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/02/article-2.png" alt="Making Egg Trainer 2"><p><em>This article is valid up to <a href="https://github.com/krgamestudios/news-server/tree/v1.0.3">news-server v1.0.3</a> - to learn about the revised API, look out for "Making Egg Trainer 6".</em></p><p>Today, we're having a look at one of the microservices I mentioned in the last article: the news server. If you're familiar with a tool like <a href="https://en.wikipedia.org/wiki/CURL">cURL</a>, you can follow along and play around with the live demo of the news server (just be aware that any abuse of my dev server will lead to it's key being changed :P).</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/krgamestudios/news-server"><div class="kg-bookmark-content"><div class="kg-bookmark-title">krgamestudios/news-server</div><div class="kg-bookmark-description">An API centric news server. Contribute to krgamestudios/news-server development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/favicons/favicon.svg" alt="Making Egg Trainer 2"><span class="kg-bookmark-author">krgamestudios</span><span class="kg-bookmark-publisher">GitHub</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://avatars.githubusercontent.com/u/10509145?s=400&amp;v=4" alt="Making Egg Trainer 2"></div></a></figure><h3 id="premise">Premise</h3><p>I've made a few games in the past, such as <a href="https://kingdombattles.net/">kingdombattles.net</a> and the first iteration of <a href="https://eggtrainer.com/">eggtrainer.com</a>, which have great big news feeds on their front page. These feeds were updated almost daily during development (a trend that actually hurts in the long run - regular intervals are better), but they were markdown-file-based and acted through the game server itself, which led to any alterations to the feed requiring alterations to the core game itself.</p><p>At some point, I decided it might be interesting to try and implement the news feed as a separate program - a <a href="https://en.wikipedia.org/wiki/Microservices">microservice</a> - which would separate the concerns for me. I tried this with the <a href="https://github.com/krgamestudios/MERN-template">MERN-template</a> (which will become egg trainer soon enough), and the result was remarkable! I could now work with and on the server without worrying about breaking anything in the game, including the database.</p><h3 id="basics">Basics</h3><p>Without further ado, try typing the following into your terminal:</p><pre><code>curl http://dev-news.eggtrainer.com:3100/news
</code></pre><p>The tool used is curl, which you should hopefully be familiar with. It is requesting a resources from a development server hosted at <code>dev-news.eggtrainer.com</code>, via the port <code>3100</code>. Then, it asks specifically for the route <code>news</code>.</p><p>The main URL can be anything, depending on how you set up your <a href="https://en.wikipedia.org/wiki/Domain_Name_System">DNS</a> (I use google domains for this). However, <code>3100</code> is a setting specified by the configuration files (.env, or docker-compose.yml depending on it's release), while <code>/news</code> is a route chosen to allow other possible future routes to be implemented (such as <code>/admin</code>, etc.)</p><p>The result you get back from curl should be a <a href="https://en.wikipedia.org/wiki/JSON">JSON</a> array, containing objects detailing the published articles. This is the result that the front end of the template (and potentially other programs) can process into a nice pretty news feed. As it's currently set up, only the last 10 articles will be shown. The "index" field is it's absolute index, counting from the beginning.</p><pre><code class="language-json">[
  {
    "index": 1,
    "title": "Hello World",
    "author": "Kayne Ruse",
    "body": "This is the body of the article.",
    "edits": 0,
    "createdAt": "2021-02-04T08:46:37.000Z",
    "updatedAt": "2021-02-04T08:46:37.000Z"
  },
  ...
]
</code></pre><h3 id="other-options">Other Options</h3><p>Some other options are available for simple GET commands like the one used above:</p><pre><code>//access the articles, starting from the beginning
curl dev-news.eggtrainer.com:3100/news/archive

//access only the metadata of the articles (everything but the body)
curl dev-news.eggtrainer.com:3100/news/titles

//access only the metadata of the articles, starting from the beginning
curl dev-news.eggtrainer.com:3100/news/archive/titles

//you can also modify the maximum number of articles returned for any of the above, using "limit"
curl dev-news.eggtrainer.com:3100/news?limit=999

//you can request a specific article using it's index (from the beginning using "archive", or just it's metadata using "title")
curl dev-news.eggtrainer.com:3100/news/1
</code></pre><p>I'll go into details of the implementation below.</p><h3 id="publishing">Publishing</h3><p>Next, we'll look at how to publish an article to the news server - it's kind of useless without this. The configuration files have a field called <code>QUERY_KEY</code>, which has the value <code>key</code>. This is the default publish key, and should be changed before using your own copy. But it's good enough for the demo.</p><p>We're going to use a POST request, and set some information in the message's heading. Then, we'll send a JSON object as the request to publish a new article (specified with <code>-d</code>.</p><pre><code>curl -X POST -H "Content-Type: application/json" \
    http://dev-news.eggtrainer.com:3100/news \
    -d '{"key":"key","title":"foo","author":"your name","body":"bar"}'
</code></pre><p>Breaking down the requested JSON looks like this:</p><pre><code>{
  "key": "key",
  "title": "foo",
  "author": "your name",
  "body": "bar"
}
</code></pre><p>The result will look something like this: <code>{"ok":true,"index":3}</code>, "index" is the absolute index of the article (from the beginning). Congrats! The GET requests from above will now show your brand new article!</p><h3 id="editing">Editing</h3><p>So... your article is published, but you've noticed a mistake! What do you do? Thankfully, I have just the solution: <code>PATCH</code>. As long as you know the absolute index of the article, you can edit that specific article via it's route like this:</p><pre><code>curl -X PATCH -H "Content-Type: application/json" \
    http://dev-news.eggtrainer.com:3100/news/3 \
    -d '{"key":"key","title":"fizz","body":"buzz"}'
</code></pre><p>First, change <code>POST</code> to <code>PATCH</code>, then add the absolute index to the end of the route. Finally, specify the publishing key and fields you want to modify in the JSON object. Any fields you don't specify won't be affected.</p><p>If you change your mind about an edit, every change is saved to the database in a table called "revisions", but there's currently no API to revert the changes.</p><h3 id="deleting">Deleting</h3><p>You know what? That article was terrible. Let's delete it.</p><p>Much like <code>POST</code> and <code>PATCH</code>, <code>DELETE</code> is available for specific absolute indexes. The only JSON argument it takes is the key:</p><pre><code>curl -X DELETE -H "Content-Type: application/json" \
    http://dev-news.eggtrainer.com:3100/news/3 \
    -d '{"key":"key"}'</code></pre><p><code>GET</code>, <code>POST</code>, <code>PATCH</code> and <code>DELETE</code>. Hopefully you understand, at least roughly, how to use these to manipulate the news server. Remember, the last three require the argument "key", which currently has the value "key".</p><p>BTW, deletions are also saved to "revisions", but it's a bit clunky.</p><h3 id="implementation-details">Implementation Details</h3><p>What I've written so far could be an article in itself - but let's keep going; lets talk about some code. Please be aware that for this section, I'm using Nodejs, express, mariaDB and Sequelize, for the most part. I linked the repository above, but I'll link to specific files here.</p><p>The server's entry point is <code><a href="https://github.com/krgamestudios/news-server/blob/main/server/server.js?ts=4">server/server.js</a></code>; lets have a look at it's contents (click that link). Rather than explain every line, let's skip to the relevant parts.</p><p>You'll notice <code>cors</code>, which is unusual - it's used to deal with <a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing">cross-origin-resource-sharing</a>, in other words allowing <code>eggtrainer.com</code> or <code>dev.eggtrainer.com</code> to access and use <code>news.eggtrainer.com</code>.</p><p>The <code>database</code> is required but not used, simply to invoke and set up sequelize. Next, the <code>/news</code> route is created, which takes in the router (we'll get to that in a moment). Finally, if any other route is accessed, the user is redirected to the server's github page. This isn't standard, it's just my way of saying "read the docs!".</p><p>It would, in theory, be fairly easy to add a new section to this, or to drop <code>/news</code> into another program. Yay modularity!</p><p>next, lets have a look at <code><a href="https://github.com/krgamestudios/news-server/blob/main/server/news/index.js">server/news/index.js</a></code>. I'd like to say it was a simple router, but actually, the <code>query</code> function that handles GET requests is rather complex. You can, however, see a pattern - every second route handles <code>:id</code>, while the query function takes two arguments each time:</p><pre><code>router.get('/', query(false, false));
router.get('/:id(\\d+)', query(false, false));
router.get('/archive', query(true, false));
router.get('/archive/:id(\\d+)', query(true, false));
router.get('/titles', query(false, true));
router.get('/titles/:id(\\d+)', query(false, true));
router.get('/archive/titles', query(true, true));
router.get('/archive/titles/:id(\\d+)', query(true, true));
</code></pre><p>Or breaking it down:</p><pre><code>/               - query(false, false)
/archive        - query(true, false)
/titles         - query(false, true)
/archive/titles - query(true, true)</code></pre><p>Thankfully, <a href="https://github.com/krgamestudios/news-server/blob/main/server/news/query.js?ts=4">query's implementation is much easier to read</a>.</p><p>It has two parts that are almost the same - the first is used when "id" is specified (the absolute index of the article). They both use <code>titlesOnly</code> to omit the body and send only the metadata, and they both use <code>ascending</code> to order the results from the database (you can also spot <code>limit</code> being used to limit the number of articles actually returned).</p><p>Other files in this folder do pretty much what you'd expect them to. <a href="https://github.com/krgamestudios/news-server/blob/main/server/news/publish.js?ts=4">server/news/publish.js</a> publishes an article (while handling a Sequelize bug to return the absolute index), <a href="https://github.com/krgamestudios/news-server/blob/main/server/news/edit.js?ts=4">server/news/edit.js</a> modifies an existing record and <a href="https://github.com/krgamestudios/news-server/blob/main/server/news/remove.js?ts=4">server/news/remove.js</a> deletes the specified record.</p><h3 id="front-ends">Front-Ends</h3><p>Oh boy, this has been a hell of an article, hasn't it? Everything we've been through has been new for you, so I know it might be confusing. So... lets simplify things a little, yeah?</p><p>There's a folder in the root called <code><a href="https://github.com/krgamestudios/news-server/tree/main/front-ends">front-ends</a></code> which contains a series of utilities for interacting with the news server, based on the specific framework that you want to use. (confession: at the time of writing, only react components are available, but I'm planning on adding vue components soon).</p><p>Having a quick look at the <a href="https://github.com/krgamestudios/news-server/blob/main/front-ends/react/news-publisher.jsx?ts=4">react publish component</a>, you can see a form, with a <code>handleSubmit</code> function. This component takes two props: <code>uri</code> and <code>key</code>, which are the URL for the news server and the publishing key respectfully. Other than that, it's ready to go. It even handles trimming the input. (There's no CSS, so feel free to customize it as you see fit.)</p><p>Similarly, the <a href="https://github.com/krgamestudios/news-server/blob/main/front-ends/react/news-editor.jsx?ts=4">edit component</a> has some nifty features - it uses an external package called <code>react-dropdown-select</code> to create a fancy drop down, and then populates it with every article title written so far. You can select one, and it'll request the full body of that article, and fill out the form for you to conveniently edit. It also requires the <code>uri</code> and <code>key</code> props, but otherwise it works just as smoothly as the publish component.</p><p>There is no delete component, because uhh... I may have forgotten to write one. But I might add it as a feature of the edit component at some point...</p><p>Finally, let's talk about the star of the show - <a href="https://github.com/krgamestudios/news-server/blob/main/front-ends/react/news-feed.jsx?ts=4">the news feed component</a>. This one's code is fairly compact, simply fetching the most recent articles and rendering them, but in it's small size are a few tiny features, like pluralizing the word "edit" when there's more than one, or hiding that info entirely if there are 0 edits so far. it can theory handle any number of articles, and even displays the dates pretty well.</p><h3 id="conclusion">Conclusion</h3><p>OK, deep breath, we're finally at the end.</p><p>This was quite fun to write, and I hope you enjoyed reading it, and learning about my news server. My real hope is that somebody finds a use for it, either on it's own or as part of the MERN-template.</p><p>Next time probably won't be so in-depth. Maybe.</p><p><em>My name is Kayne Ruse of KR Game Studios, you can find me on the net as Ratstail91, usually raving about APIs and scrawling RESTful queries on the walls.</em></p><p><em>Egg Trainer Website: <a href="https://eggtrainer.com/">https://eggtrainer.com/</a></em></p><p><em>MERN-template repo: <a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a></em></p><p><em>news-server repo: <a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a></em></p><p><em>Business Inquiries: krgamestudios@gmail.com</em></p>]]></content:encoded></item><item><title><![CDATA[Making Egg Trainer 1]]></title><description><![CDATA[Egg Trainer is a Pokemon-inspired PBBG where you buy eggs, hatch them, train the creatures and battle them against each other.]]></description><link>https://blog.pbbg.com/making-egg-trainer-1/</link><guid isPermaLink="false">601703396878724fc33851ad</guid><dc:creator><![CDATA[Kayne Ruse]]></dc:creator><pubDate>Mon, 15 Feb 2021 04:07:00 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/04/article-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/04/article-1.png" alt="Making Egg Trainer 1"><p>Welcome to this article (and potentially series) about the development of Egg Trainer! In these article(s) we'll cover different stages of development for the persistent browser based game called Egg Trainer.</p><p>I've actually developed Egg Trainer to a workable state about a year ago, but since I'm rewriting the whole game from the ground up, I decided to begin writing this series to 1. gain some attention and excitement, and 2. entertain my fans. Let's begin.</p><h2 id="premise">Premise</h2><p>Egg Trainer is a Pokemon-inspired persistent browser based game where you buy eggs, hatch them, train the creatures and battle them against each other. I love Pokemon, so I decided to boil down the best parts of those games to their core mechanics for this project. Thus: Training and Battling. There's also some elements of surprise in what hatches from the eggs, and collectability.</p><p>The game's current build doesn't let you login without an alpha account - this is so I can limit the amount of feedback and bug reports during the main development. The plan was (and is) to open the game to beta players when the main features are ready, but you *can* currently collect eggs and creatures. Contact me with your username for an alpha account if you're interested.</p><h2 id="the-template">The Template</h2><p>I decided, before beginning on the rewrite, that I could reuse some elements of the website. So, I began developing the MERN template using my favourite tech stack: MySQL, Express, React and Node.</p><p>The MERN template has a number of essential features: account management, email validation, administration panel, etc. It's also, in theory, easy to set up (I'd love some feedback from people trying it out). There are a few legalities that need to be addressed, namely account deletion (right to be forgotten) and the data collection notice - I'm not entirely certain I got these right, but at least I made an effort.</p><p>The signup process is thus:</p><p>1. Enter your email, username and password<br>2. A validation email is sent to your inbox<br>3. Click the link in the email<br>4. You're set to go!</p><p>You've probably noticed a big red flag - "password". Yes, I do in fact collect passwords, but they never touch the database without being hashed and salted via <a href="https://www.npmjs.com/package/bcryptjs">bcryptjs</a> first. I've done extensive research into password management and, although I can't say for certain, I'm reasonably confident that they're secure. HOWEVER, I must implore anyone deploying this template to ensure that you're using HTTPS protocol - it's not hard, <a href="https://certbot.eff.org/">certbot</a> is a thing.</p><p>Another privacy concern are cookies - although there are no ads in the template, I do make it clear that the template uses cookies, and in fact I disable the site entirely if the user doesn't agree to use them. This might change in the future, we'll see; this is actually my first time using cookies, so I'm being overly cautious.</p><h2 id="the-microservices">The Microservices</h2><p>Not every game will require every element of Egg Trainer, so some parts of the template were isolated into <a href="https://en.wikipedia.org/wiki/Microservices">microservices</a>. A microservice is simply a part of the program which runs independently from the main program, often having it's own codebase and configuration. This has a few benefits - I can keep the main game's code simple without extra clutter, and I can modify the microservices without having to alter the main game at all.</p><p>At the time of writing, there are two microservices planned: news-server and chat-server. News-server is already functional and live, and can be accessed with a GET request here:</p><!--kg-card-begin: markdown--><p>GET <a href="http://dev-news.eggtrainer.com:3100/news">http://dev-news.eggtrainer.com:3100/news</a></p>
<!--kg-card-end: markdown--><p>This can be accessed via <a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST</a> requests in the client to get formatted news articles for the homepage feed. I like to keep my players up to date with news posted directly to the game's main page.</p><p>The second microservice hasn't been written yet - chat-server. The game will have a chat window that allows people to communicate, at first in general rooms and DMs, and later in 1v1 battles. This feature was requested, and I liked it so much it became part of the template plan. It will in theory use REST as well, utilizing it's own internal account and logging systems. I haven't exactly planned it out yet, as it's not needed just yet...</p><h2 id="administration-panel">Administration Panel</h2><p>There is also an administration panel under construction, which will only be available to accounts with admin privileges. The client uses cookies to determine if the admin panel is shown, and the back-ends will ensure that nobody but the admins can access it, of course.</p><p>The admin panel will be simple - allowing access to the ban/unban feature, as well as an easy way to publish news articles with a click. More info such as chat logs and game monitoring will be added as I need them.</p><h2 id="conclusion-and-links">Conclusion and Links</h2><p>I'm not sure if this article is very substantial, but hopefully it gives you an insight into the MERN template. Hopefully, by the time the next article is written, the template will be complete, and ready for conversion into Egg Trainer.</p><p>My name is Kayne Ruse of KR Game Studios, you can find me on the net as Ratstail91.<br>Egg Trainer Website: <a href="https://eggtrainer.com/">https://eggtrainer.com/</a><br>MERN-template repo: <a href="https://github.com/krgamestudios/MERN-template">https://github.com/krgamestudios/MERN-template</a><br>news-server repo: <a href="https://github.com/krgamestudios/news-server">https://github.com/krgamestudios/news-server</a><br>Business Enquiries: <a href="mailto:krgamestudios@gmail.com">krgamestudios@gmail.com</a></p>]]></content:encoded></item><item><title><![CDATA[The State of PBBG 2021 Survey Results]]></title><description><![CDATA[This year marks the first ever State of PBBG survey, aimed at gaining outreach and giving players a bigger voice in the games they play. The survey was open for 15 days, and represented 144 total community members.]]></description><link>https://blog.pbbg.com/the-state-of-pbbg-2021-survey-results/</link><guid isPermaLink="false">6021cd5f6878724fc338543e</guid><category><![CDATA[State of PBBG]]></category><dc:creator><![CDATA[Christopher Graves]]></dc:creator><pubDate>Tue, 09 Feb 2021 00:14:58 GMT</pubDate><media:content url="https://blog.pbbg.com/content/images/2021/02/State-of-PBBG-Logo-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pbbg.com/content/images/2021/02/State-of-PBBG-Logo-1.png" alt="The State of PBBG 2021 Survey Results"><p>This year marks the first ever State of PBBG survey, aimed at gaining outreach and giving players a bigger voice in the games they play. The survey was open for 15 days, and represented 144 total community members.</p><p>Below are the results that were thoughtfully collated by our own @rodrigo.borges#4172 on the PBBG Discord! Be sure to give him a shoutout for the spectacular work. We're working on drafting up the next survey over the next couple of months, so if you have any suggestions please let us know in the Discord linked below.</p><p>You can view the <strong>raw results</strong> <a href="https://docs.google.com/spreadsheets/d/1WhXUP_357mI_ZFBqnvy27tKGMSQt9kQDV3VZdhoMsw4/edit#gid=1179595987">here</a>, the <strong>survey site</strong> <a href="https://stateof.pbbg.com">here</a>, and join our <strong>Discord </strong><a href="https://chat.pbbg.com">here</a>.</p><hr><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/1.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/2.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/3.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/4.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/5.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/6.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/7.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/8.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/9.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/10.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/11.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/12.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/14.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/14-1.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pbbg.com/content/images/2021/02/15.png" class="kg-image" alt="The State of PBBG 2021 Survey Results"></figure>]]></content:encoded></item></channel></rss>