<?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[Blog: Krestianstvo SDK]]></title><description><![CDATA[Thoughts, stories and ideas.]]></description><link>https://blog.krestianstvo.org/en/</link><image><url>http://blog.krestianstvo.org/en/favicon.png</url><title>Blog: Krestianstvo SDK</title><link>https://blog.krestianstvo.org/en/</link></image><generator>Ghost 4.48</generator><lastBuildDate>Sat, 04 Apr 2026 20:40:36 GMT</lastBuildDate><atom:link href="https://blog.krestianstvo.org/en/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Answering Common Questions about Krestianstvo SDK 4]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Started writing documentation with answering common questions about <a href="https://play.krestianstvo.org">Krestianstvo SDK 4</a></p>
<h4 id="1isitusingthesmalltalkversionofcroquetsqueakopencroquetoropenqwaq">1. Is it using the Smalltalk version of Croquet: <a href="https://wiki.c2.com/?OpenCroquet">Squeak Open Croquet</a> or <a href="https://en.wikipedia.org/wiki/OpenQwaq">Open Qwaq</a>?</h4>
<p>No. Krestianstvo SDK 4 is entirely written in JavaScript and is running on top of JavaScript VM.<br>
Open Croquet architecture is used in <a href="https://krestianstvo.org/sdk1/">Krestianstvo</a></p>]]></description><link>https://blog.krestianstvo.org/en/answering-common-questions-about-krestianstvo-sdk-4/</link><guid isPermaLink="false">6333da661007790001993be0</guid><category><![CDATA[Krestianstvo SDK]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Wed, 28 Sep 2022 05:25:39 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2022/09/2.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://blog.krestianstvo.org/en/content/images/2022/09/2.jpg" alt="Answering Common Questions about Krestianstvo SDK 4"><p>Started writing documentation with answering common questions about <a href="https://play.krestianstvo.org">Krestianstvo SDK 4</a></p>
<h4 id="1isitusingthesmalltalkversionofcroquetsqueakopencroquetoropenqwaq">1. Is it using the Smalltalk version of Croquet: <a href="https://wiki.c2.com/?OpenCroquet">Squeak Open Croquet</a> or <a href="https://en.wikipedia.org/wiki/OpenQwaq">Open Qwaq</a>?</h4>
<p>No. Krestianstvo SDK 4 is entirely written in JavaScript and is running on top of JavaScript VM.<br>
Open Croquet architecture is used in <a href="https://krestianstvo.org/sdk1/">Krestianstvo SDK 1</a>. Open Qwaq architecture is used in <a href="https://krestianstvo.org/sdk2/">Krestianstvo SDK 2</a></p>
<h4 id="2isitusingcroquetosoranyofcroquetioserviceswritteninjavascript">2. Is it using <a href="https://croquet.io">Croquet OS</a> or any of croquet.io services written in JavaScript?</h4>
<p>No. Krestianstvo SDK 4 is introducing its own implementation of Croquet Application Architecture in JavaScript, based on <a href="https://solidjs.com">Solid JS</a> &amp; <a href="https://github.com/adamhaile/S">S.js</a> using Functional Reactive Programming (FRP).</p>
<h4 id="3isitusingjavascriptversionofcroquetknownasvirtualworldframework">3. Is it using JavaScript version of Croquet known as <a href="https://en.wikipedia.org/wiki/Virtual_world_framework">Virtual World Framework</a>?</h4>
<p>Only implementations of Reflector server and Virtual Time are used and modified to suit FRP.<br>
Virtual World Framework provides its own unique implementation of Croquet Application Architecture based on prototypes, nodes and drivers. VWF architecture is used in <a href="https://krestianstvo.org/sdk3/">Krestianstvo SDK 3</a>. The 4th version of Krestianstvo SDK contains no elements of it.</p>
<h4 id="4isitcompatiblewithcroquetosorvirtualworldframework">4. Is it compatible with <a href="https://croquet.io">Croquet OS</a> or <a href="https://en.wikipedia.org/wiki/Virtual_world_framework">Virtual World Framework</a>?</h4>
<p>Not out-of-the-box. Although Croquet OS / VWF and Krestianstvo SDK 4 share the same original Open Croquet roots, some effort will be required in porting an application between their different implementations, alongside pros and cons.<br>
The application development (<a href="https://codesandbox.io/s/krestianstvo-helloworld-pnimfu?file=/src/index.js">code example</a>) with Krestianstvo SDK 4 is looked quite different, comparing to the  development in Croquet OS or VWF one&apos;s. Croquet OS and VWF Application Architecture is based on Model - View pattern, implemented in Class/Instance programming paradigm. In the contrary, Krestianstvo SDK 4 Application Architecture is based just on pure functions in form of Signals and Computations (Effects). Croquet OS uses pub/sub messaging for interconnecting Model/View instances. VWF is using drivers for that interconnection. In the contrary, Krestianstvo SDK 4 is using &quot;glitchless&quot; automatic dependency graph with a synchronous execution engine found in Solid JS and S.js</p>
<h4 id="5doineedtorunmyownreflectorservertostartdevelopingwithkrestianstvosdk4">5. Do I need to run my own Reflector server to start developing with Krestianstvo SDK 4?</h4>
<p>No. You can use any of publicly available already running reflector servers. Like <a href="https://time.krestianstvo.org">https://time.krestianstvo.org</a> or <a href="https://time.livecoding.space">https://time.livecoding.space</a></p>
<h4 id="6canirunmyownreflectorserver">6. Can I run my own Reflector server?</h4>
<p>Yes, you can host your own <a href="https://github.com/NikolaySuslov/lcs-reflector">Reflector server</a> anywhere in LAN or WAN. Just point to it in the <code>&lt;Selo/&gt;</code> component</p>
<pre><code class="language-js">&lt;Selo
    nodeID={&quot;simple&quot;}
    seloID={&quot;1&quot;}
    component={Simple}
    worlds={worlds}
    fallbackWorld={EmptyWorld}
    reflectorHost={&quot;https://url.to.my.reflector&quot;}
/&gt;
</code></pre>
<p>Or just use directly in Web Browser url with <strong>r</strong> parameter: <a href="https://play.krestianstvo.org/demo1?r=https://time.krestianstvo.org">https://play.krestianstvo.org/demo1?r=https://time.krestianstvo.org</a></p>
<h4 id="7doesreflectorserverusedinkrestianstvosdk4awareofaclientsapplicationlogicorstoreanyapplicationstate">7. Does Reflector server used in Krestianstvo SDK 4 aware of a client&apos;s application logic or store any application state?</h4>
<p>No. Reflector server, that is used in Krestianstvo SDK 4 is fully conform the Croquet Application Architecture. Meaning, that Reflector server is used only for initial connection, ticking, stamping and reflecting the messages received from the clients with the data they want to share (e.g. 2D coords from a mouse movement). It knows nothing about application logic, and don&apos;t relay any data, that can be generated with a future messages locally on every synced client, running Croquet deterministic computations.</p>
<h4 id="8caniusedifferentreflectorserversatthesametimefordifferentworldslinkedbyportalsbutexistedinoneworldwebpage">8. Can I use different Reflector servers at the same time for different worlds linked by Portals, but existed in one world/web page?</h4>
<p>Yes. When creating a Portal, just use url with <strong>r</strong> parameter pointing to any other running reflector server.</p>
<h4 id="9areportalsusingiframestomakeinterlinkedworlds">9. Are Portals using iFrames to make inter-linked worlds?</h4>
<p>No. Portal is just a pure function in form of Solid JS component. Thus, portal can be used inside any other Solid JS component, with no need on creating the new JavaScript context and iFrame. You can freely create a stacks of portals and manipulate them as a single functional component, by passing props and sending messages through it.</p>
<h4 id="10doesportalssupportlinkingtothemselves">10. Does Portals support linking to themselves?</h4>
<p>Yes. Portals are recursive. By default portal&apos;s recursion depth is set to <strong>2</strong>. Use parameter <strong>d</strong> in the url to set the depth manually.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Krestianstvo SDK 4 | Implementing Croquet and Recursive Portals on Solid JS]]></title><description><![CDATA[<p>Let me introduce to you the new <strong>4th</strong> version of <strong><a href="https://play.krestianstvo.org">Krestianstvo SDK</a></strong>!</p><p>The main feature of the 4th version is the full-featured implementation of the <a href="https://croquet.io/"><strong>Croquet Application Architecture</strong></a> in Functional Reactive Paradigm using <strong><a href="https://www.solidjs.com/">SolidJS</a> / <a href="https://github.com/adamhaile/S">S.JS</a></strong> and introduction of <strong>Recursive Portals</strong>. The only parts, that stayed the same as in</p>]]></description><link>https://blog.krestianstvo.org/en/krestianstvo-sdk-4/</link><guid isPermaLink="false">630e656a6d803e0001a6a6c1</guid><category><![CDATA[Krestianstvo SDK]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Thu, 01 Sep 2022 04:13:54 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2022/09/scr2.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.krestianstvo.org/en/content/images/2022/09/scr2.jpg" alt="Krestianstvo SDK 4 | Implementing Croquet and Recursive Portals on Solid JS"><p>Let me introduce to you the new <strong>4th</strong> version of <strong><a href="https://play.krestianstvo.org">Krestianstvo SDK</a></strong>!</p><p>The main feature of the 4th version is the full-featured implementation of the <a href="https://croquet.io/"><strong>Croquet Application Architecture</strong></a> in Functional Reactive Paradigm using <strong><a href="https://www.solidjs.com/">SolidJS</a> / <a href="https://github.com/adamhaile/S">S.JS</a></strong> and introduction of <strong>Recursive Portals</strong>. The only parts, that stayed the same as in the 3rd version of Krestianstvo SDK are: Reflector and Virtual Time. Their implementations are based on the <a href="https://github.com/virtual-world-framework/vwf"><strong>Virtual World Framework</strong></a>, thus they were just slightly modified to suit Functional Reactive Paradigm. </p><!--kg-card-begin: markdown--><iframe src="https://player.vimeo.com/video/742885266?title=0&amp;byline=0&amp;portrait=0" width="640" height="360" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe><!--kg-card-end: markdown--><p>The 4th version of Krestianstvo SDK is distributed as a standalone <a href="https://www.npmjs.com/package/krestianstvo"><strong>ESM module</strong></a> for JavaScript. It could be easily bundled with any <a href="https://www.solidjs.com/">Solid JS</a> or <a href="https://astro.build/">Astro</a> web application being hosted and running just in the Cloud. </p><p>The work on the 4th version was started in 2019, when I was working on <a href="http://blog.krestianstvo.org/en/krestianstvo-luminary-for-open-croquet-architecutre-and-virtual-world-framework-in-peer-to-peer-web/"><strong>Luminary</strong></a> and introduced the Functional Reactive Streams into the Croquet application architecture. <a href="http://blog.krestianstvo.org/en/collaborative-robots-rubiks-cube-lego-boost/"><strong>The project with Rubik&apos;s Cube</strong></a> has shown, how Croquet gets a new look on Virtual Time and Promises inside actions, all backed by FRP. For example, the participants could delay the Virtual Time and observe their actions in virtual world in &quot;slow motion&quot;. &#xA0;</p><p>Then in 2021 I participated in the first <strong><a href="https://browsersound.com/">Festival for Web based Music</a>. </strong>At the festival me and artist Delia Ramos were creating the web art project - <a href="https://concert.livecoding.space/">&quot;<strong>THIS IS NOT A CONCERT</strong>&quot;</a>. &#xA0;In that project, an audience collaboratively explored the artwork inside virtual canvas space within multi-contextual / conceptual creative layers by touching the virtual objects, interacting or viewing through &quot;filters&quot; in Web Browser. The core object, that I needed to for that project was a <strong>Recursive Portal</strong>,<strong> </strong>that should work as a filter, portal to other virtual canvas spaces and also as a portal to itself. &#xA0;</p><p>But, comparable to the original Smalltalk version of the Croquet, as in the Virtual World Framework and in the 3rd version of Krestianstvo SDK there are still lack of Portals. The <a href="https://croquet.io">Croquet.io</a> has introduced Portals for the Web, by using sandboxed HTML iFrames (<a href="https://davidasmith.medium.com/multiplane-portals-for-the-metaverse-a4b7af913e8e">Multiplane Portals for the Metaverse</a>). And in Krestianstvo I wanted to implement Portals the same way as Croquet Smalltalk version does, as pure objects with an ability to make links to themselves, forming a Recursive Portals. </p><p>Finally, I was lucky to do it just in pure JavaScript, thanks to Solid JS! To make these all happen, it demanded of me to implement the Croquet application architecture nearly from scratch using functional reactive paradigm from Solid JS / S.JS. </p><!--kg-card-begin: markdown--><iframe src="https://player.vimeo.com/video/745245330?title=0&amp;byline=0&amp;portrait=0" width="640" height="360" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe><!--kg-card-end: markdown--><p>The typical application in the 4th version of <strong><a href="https://play.krestianstvo.org">Krestianstvo SDK</a> </strong>is an application, that will be build up from Solid JS main types of building blocks: Components and Reactive Primitives. Solid&apos;s fine-grained reactivity is built on three core primitives: Signals, Memos, and Effects. Together, they form an auto-tracking synchronization engine. Reactive computations take the form of function-wrapped expressions that execute synchronously (<a href="https://www.solidjs.com/guides/getting-started#learn-solid">more in SolidJS documentation</a>). </p><p>Krestianstvo uses Solid JS reactivity for implementing Croquet&apos;s concept of Model - View interconnection. Croquet Models - are just pure Solid JS Signals, Memos and Stores. Croquet Views - are just Solid JS lightweight Components with no state and no instances. All received external messages from Reflector and all internal Future messages, that responsible for actions are wrapped in a Signals and then dispatched by an Effects accordingly. For example, Smalltalk like &quot;<strong>doesNotUnderstand</strong>&quot; message is easily realised in Krestianstvo with Solid JS. </p><p>Here is an example of simple working app in Krestianstvo SDK | 4 (view it on <a href="https://codesandbox.io/s/krestianstvo-helloworld-pnimfu">codesandbox</a>)</p><!--kg-card-begin: markdown--><pre><code class="language-js">import { render } from &quot;solid-js/web&quot;;
import { Selo, createLocalStore } from &quot;krestianstvo&quot;;

const Counter = (props) =&gt; {
  const [local, setLocal] = createLocalStore(
    {
      data: {
        type: &quot;Node&quot;,
        nodeID: props.nodeID,
        properties: {
          name: props.nodeID,
          count: 0,
          ticking: false,
          initialized: false
        }
      }
    },
    props
  );

  const inc = () =&gt; {
    setLocal(&quot;data&quot;, &quot;properties&quot;, &quot;count&quot;, (c) =&gt; c + 1);
    props.selo.future(props.nodeID, &quot;inc&quot;, 1);
  };

  const initialize = () =&gt; {
    inc();
  };

  props.selo.createAction(props.nodeID, &quot;inc&quot;, inc);
  props.selo.createAction(props.nodeID, &quot;initialize&quot;, initialize);

  return (
    &lt;&gt;
      &lt;h1&gt;{local.data.properties.count}&lt;/h1&gt;
    &lt;/&gt;
  );
};

render(
  () =&gt; (
    &lt;Selo
      nodeID={&quot;counter&quot;}
      seloID={&quot;sandbox_counter&quot;}
      component={Counter}
      reflectorHost={&quot;https://time.krestianstvo.org&quot;}
    /&gt;
  ),
  document.getElementById(&quot;root&quot;)
);
</code></pre>
<!--kg-card-end: markdown--><p>To be continued&#x2026;</p><hr><p>Demo playground: <a href="https://play.krestianstvo.org">https://play.krestianstvo.org</a></p><p>Glitch demo project: <a href="https://krestianstvo-playground.glitch.me/">https://krestianstvo-playground.glitch.me</a></p><!--kg-card-begin: markdown--><p>The source code for <strong>Krestianstvo SDK 4</strong>:</p>
<ul>
<li>Playground: <a href="https://github.com/NikolaySuslov/krestianstvo-playground">GitHub</a></li>
<li>Core library on Solid JS: <a href="https://github.com/NikolaySuslov/krestianstvo">GitHub</a></li>
<li>Prototype on S.js: <a href="https://github.com/NikolaySuslov/krestianstvo-s.js">GitHub</a></li>
<li>Reflector server: <a href="https://github.com/NikolaySuslov/lcs-reflector">GitHub</a></li>
</ul>
<!--kg-card-end: markdown--><p></p><p></p><p></p><h2></h2>]]></content:encoded></item><item><title><![CDATA[Collaborative Robots: Rubik's Cube & Lego BOOST]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Let me share with you the new LiveCoding.space 2020 World: &#xA0;<br>
<a href="http://livecoding.space/w/rubik">Collaborative Robots: Rubik&apos;s Cube &amp; Lego BOOST</a>.</p>
<p>Here is the outline of the following post:</p>
<ul>
<li>Collaborative Rubik&apos;s Cube simulator</li>
<li>Croquet VWF and Functional Reactive Streams, why this feature is must have!</li>
<li>LiveCoding.space driver</li></ul>]]></description><link>https://blog.krestianstvo.org/en/collaborative-robots-rubiks-cube-lego-boost/</link><guid isPermaLink="false">5feb44bff828d00001124bae</guid><category><![CDATA[Krestianstvo SDK]]></category><category><![CDATA[LiveCoding.space]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Tue, 29 Dec 2020 21:07:40 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2020/12/rubik_boost.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://blog.krestianstvo.org/en/content/images/2020/12/rubik_boost.jpg" alt="Collaborative Robots: Rubik&apos;s Cube &amp; Lego BOOST"><p>Let me share with you the new LiveCoding.space 2020 World: &#xA0;<br>
<a href="http://livecoding.space/w/rubik">Collaborative Robots: Rubik&apos;s Cube &amp; Lego BOOST</a>.</p>
<p>Here is the outline of the following post:</p>
<ul>
<li>Collaborative Rubik&apos;s Cube simulator</li>
<li>Croquet VWF and Functional Reactive Streams, why this feature is must have!</li>
<li>LiveCoding.space driver for Lego BOOST brick, implementation details</li>
</ul>
<iframe src="https://player.vimeo.com/video/495585020?title=0&amp;byline=0&amp;portrait=0" width="640" height="360" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
<h2 id="collaborativerubikscubesimulator">Collaborative Rubik&apos;s Cube simulator</h2>
<p>Collaborative Rubik&apos;s Cube simulator transforms the original Rubik&#x2019;s Cube demo (by Stewart Smith) that powers the Rubik&#x2019;s Cube Google Doodle, the Chrome Cube Lab to collaborative one.<br>
Multiple users can explore Rubik&apos;s cubes collaboratively and send commands simultaneously. Create a zoo of Rubik&apos;s Cubes in virtual worlds.<br>
In LiveCoding.space Rubic&apos;s Cube is augmented with virtual robot, that is backed by three physical devices (Lego BOOST brick). So, virtual Rubic&apos;s Cube dispatch user commands for rotating faces and executes them sequentially on appropriate devices. Even users, that don&apos;t have a connected Lego BOOST brick, could execute commands remotely on other users devices, in the same virtual world.</p>
<h2 id="croquetvwfandfunctionalreactivestreams">Croquet VWF and Functional Reactive Streams</h2>
<p>In Croquet VWF by default any call of Model&apos;s method, like &#xA0;<br>
<code>vwf.callMethod(nodeId, &apos;methodName&apos;, [parameters])</code> will go trough VWF Model/View drivers chain for updating the application node tree, executing JS code as soon as possible using proxy &apos;traps&apos;: <code>callingMethod</code> and <code>calledMethod</code>.<br>
That works quit well for synchronous sequential code execution. And also for executing non&#xA0;sequential asynchronous code.<br>
But, that does not suited to work with Promises (async/await), which represents the eventual completion, especially sequences of promises.<br>
So, imagine you have a real physical Rubic&apos;s Cube robot, consisting of three independent robot devices (Lego BOOST in our example), every device has for three motors, leds, sensors. And you want to synchronise their work, by sending sequential messages from virtual world, like:<br>
<code>robot1.motorA(90); robot2.motorA(-90); robot1.motorB(-90);</code>. That any next operation waits for a previous operation to complete.<br>
Functional Reactive Streams come as a solution to Croquet VWF and open an unlimited functionality for interconnecting physical world of devices with virtual world in a unique collaborative way, which was not available before!</p>
<hr>
<h2 id="livecodingspacedriverforlegoboostbrickimplementationdetails">LiveCoding.space driver for Lego BOOST brick: implementation details</h2>
<p>LiveCoding.space 2020 update includes an experimental driver for collaborative synchronous/asynchronous controlling of the external robot device within virtual world.<br>
The implementation of the driver is heavily based on using functional reactive streams. The communication with Lego BOOST brick is done over Web Bluetooth. There is no need for any third party software nor OS driver to start using Lego BOOST inside virtual world. You just need a computer/smart phone with Bluetooth, Web Browser and Lego BOOST brick.</p>
<p>When, Lego BOOST brick is connected, the initialization of reactive functional stream of promises is happened in the driver.</p>
<pre><code class="language-JS">&#xA0; &#xA0; self.streamScheduler = M.scheduler.newDefaultScheduler();
&#xA0; &#xA0; const [induce, events] = M.createAdapter();
&#xA0; &#xA0; self.streamAdapter = {
&#xA0; &#xA0; &#xA0; &#xA0; induce: induce,
&#xA0; &#xA0; &#xA0; &#xA0; events: events
&#xA0; &#xA0; }

&#xA0; &#xA0; const result = M.concatMap((x) =&gt; M.fromPromise(x()), events);
&#xA0; &#xA0; self.eventsStream = M.tap(res =&gt; { tapFunction(res) }, result); 
&#xA0; &#xA0; M.runEffects(self.eventsStream, self.streamScheduler);

</code></pre>
<p>Every method call from the Croquet VWF Model, that is considered to be a Promise, like <code>robotA.setMotorAngle(90)</code>, will go through Lego BOOST driver, where it will be added to the stream of promises:</p>
<p>Example of adding LegoBOOST Led action:</p>
<pre><code class="language-JS">let promiseAction = async function () {
&#xA0; &#xA0; return self.boost.ledAsync(ledColor).then(r =&gt; {
&#xA0; &#xA0; &#xA0; &#xA0; return {
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; check: {
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; isLegoBoost: isLegoBoost,
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; isLegoBoostClone: isLegoBoostClone
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; },
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; action: &quot;lego&quot;,
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; nodeID: nodeID,
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; methodName: methodName,
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; methodParameters: [ledColor],
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; res: r
&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; })
}
self.streamAdapter.induce(promiseAction);
</code></pre>
<p>Then, only when Promise from stream will be fulfilled, the side effect will be performed:</p>
<pre><code class="language-JS">&#xA0; &#xA0; const tapFunction = function (res) {
&#xA0; &#xA0; &#xA0; &#xA0; if (res &amp;&amp; res.action == &quot;lego&quot;) {
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; if (res.check.isLegoBoost) {
&#xA0;self.kernel.callMethod(res.nodeID, &quot;sat_&quot; + res.methodName, res.methodParameters)
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; &#xA0; &#xA0; console.log(res);
&#xA0; &#xA0; }

</code></pre>
<p>Finally, in LiveCoding.space code editor one could&#xA0;execute the sequence of async code and expect the right order of operations on connected physical devices:</p>
<pre><code class="language-JS">robotA.setLed(&quot;red&quot;);
robotB.setMotorAngle(&apos;A&apos;, 180, -100);
robotA.setMotorAngle(&apos;B&apos;, 90, 100);
robotB.setLed(&quot;green&quot;);
</code></pre>
<p><img src="http://blog.krestianstvo.org/en/content/images/2020/12/rubik_app-1.jpg" alt="Collaborative Robots: Rubik&apos;s Cube &amp; Lego BOOST" loading="lazy"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[LiveCoding.space 2020]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Glad to share with you the long awaited 2020 update to the <a href="https://livecoding.space">LiveCoding.space</a> project, so let me introduce to you:</p>
<ul>
<li>What&apos;s new in 2020 update!</li>
<li>Answer the question, why LiveCoding.space is still based on Croquet VWF instead of Croquet.io</li>
<li>And finally dive into the details</li></ul>]]></description><link>https://blog.krestianstvo.org/en/livecoding-space-2020-update/</link><guid isPermaLink="false">5fea3ab307043700011754ab</guid><category><![CDATA[Krestianstvo SDK]]></category><category><![CDATA[LiveCoding.space]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Tue, 29 Dec 2020 21:07:16 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2020/12/post1-1.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://blog.krestianstvo.org/en/content/images/2020/12/post1-1.jpg" alt="LiveCoding.space 2020"><p>Glad to share with you the long awaited 2020 update to the <a href="https://livecoding.space">LiveCoding.space</a> project, so let me introduce to you:</p>
<ul>
<li>What&apos;s new in 2020 update!</li>
<li>Answer the question, why LiveCoding.space is still based on Croquet VWF instead of Croquet.io</li>
<li>And finally dive into the details of new &quot;Minimal&quot; application</li>
</ul>
<h2 id="livecodingspace2020updates">LiveCoding.space 2020 updates</h2>
<iframe src="https://player.vimeo.com/video/495598103?title=0&amp;byline=0&amp;portrait=0" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<ol>
<li>LiveCoding.space is moving towards ES6 compliance! It means, that all Croquet VWF core application components are now ES6 modules (including VWF model, view, drivers etc).</li>
<li>The minimal Croquet VWF core is now distributed separately from the drivers/application entanglement, compared to original VWF. This new core consists of refactored components: Croquet Virtual Time, Reflector Client, Luminary, VWF core app, Kernel, Model, View, JavaScript etc., all in ES6 modules format. Look at example: <a href="https://livecoding.space/w/minimal"><strong>&quot;Minimal&quot;</strong> application</a>.</li>
<li>The core now has an experimental support of &quot;stream of messages&quot;, based on functional reactive streams. That feature allows to record/replay/delay etc. external &amp; internal (reflector/luminary) messages on peers (ongoing changes).</li>
<li>Use very fast binary heap priority queue for sorting messages on Croquet core.</li>
<li>All LiveCoding.space application components and worlds are now described in JSON format, with no YAML support anymore.</li>
<li>There is no &quot;super&quot; user anymore, who should own proxy components for bootsrapping worlds from decentralized storage. Now every user could own it&apos;s own proxy and built the world from corresponding components.</li>
<li>Any saved World could be used now as a World prototype for later reuse.</li>
<li>Experimental driver for communication with external hardware over Web Bluetooth and functional reactive streams. Look at example: <a href="https://livecoding.space/w/rubik"><strong>&quot;Collaborative Robots&quot;</strong></a>.</li>
<li>Finally add support for Oculus Quest/VIVE/Windows MR/Gear VR headsets in all spaces by default with teleportation control. Look at example: <a href="https://livecoding.space/w/paint"><strong>&quot;Paint&quot;</strong></a> application.</li>
<li>Avatars are now have virtual pointers for interaction with in-world UI&apos;s.</li>
<li>Added QR codes for world instance&apos;s URL for user friendly connection from mobile devices.</li>
<li>Added costumes functionality for avatars and pointers.</li>
<li>A-Frame library is updated to the latest 1.1 version, with support of the latest Web XR, AR JS and Layers. Look at example: <a href="https://livecoding.space/w/aframe-ar/"><strong>&quot;AR&quot; application</strong></a>.</li>
<li>Gun DB is updated to the latest stable version 0.2020.520</li>
</ol>
<p><img src="http://blog.krestianstvo.org/en/content/images/2020/12/paint_app.jpg" alt="LiveCoding.space 2020" loading="lazy"><br>
Screenshot from <a href="https://livecoding.space/w/paint"><strong>&quot;Paint&quot;</strong></a> application.</p>
<hr>
<h2 id="croquetvwforcroquetio">Croquet VWF or Croquet.io?</h2>
<p>If you are aware of <a href="https://livecoding.space">LiveCoding.space</a> project, you may noticed, that it is based on <a href="https://en.wikipedia.org/wiki/Croquet_Project">Croquet architecture</a> (VWF version). While working with VWF just from 2012, I have started this project in <a href="http://blog.krestianstvo.org/en/virtual-world-framework-a-frame/">2017</a>. VWF is known as <a href="https://github.com/virtual-world-framework/vwf">Virtual World Framework</a> an open source version of Croquet architecture for Web Browser.<br>
Later in 2019 the latest version of Croquet was introduced <a href="https://www.croquet.io/">Croquet.io</a>, known nowadays as just Croquet (no version supplement) - and which is Awesome!<br>
<a href="http://blog.krestianstvo.org/en/aframe-croquet-component/">Check here experimental projects</a>, where I explore the potential features.<br>
Yet, that latest version of Croquet requires Internet connection and is closed sourced, but provides the SDK for developers. The SDK is well documented and allows to create collaborative apps just in minutes using Croquet.io architecture in Web Browser, but with two restrictions:</p>
<ul>
<li>you could not modify/extend the Croquet core, as it is closed sourced</li>
<li>you are only allowed to use Croquet specific reflector servers, that are provided by Croquet.io on Internet, and could not create your own ones</li>
</ul>
<p>Actually, for the most applications, that are developed using Croquet architecture, these restrictions are not limitations, as may appear. In most cases, the developer will never need to touch the Croquet core, as applications are fully client side. And geo-distributed reflector servers running 24/7 are also can satisfy nearly every needs.<br>
But, unfortunately, for the <a href="https://livecoding.space">LiveCoding.space</a> project these two restrictions are the critical limitations, as there is no way to implement the latest <a href="http://blog.krestianstvo.org/en/krestianstvo-luminary-for-open-croquet-architecutre-and-virtual-world-framework-in-peer-to-peer-web/">Krestianstvo Luminary</a> and other decentralized extensions in the Croquet core.</p>
<blockquote>
<p>For now <a href="https://livecoding.space">LiveCoding.space</a> project will remain to be based on the open source version Croquet (VWF).</p>
</blockquote>
<p>While looking closely on the latest Croquet.io, one can find, that the new version is implemented on the latest ES6 standards, have introduced pub/sub events for inter - Model/View communications and other things, but architecturally still relies on specific reflector servers and snapshots much like in Croquet VWF.</p>
<p>In comparison, <a href="https://livecoding.space">LiveCoding.space</a> alongside with using own standard <a href="https://github.com/NikolaySuslov/lcs-reflector">minimal reflector servers</a>, it moves Croquet VWF architecture towards decentralization, by introducing <a href="http://blog.krestianstvo.org/en/krestianstvo-luminary-for-open-croquet-architecutre-and-virtual-world-framework-in-peer-to-peer-web/">Krestianstvo Luminary</a>.</p>
<p><img src="http://blog.krestianstvo.org/en/content/images/2020/12/reflector_vs_luminary.jpg" alt="LiveCoding.space 2020" loading="lazy"></p>
<p>So, the combination of &#xA0;Croquet VWF &amp; Krestianstvo Luminary does not need any Croquet specific reflector servers at all, comparing to the original Croquet VWF or Croquet.io architectures.</p>
<hr>
<h2 id="exampleoflivecodingspaceapplicationminimal">Example of LiveCoding.space application: Minimal</h2>
<p><img src="http://blog.krestianstvo.org/en/content/images/2020/12/minimal_app-1.jpg" alt="LiveCoding.space 2020" loading="lazy"></p>
<p>Let&apos;s explore the &#xA0;<a href="https://livecoding.space/w/minimal"><strong>&quot;Minimal&quot;</strong> application</a> details:</p>
<p>This &quot;Minimal&quot; application every virtual second updates a world property with Croquet Time and shows it on a web page and debug console; counts clicks on Model on every peer, without transmitting this data; generating a random number in Model on every peer. &#xA0;<br>
There are only three steps needed to complete a working application:</p>
<ol>
<li>Create World&apos;s description file in JSON format:</li>
</ol>
<pre><code class="language-JSON">{
&#xA0; &quot;extends&quot;: &quot;proxy/node.vwf&quot;,
&#xA0; &quot;properties&quot;: {
&#xA0; &#xA0; &quot;timeCount&quot;: 0,
&#xA0; &#xA0; &quot;clicks&quot;: 0,
&#xA0; &#xA0; &quot;randomNumber&quot;: null
&#xA0; },
&#xA0; &quot;methods&quot;:{
&#xA0; &#xA0; &quot;initialize&quot;: {},
&#xA0; &#xA0; &quot;run&quot;: {},
&#xA0; &#xA0; &quot;incClicks&quot;: {},
&#xA0; &#xA0; &quot;decClicks&quot;: {},
&#xA0; &#xA0; &quot;getRandom&quot;: {}
&#xA0; },
&#xA0; &quot;scripts&quot;:{
&#xA0; &#xA0; &quot;source&quot;: &quot;minimal.js&quot;
&#xA0; }
}
</code></pre>
<ol start="2">
<li>Create minimal.js file with Model driver methods</li>
</ol>
<pre><code class="language-JS">this.initialize = function () {
&#xA0; &#xA0; this.run()
}

this.run = function () {
&#xA0; &#xA0; this.timeCount = this.time;
&#xA0; &#xA0; console.log(this.timeCount);
&#xA0; &#xA0; this.future(1).run();
}

this.incClicks = function () {
&#xA0; &#xA0; this.clicks = this.clicks + 1
}

this.decClicks = function () {
&#xA0; &#xA0; this.clicks = this.clicks - 1
}

this.getRandom = function () {
&#xA0; &#xA0; this.randomNumber = this.random();
}

</code></pre>
<ol start="3">
<li>Create/modify default index.vwf.js file with View driver methods.</li>
</ol>
<pre><code class="language-JS">import { h, text,patch } from &quot;$host/lib/ui/superfine.js&quot;

class UserView {

&#xA0; &#xA0; constructor(view) {
&#xA0; &#xA0; &#xA0; &#xA0; this.view = view;
&#xA0; &#xA0; &#xA0; &#xA0; this.init();
&#xA0; &#xA0; }
&#xA0; &#xA0; 

&#xA0; &#xA0; init() {
&#xA0; &#xA0; &#xA0; &#xA0; let self = this;

&#xA0; &#xA0; &#xA0; &#xA0; vwf_view.initializedNode = function (nodeID, childID, childExtendsID, childImplementsIDs,
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; childSource, childType, childIndex, childName) {
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; 
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; if (childID == vwf_view.kernel.application()) {

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; [&quot;time&quot;, &quot;clicks&quot;, &quot;random&quot;].forEach(name =&gt; {

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; let el = document.createElement(name);
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; el.setAttribute(&quot;id&quot;, name);
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; document.querySelector(&quot;body&quot;).appendChild(el);

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; })

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; self.satTime(0);
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; self.satClicks(0);
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; self.satRandom(0);

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; &#xA0; &#xA0; }

&#xA0; &#xA0; &#xA0; &#xA0; vwf_view.satProperty = function (nodeID, propertyName, propertyValue) {

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; if (propertyValue === undefined || propertyValue == null) {
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; return;
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; //let el = document.querySelector(&quot;[id=&apos;&quot; + nodeID + &quot;&apos;]&quot;);

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; if (!document.getElementById(&quot;time&quot;))
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0;return


&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; if (propertyName == &apos;timeCount&apos;) {
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; self.satTime(propertyValue);
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; }

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; if(propertyName == &apos;clicks&apos;){
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; self.satClicks(propertyValue)
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; }

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; if(propertyName == &apos;randomNumber&apos;){
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; self.satRandom(propertyValue);

&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; //update body color
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; let randomColor = Math.floor(parseFloat(propertyValue)*16777215).toString(16);
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; document.body.style.backgroundColor = &quot;#&quot; + randomColor;
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; }

&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; }

&#xA0; &#xA0; satTime(state) {
&#xA0; &#xA0; &#xA0; &#xA0; patch(
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; document.getElementById(&quot;time&quot;), 
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;time&quot;, {style: &quot;position: absolute; top: 100px; margin-left: 20px;&quot; }, [
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;h2&quot;, {}, text(&apos;Time: &apos;)), 
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;h1&quot;, {}, text(state))
&#xA0; &#xA0; &#xA0; &#xA0; ]))
&#xA0; &#xA0; }

&#xA0; &#xA0; satClicks(state) {
&#xA0; &#xA0; &#xA0; &#xA0; patch(
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; document.getElementById(&quot;clicks&quot;),
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;clicks&quot;, {style: &quot;position: absolute; top: 240px; margin-left: 20px;&quot;}, [
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;h2&quot;, {}, text(&apos;Clicks: &apos;)), 
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;h1&quot;, {}, text(state)),
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;button&quot;, { onclick: () =&gt; vwf_view.kernel.callMethod(vwf.application(), &quot;incClicks&quot;) }, text(&quot;+&quot;)),
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;button&quot;, { onclick: () =&gt; vwf_view.kernel.callMethod(vwf.application(), &quot;decClicks&quot;) }, text(&quot;-&quot;))
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; ])
&#xA0; &#xA0; &#xA0; &#xA0; )
&#xA0; &#xA0; }

&#xA0; &#xA0; satRandom(state) {
&#xA0; &#xA0; &#xA0; &#xA0; patch(
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; document.getElementById(&quot;random&quot;),
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;random&quot;, {style: &quot;position: absolute; top: 400px; margin-left: 20px;&quot;}, [
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;h2&quot;, {}, text(&apos;Random number: &apos;)), 
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;h1&quot;, {}, text(state)),
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; h(&quot;button&quot;, { onclick: () =&gt; vwf_view.kernel.callMethod(vwf.application(), &quot;getRandom&quot;) }, text(&quot;Generate&quot;))
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; ])
&#xA0; &#xA0; &#xA0; &#xA0; )
&#xA0; &#xA0; }
}

export {UserView as default}
</code></pre>
<ol start="4">
<li>Optional add Model/View drivers to the app config if needed (like editor driver etc)</li>
</ol>
<pre><code class="language-JSON">{
&#xA0; &quot;info&quot;:{
&#xA0; &#xA0; &quot;title&quot;: &quot;Minimal App&quot;
&#xA0; },
&#xA0; &quot;model&quot;: {},
&#xA0; &quot;view&quot;: {}
}
</code></pre>
<ol start="5">
<li>Optional add simple description for World catalog on it&apos;s Web page</li>
</ol>
<pre><code class="language-JSON">{
&#xA0; &#xA0; &quot;info&quot;: {
&#xA0; &#xA0; &#xA0; &#xA0; &quot;en&quot;: {
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &quot;title&quot;: &quot;Minimal app&quot;,
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &quot;imgUrl&quot;: &quot;/defaults/assets/webimg.jpg&quot;,
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &quot;text&quot;: &quot;Minimal app example&quot;
&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; }
}
</code></pre>
<p>In the <a href="http://blog.krestianstvo.org/en/collaborative-robots-rubiks-cube-lego-boost/">next post</a>, we will look into details of Functional Reactive Streams for Croquet VWF &amp; Luminary and &quot;Collaborative Robots&quot; application example.</p>
<!--kg-card-end: markdown--><h3></h3>]]></content:encoded></item><item><title><![CDATA[A-Frame multi-user Croquet component]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The component allows easily, while staying in <a href="https://aframe.io">A-Frame</a> scene definition (plain HTML file), to add a multi-user features onto A-Frame entities in scene. Create <a href="https://croquet.studio">Croquet</a> (aka Croquet V) simulations on A-Frame entities.<br>
A-Frame multi-user component works by synchronizing / replicating entities and their components to connected peers using Croquet application architecture.</p>]]></description><link>https://blog.krestianstvo.org/en/aframe-croquet-component/</link><guid isPermaLink="false">5e2c22a99bcb180001abb812</guid><category><![CDATA[Krestianstvo SDK]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Sat, 25 Jan 2020 21:42:19 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2020/01/aframe-croquet-1.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://blog.krestianstvo.org/en/content/images/2020/01/aframe-croquet-1.jpg" alt="A-Frame multi-user Croquet component"><p>The component allows easily, while staying in <a href="https://aframe.io">A-Frame</a> scene definition (plain HTML file), to add a multi-user features onto A-Frame entities in scene. Create <a href="https://croquet.studio">Croquet</a> (aka Croquet V) simulations on A-Frame entities.<br>
A-Frame multi-user component works by synchronizing / replicating entities and their components to connected peers using Croquet application architecture. It relies on public Croquet reflectors, which are avaliable online on the Internet.</p>
<p><a href="https://github.com/NikolaySuslov/aframe-croquet-component"><strong>Source code on GitHub</strong></a></p>
<p><strong>Live basic project at Glitch</strong>: <a href="https://glitch.com/~aframe-croquet-component">https://glitch.com/~aframe-croquet-component</a></p>
<hr>
<iframe src="https://player.vimeo.com/video/387187875?title=0&amp;byline=0&amp;portrait=0" width="640" height="505" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
<p><a href="https://vimeo.com/387187875">Demo video</a></p>
<h2 id="gettingstarted">Getting Started</h2>
<h3 id="howtoshareanentityinanaframescenewithotherusers">How to share an entity in an A-Frame scene with other users:</h3>
<p>Add links to this component and croquet lib in the html header</p>
<pre><code class="language-html">&lt;script src=&quot;https://croquet.studio/sdk/croquet-latest.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://unpkg.com/aframe-croquet-component/public/lib/aframe-croquet-component.js&quot;&gt;&lt;/script&gt;
</code></pre>
<p>Add <code>croquet</code> component to the root <a-scene> element and give a name to the Croquet session</a-scene></p>
<pre><code class="language-html">&lt;a-scene croquet=&quot;sessionName: demo-scene&quot;&gt;
</code></pre>
<p>Give an <code>id</code> to the entity (if not exist) and finally add <code>multiuser</code> component</p>
<pre><code class="language-html"> &lt;a-box id=&quot;box1&quot; position=&quot;-1.5 1 -3&quot; rotation=&quot;0 45 0&quot; color=&quot;#4CC3D9&quot; multiuser&gt;&lt;/a-box&gt;
</code></pre>
<p>Open the same scene in several Web Browsers windows. The entity should be synced!</p>
<h3 id="howtotryoutthesynchronization">How to try out the synchronization:</h3>
<p>Open Web Browser Developer Tools and select an entity with <code>multiuser</code> component</p>
<pre><code class="language-js">let box = document.querySelector(&apos;a-scene&apos;).querySelector(&apos;#box1&apos;)
</code></pre>
<p>Change entity attributes like, position, rotation, geometry or material etc., by replicating the entity properties</p>
<pre><code class="language-js">box.setAttribute(&apos;position&apos;, {x:0, y: 1, z: -4});
box.setAttribute(&apos;rotation&apos;, {x:0, y: 45, z: 0});
box.setAttribute(&apos;material&apos;, {color: &apos;#4BAC41&apos;});
box.setAttribute(&apos;geometry&apos;, {width: 3});
</code></pre>
<p>Start a Croquet application attached to an entity, by replicating a computation (animation example)</p>
<pre><code class="language-js">box.setAttribute(&apos;multiuser&apos;, {anim: true});
</code></pre>
<p>Also you could try to attach to scene the <a href="https://github.com/aframevr/aframe-inspector">A-Frame scene Inspector</a> by pressing <code>&lt;ctrl&gt; + &lt;alt&gt; + i</code>. Modify entity properties within it&apos;s GUI and observe how some of the properties replicates on other peers.</p>
<h2 id="basicsceneexample">Basic Scene Example</h2>
<p><a href="./public/index.html">source code</a></p>
<pre><code class="language-html">&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;A-Frame &amp; Croquet&lt;/title&gt;
  &lt;script src=&quot;https://croquet.studio/sdk/croquet-latest.min.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;https://aframe.io/releases/1.0.3/aframe.min.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;https://unpkg.com/aframe-croquet-component/public/lib/aframe-croquet-component.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;a-scene croquet=&quot;sessionName: demo-scene&quot;&gt;
    &lt;a-box id=&quot;box1&quot; position=&quot;-1.5 1 -3&quot; rotation=&quot;0 45 0&quot; color=&quot;#4CC3D9&quot; multiuser=&quot;anim: true&quot;&gt;&lt;/a-box&gt;
    &lt;a-sphere id=&quot;sphere1&quot; position=&quot;0 1.25 -5&quot; radius=&quot;1.25&quot; color=&quot;#EF2D5E&quot; multiuser&gt;&lt;/a-sphere&gt;
    &lt;a-cylinder id=&quot;cylinder1&quot; position=&quot;1 0.75 -3&quot; radius=&quot;0.5&quot; height=&quot;1.5&quot; color=&quot;#FFC65D&quot;&gt;&lt;/a-cylinder&gt;
    &lt;a-plane id=&quot;plane1&quot; position=&quot;0 0 -4&quot; rotation=&quot;-90 0 0&quot; width=&quot;4&quot; height=&quot;4&quot; color=&quot;#7BC8A4&quot; multiuser&gt;&lt;/a-plane&gt;
    &lt;a-sky color=&quot;#ECECEC&quot;&gt;&lt;/a-sky&gt;
  &lt;/a-scene&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Krestianstvo Luminary for Open Croquet architecture and Virtual World Framework in peer-to-peer Web]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>[UPDATED 10.2019]</strong></p>
<blockquote>
<p><strong>Krestianstvo Luminary</strong> functional prototype is avaliable to try out at <a href="https://livecoding.space">https://livecoding.space</a> and it&apos;s source code at <a href="https://github.com/NikolaySuslov/livecodingspace">LiveCoding.space GitHub repository master branch</a></p>
</blockquote>
<p>Everyone who is familiar with <a href="https://en.wikipedia.org/wiki/Croquet_Project">Croquet architecture</a> are anticipating (waiting breathless) the updates for Open Croquet architecture from <strong>Croquet V</strong> by</p>]]></description><link>https://blog.krestianstvo.org/en/krestianstvo-luminary-for-open-croquet-architecutre-and-virtual-world-framework-in-peer-to-peer-web/</link><guid isPermaLink="false">5d023e87c2f8480001f56c97</guid><category><![CDATA[Krestianstvo SDK]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Fri, 14 Jun 2019 02:11:06 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2019/06/luminary-1.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://blog.krestianstvo.org/en/content/images/2019/06/luminary-1.jpg" alt="Krestianstvo Luminary for Open Croquet architecture and Virtual World Framework in peer-to-peer Web"><p><strong>[UPDATED 10.2019]</strong></p>
<blockquote>
<p><strong>Krestianstvo Luminary</strong> functional prototype is avaliable to try out at <a href="https://livecoding.space">https://livecoding.space</a> and it&apos;s source code at <a href="https://github.com/NikolaySuslov/livecodingspace">LiveCoding.space GitHub repository master branch</a></p>
</blockquote>
<p>Everyone who is familiar with <a href="https://en.wikipedia.org/wiki/Croquet_Project">Croquet architecture</a> are anticipating (waiting breathless) the updates for Open Croquet architecture from <strong>Croquet V</strong> by David A. Smith and <a href="https://croquet.studio">Croquet Studios</a>!</p>
<p>However, while working on <a href="https://www.krestianstvo.org/sdk3">LiveCoding.space</a> project by Krestianstvo.org that is heavily based on <a href="https://en.wikipedia.org/wiki/Virtual_world_framework">Virtual World Framework</a> (containing elements of Open Croquet architecture), I have started revising the current Reflector server.</p>
<p>Let me introduce to you an ideas and early prototype of the <strong>Krestianstvo Luminary</strong> for Open Croquet architecture and Virtual World Framework.<br>
<strong>Krestianstvo Luminary</strong> potentially could replace Reflector server in flavour of using offline-first <a href="https://gun.eco/docs/Introduction">Gun DB</a> pure distributed storage system. That allows instead of &#x2018;Reflecting&#x2019; messages with centralised Croquet&#x2019;s time now, to &#x2018;Shining&#x2019; time on every connected node using Gun&#x2019;s <a href="https://gun.eco/docs/Hypothetical-Amnesia-Machine">Hypothetical Amnesia Machine</a>, running in peer-to-peer Web. Also to secure all external messages streams by using peer-to-peer identities and <a href="https://gun.eco/docs/SEA">SEA</a> cryptographic library for Gun DB. More over running Luminary on <a href="https://gun.eco/docs/AXE#faq">AXE</a> blockchain.<br>
<strong>Krestianstvo Luminary</strong> simply transforms the only server related Croquet&#x2019;s part - Reflector (taken from VWF version) into the pure peer-to-peer application, running on a client&#x2019;s Web Browsers.</p>
<p><img src="http://blog.krestianstvo.org/en/content/images/2019/06/Reflector-vs-Luminary.jpg" alt="Krestianstvo Luminary for Open Croquet architecture and Virtual World Framework in peer-to-peer Web" loading="lazy"></p>
<p>For those who are not familiar with Open Croquet architecture, just want to mark key principals behind it in simple words.</p>
<p><img src="http://blog.krestianstvo.org/en/content/images/2019/06/croquet-reflector.jpg" alt="Krestianstvo Luminary for Open Croquet architecture and Virtual World Framework in peer-to-peer Web" loading="lazy"></p>
<h3 id="croquetarchitecture">Croquet Architecture</h3>
<p>Croquet introduced the notion of virtual time for decentralised computations. Thinking on objects as stream of messages, which lead to deterministic computations on every connected node in decentralised network. All computations are done on every node by itself while interpreting an internal queue of messages, which are not replicated to the network. But these queues are synchronised by an external heartbeat messages coming from Reflector - a tiny server. Also any node&#x2019;s self generated messages, which should be distributed to other nodes are marked as external. They are explicitly routed to the Reflector, where the are stamped with the Reflector&#x2019;s time now and are returned back to the node itself and all other nodes on the network.<br>
Reflector is not only used for sending heartbeat messages, stamping external messages, but also it is used for holding the list of connected clients, list of running virtual world instances, bootstrapping new client connections.</p>
<h3 id="reflector">Reflector</h3>
<p>So, in Croquet architecture for decentralised networks, the Reflector while being a very tiny or even being a micro service - it remains a server.<br>
It uses WebSockets for coordinating clients, world instances, providing &#x2018;now time&#x2019; for the clients, reflecting external messages.</p>
<p>Let&#x2019;s look how it works in Virtual World Framework (VWF). I will use the available open source code from VWF, which I am using in LiveCoding.space project by Krestianstvo.org</p>
<p>That&#x2019;s a function returning time now by Reflector. Time is getting from a machine, running a Reflector server:<br>
(server code from <strong>lib/reflector.js</strong>)</p>
<pre><code>function GetNow( ) {
    return new Date( ).getTime( ) / 1000.0;
}
</code></pre>
<p>Then it uses to make a stamp for a virtual world instance:</p>
<pre><code>return ( GetNow( ) - this.start_time ) * this.rate
</code></pre>
<p>Reflector send this time stamps using WebSockets. And on a client side VWF has a method for dispatching:<br>
(client code from <strong>public/vwf.js</strong>)</p>
<pre><code>socket.on( &quot;message&quot;, function( message ) {
	var fields = message;
	&#x2026;.
	fields.time = Number( fields.time );
	fields.origin = &quot;reflector&quot;;
	queue.insert( fields, !fields.action );
	&#x2026;.
</code></pre>
<p>Look at send and respond methods, where clients use WebSocket to send external messages back to the Reflector:</p>
<pre><code>   var message = JSON.stringify( fields );
   socket.send( message );
</code></pre>
<h3 id="luminary">Luminary</h3>
<p>Now, let&#x2019;s look at how Krestianstvo Luminary could identically replace the Reflector server.</p>
<p><img src="http://blog.krestianstvo.org/en/content/images/2019/06/luminary.jpg" alt="Krestianstvo Luminary for Open Croquet architecture and Virtual World Framework in peer-to-peer Web" loading="lazy"></p>
<p>First of all clients are never forced using WebSockets directly from the application itself for sending or receiving messages. Instead Gun DB responds for that functionality internally. All operations which previously relay on WebSocket connection are replaced by subscribing to updates and changes on a Gun DB nodes and properties.<br>
So, instances, clients - are just Gun DB nodes, available to all connected peers. In that scene, the required Reflector&#x2019;s application logic is moving from the server to the clients. As, every client on any moment of time could get actual information about instance he is connected to, clients on that instance, etc. Just requesting a node on Gun DB.</p>
<p>Now, about time.</p>
<p>Instead of using machine&#x2019;s new Date().getTime(), Krestianstvo Luminary uses state from Gun&#x2019;s <a href="https://gun.eco/docs/Hypothetical-Amnesia-Machine">Hypothetical Amnesia Machine</a>, which combines timestamps, vector clocks, and a conflict resolution algorithm. So, every written property on a Gun&#x2019;s node stamped with HAM. This state is identical for all peers. That&#x2019;s meaning that we could get this state just on any client.<br>
Taking in consideration that Gun DB guaranteers that, every change on every node or property will be delivered in right order to all peers. We could make a heartbeat node and subscribe peers to it updates.</p>
<p>Here is the code for creating a heartbeat for VWF:</p>
<pre><code>Gun.chain.heartbeat = function (time, rate) {
              // our gun instance
              var gun = this;
              gun.put({
                  &apos;start_time&apos;: &apos;start_time&apos;,
                  &apos;rate&apos;: 1
              }).once(function (res) {
                  // function to start the timer
                  setInterval(function () {
                      let message = {
                          parameters: [],
                          time: &apos;tick&apos;
                      };
                      gun.get(&apos;tick&apos;).put(JSON.stringify(message));
                  }, 50);
              })
  
              // return gun so we can chain other methods off of it
              return gun;
          }

</code></pre>
<p>Client, which start firstly or create a new virtual world instance, create heartbeat node for that instance and run a metronome (that part could be run on Gun DB instance somewhere on the hosting server, for anytime availability):</p>
<pre><code>let instance = _LCSDB.get(vwf.namespace_); //
instance.get(&apos;heartbeat&apos;).put({ tick: &quot;{}&quot; }).heartbeat(0.0, 1);
</code></pre>
<p>So, every 50 ms, this client will writes to property &#x2018;tick&#x2019; the message content, thus changing it, so Gun HAM will move the state for this property, stamping it with the new unique value, from which the Croquet time will be calculated later.<br>
The start time will be the state value of HAM at &#x2018;start_time&#x2019; property, of heartbeat node. Please notice, that actual Croquet timestamp is not calculated here, as it was in Reflector server. The timestamp used for the Croquet internal queue of messages will be calculated on reading of &#x2018;tick&#x2019; by the VWF client in it&#x2019;s main application.</p>
<p>Here is the simplified core version of dispatching &#x2018;tick&#x2019; on VWF client main app, just to get the idea: (full code on <strong>public/vwf.js</strong>, links below)</p>
<pre><code>let instance = _LCSDB.get(vwf.namespace_);

instance.get(&apos;heartbeat&apos;).on(function (res) { 
   if(res.tick) {
	let msg = self.stamp(res, start_time, rate);

	queue.insert(fields, !fields.action);

	}
}

this.stamp = function(source, start_time, rate) {

           	let message = JSON.parse(source.tick);

            message.state = Gun.state.is(source, &apos;tick&apos;);
            message.start_time = start_time; //Gun.state.is(source, &apos;start_time&apos;);
            message.rate = rate; //source.rate;

            var time = ((message.state - message.start_time)*message.rate)/1000;

            if (message.action == &apos;setState&apos;){
                time = ((_app.reflector.setStateTime - message.start_time)*message.rate)/1000;
            }
            message.time = Number( time );
            message.origin = &#x201C;reflector&quot;;

            return message
        }

</code></pre>
<p>The main point here is the calculation of Croquet time using Gun&#x2019;s HAM state:</p>
<pre><code>Gun.state.is ( node, property )
</code></pre>
<p>for message:</p>
<pre><code>message.state = Gun.state.is(source, &#x2018;tick&#x2019;); // time of updating tick
message.start_time = Gun.state.is(source, &#x2018;start_time&apos;); //start time of the instance heartbeat
message.rate = source.rate;
var time = ((message.state - message.start_time)*message.rate)/1000;
</code></pre>
<p>So, all peers will calculate exactly the same Croquet time on getting an update from Gun DB,  regardless of the time when they get this update (network delays, etc).</p>
<p>As you could imagine, sending external messages will be as simple as just writing the message by a peer to an instance heartbeat with a new message&#x2019;s content. All connected peers and a peer itself will get that message, stamped with Croquet time, while they are subscribed on changes on heartbeat node (look above at <strong>instance.get(&#x2018;heartbeat&#x2019;).on()</strong> definition )</p>
<pre><code>instance.get(&apos;heartbeat&apos;).get(&apos;tick&apos;).put(JSON.stringify(newMsg));
</code></pre>
<p>Actually that&#x2019;s it!</p>
<h3 id="conclusions">Conclusions</h3>
<ul>
<li>Reflector server is no longer required for running virtual worlds (any existed GunDB instance on a network fits, could know nothing about Croquet and clients)</li>
<li>clients, world instances, connecting logic are hold by a distributed DB</li>
<li>stamping messages are doing by clients themselves using Gun&#x2019;s HAM</li>
<li>one dedicated peer, producing metronome empty messages for moving time forward (could be anywhere)</li>
</ul>
<p>All advantages that Gun DB provides, could be applicable inside a Croquet Architecture. One of scenarios could be the use of <a href="https://gun.eco/docs/Timegraph">Gun&#x2019;s Timegraph</a>. That&#x2019;s will allow to store and retrieve the history of messages for recording and replaying later. Using SEA Security, Encryption, &amp; Authorization library, will allow to create a highly secure instance&#x2019;s heartbeats using peer-to-peer identifies and being deplyed anywhere, anytime available on AXE blockchain.</p>
<h3 id="issues">Issues</h3>
<p><strong>[UPDATED 10.2019]</strong></p>
<blockquote>
<p><strong>Krestianstvo Luminary functional prototype is avaliable to try out at <a href="https://livecoding.space">https://livecoding.space</a></strong></p>
</blockquote>
<p><s>For making a fully functional prototype, there are still an issues in porting Reflector application logic to a functional-reactive Gun DB architecture nature. That concerns to the procedure of connecting clients to a running instance. As it is connected with getting/setting instance state, pending messages and then replaying them on a new connected peers. But, all that is not critical, as does not affect the main idea behind Krestianstvo Luminary.</s><br>
There are performance issues, as Gun DB is using <a href="https://gun.eco/docs/RAD">RAD storage adapter</a>. But configuring several RAD options could be helpful, concerning <strong>opt.chunk</strong> and <strong>opt.until</strong> (due to RAD or JSON parse time for each chunk).</p>
<h3 id="sourcecode">Source code</h3>
<p><strong>[UPDATED 10.2019]</strong><br>
The source code of the latest functional prototype is avaliable under <strong>master branch</strong> at <a href="https://github.com/NikolaySuslov/livecodingspace">LiveCoding.space GitHub repository</a></p>
<p><s>The raw code is available at <a href="https://github.com/NikolaySuslov/livecodingspace">LiveCoding.space GitHub repository</a> under the <a href="https://github.com/NikolaySuslov/livecodingspace/tree/luminary">branch <strong>&#x2018;luminary&#x2019;</strong></a>.</s></p>
<p><s>The <a href="https://github.com/NikolaySuslov/livecodingspace/tree/luminary-partial">branch <strong>&#x2018;luminary-partial&#x2019;</strong></a> contains working prototype of partial Luminary, when one master-client is chosen for reflector logic, it uses <strong>Gun.state()</strong> for stamping messages, as it was done in the original reflector app, and then distribute as updates to other peers through Gun DB.</s></p>
<p>Thanks for reading and I will be gladfull if you will share your comments and visions on that.</p>
<p>Nikolai Suslov</p>
<!--kg-card-end: markdown--><p></p>]]></content:encoded></item><item><title><![CDATA[Open Croquet for Squeak 6.x]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>UPDATED 03/2020: <strong>Please use the latest code and instructions for that Open Croquet integration from GitHub project <a href="https://github.com/NikolaySuslov/croquet-squeak">https://github.com/NikolaySuslov/croquet-squeak</a></strong>. There is also a fix for using it with recent Squeak 5.3 image.</p>
</blockquote>
<blockquote>
<p>UPDATED 10/2018: <strong>That Open Croquet integration also applies for the current <a href="https://squeak.org">Squeak</a></strong></p></blockquote>]]></description><link>https://blog.krestianstvo.org/en/open-croquet-for-squeak-6/</link><guid isPermaLink="false">5a947f887a7b3d0001c0f4b2</guid><category><![CDATA[Smalltalk]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Mon, 26 Feb 2018 21:59:26 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2018/02/croquet-squeak6.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<img src="http://blog.krestianstvo.org/en/content/images/2018/02/croquet-squeak6.jpg" alt="Open Croquet for Squeak 6.x"><p>UPDATED 03/2020: <strong>Please use the latest code and instructions for that Open Croquet integration from GitHub project <a href="https://github.com/NikolaySuslov/croquet-squeak">https://github.com/NikolaySuslov/croquet-squeak</a></strong>. There is also a fix for using it with recent Squeak 5.3 image.</p>
</blockquote>
<blockquote>
<p>UPDATED 10/2018: <strong>That Open Croquet integration also applies for the current <a href="https://squeak.org">Squeak 5.2 release</a></strong></p>
</blockquote>
<p>Restoring the original Open Croquet onto Squeak 6.x. (experimental).<br>
For a long time, the community avaliable Open Croquet images exist only in bootstrap images for Squeak 3.8 and for Squeak 4.2. Actually, there is no any open solution to use the latest Squeak VM and Smalltalk language with Open Croquet architecure. So, that starting from the original version to OpenQwaq, anyone could load it from scratch onto the new Squeak.<br>
Below you could find install instructions, links and first steps in achiving this.</p>
<p>Demo-video: <a href="https://vimeo.com/257578323">https://vimeo.com/257578323</a></p>
<iframe src="https://player.vimeo.com/video/257578323?title=0&amp;byline=0&amp;portrait=0" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>  
<h3 id="copmaringtotheoriginalopencroquetforsqueak3842">Copmaring to the original Open Croquet for Squeak 3.8/4.2:</h3>
<ul>
<li>No Embeded Morphic apps (bugs)</li>
<li>No Tweak (yet)</li>
<li>Original TContactPoint (find master on network) broadcaster/listener is replaced with WebSocket broadcaster/listener using WebClient (switching from UDP)</li>
<li>Island snapshoting/serializing/restoring needs deep review</li>
</ul>
<h2 id="instructionsandlinks">Instructions and Links:</h2>
<blockquote>
<p>UPDATED: 10/2018  <strong>Instructions For Squeak 5.2</strong></p>
</blockquote>
<ol>
<li>Download an official 32bit <a href="http://files.squeak.org/5.2/Squeak5.2-18225-32bit/">Squeak 5.2 VM &amp; Image</a></li>
<li>Do It in Workspace: <code>(Installer fromUrl: &apos;http://sdk.krestianstvo.org/sdk/croquet/croquet-sn.3.mcm&apos;) install</code></li>
<li>Download and place an additional content from <a href="https://www.krestianstvo.org/sdk/croquet/Content.zip">https://www.krestianstvo.org/sdk/croquet/Content.zip</a> to the /Contents/Resources folder</li>
<li>In Objects will be the category Croquet to experiment with.</li>
</ol>
<p>Preloaded Squeak image (<strong>version as of October 2018</strong>):</p>
<ul>
<li>
<p><strong>All-In-One Squeak VM and image with preloaded Croquet and content</strong>: <a href="https://www.krestianstvo.org/sdk/croquet/Squeak5.2-18225-32bit-All-in-One-Croquet.zip">https://www.krestianstvo.org/sdk/croquet/Squeak5.2-18225-32bit-All-in-One-Croquet.zip</a></p>
</li>
<li>
<p><strong>Only Squeak image with preloaded Croquet</strong>: <a href="https://www.krestianstvo.org/sdk/croquet/Squeak5.2-18225-32bit-Croquet-Image.zip">https://www.krestianstvo.org/sdk/croquet/Squeak5.2-18225-32bit-Croquet-Image.zip</a></p>
</li>
</ul>
<hr>
<p>Preloaded Squeak image (<strong>version as of February 2018</strong>):</p>
<ul>
<li>
<p><strong>Squeak VM and image with preloaded Croquet and content</strong>: <a href="https://www.krestianstvo.org/sdk/croquet/CroquetForSqueak6-App-MacWin-32bit.zip">https://www.krestianstvo.org/sdk/croquet/CroquetForSqueak6-App-MacWin-32bit.zip</a></p>
</li>
<li>
<p><strong>Only Squeak image with preloaded Croquet and content</strong>: <a href="https://www.krestianstvo.org/sdk/croquet/CroquetForSqueak6-Image-resources.zip">https://www.krestianstvo.org/sdk/croquet/CroquetForSqueak6-Image-resources.zip</a></p>
</li>
<li>
<p><strong>Only content (Textures, Models, etc.)</strong>: <a href="https://www.krestianstvo.org/sdk/croquet/Content.zip">https://www.krestianstvo.org/sdk/croquet/Content.zip</a></p>
</li>
</ul>
<p>How to install manually:</p>
<ol>
<li>Get the latest Squeak VM with included <strong>B3DAcceleratorPlugin(!)</strong><br>
The preloaded app uses VM cog.spur 32 bit for Mac/Windows:</li>
</ol>
<ul>
<li>Win: <a href="https://bintray.com/opensmalltalk/vm/download_file?file_path=squeak.cog.spur_win32x86_201802232356.zip">https://bintray.com/opensmalltalk/vm/download_file?file_path=squeak.cog.spur_win32x86_201802232356.zip</a></li>
<li>Mac: <a href="https://bintray.com/opensmalltalk/vm/download_file?file_path=squeak.cog.spur_macos32x86_201802232356.dmg">https://bintray.com/opensmalltalk/vm/download_file?file_path=squeak.cog.spur_macos32x86_201802232356.dmg</a></li>
</ul>
<ol start="2">
<li>
<p>Get the latest Squeak 6.x image from <a href="http://files.squeak.org/6.0alpha/">http://files.squeak.org/6.0alpha/</a><br>
The preloaded app uses <a href="http://files.squeak.org/6.0alpha/Squeak6.0alpha-17606-32bit/">http://files.squeak.org/6.0alpha/Squeak6.0alpha-17606-32bit/</a></p>
</li>
<li>
<p>Run Squeak.</p>
</li>
<li>
<p>In Workspace DoIt:<br>
(Installer fromUrl: &apos;<a href="http://sdk.krestianstvo.org/sdk/croquet/croquet-sn.2.mcm">http://sdk.krestianstvo.org/sdk/croquet/croquet-sn.2.mcm</a>&apos;) install</p>
</li>
</ol>
<p>This will load FFI, OpenGL and Croquet packages from the project&apos;s repository &quot;Croquet for Squeak 6.x&quot;.</p>
<p>MCHttpRepository<br>
location: &apos;<a href="http://sdk.krestianstvo.org/sdk/croquet">http://sdk.krestianstvo.org/sdk/croquet</a>&apos;<br>
user: &apos;&apos;<br>
password: &apos;&apos;</p>
<p>Or you could manually load FFI at first:</p>
<p>(Installer repository: &apos;<a href="http://source.squeak.org/FFI">http://source.squeak.org/FFI</a>&apos;)<br>
install: &apos;FFI-Pools&apos;;<br>
install: &apos;FFI-Kernel&apos;;<br>
install: &apos;FFI-Tests&apos;.</p>
<p>and then only OpenGL and Croquet packages:<br>
(Installer fromUrl: &apos;<a href="http://sdk.krestianstvo.org/sdk/croquet/croquet-sn.1.mcm">http://sdk.krestianstvo.org/sdk/croquet/croquet-sn.1.mcm</a>&apos;) install</p>
<ol start="5">
<li>Open &apos;Objects&apos; in Squeak and choose &apos;Croquet&apos; category.<br>
Drag Croquet(Master) or Demo(Master) onto the empty space.</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Virtual World Framework & A-Frame]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In this post I want to share the details about the latest project being done on Krestianstvo SDK.<br>
<a href="https://en.wikipedia.org/wiki/Virtual_world_framework">Virtual World Framework</a> provides a robust decentralised architecture for building virtual world apps based on replicated computation model. It&apos;s JavaScript version is strongly based on <a href="https://threejs.org">ThreeJS</a> library for programming apps</p>]]></description><link>https://blog.krestianstvo.org/en/virtual-world-framework-a-frame/</link><guid isPermaLink="false">5a1c9eee34134f0001da24ee</guid><category><![CDATA[Krestianstvo SDK]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Mon, 20 Mar 2017 23:37:56 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2017/03/site.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://blog.krestianstvo.org/en/content/images/2017/03/site.jpg" alt="Virtual World Framework &amp; A-Frame"><p>In this post I want to share the details about the latest project being done on Krestianstvo SDK.<br>
<a href="https://en.wikipedia.org/wiki/Virtual_world_framework">Virtual World Framework</a> provides a robust decentralised architecture for building virtual world apps based on replicated computation model. It&apos;s JavaScript version is strongly based on <a href="https://threejs.org">ThreeJS</a> library for programming apps with 3D visualisation and deep interaction support. So, for building such apps, the developer should be aware of ThreeJS internals, not to mention the knowing of the VWF component&apos;s architecture. But, actually VWF is working just with any programmable elements whatever simple they are. The <a href="https://aframe.io">A-Frame</a> framework solves the problem of ThreeJS &#x441;omplexity for developing Web apps for Virtual Reality. It provides the component-based architecture for that. A-Frame incapsulates ThreeJS, hiding the internals, and providing high-level interface for describing web app declaratively.<br>
So, I have developed a model and view drivers for VWF, that provides basic support for using A-Frame components in Virtual World Framework apps. That allows to build a VWF collaborative apps with 3D visualisation, WebVR, HMD, trackers and mobile devices support easily.</p>
<p>LiveCoding.space</p>
<blockquote>
<p><a href="https://github.com/NikolaySuslov/livecodingspace">Source code at GitHub</a></p>
</blockquote>
<p>Code for using in original VWF</p>
<blockquote>
<p><a href="https://github.com/NikolaySuslov/vwf/tree/aframe">Source code at GitHub</a></p>
</blockquote>
<p>Here is a small video demonstration, that shows the interaction within collaborative <a href="https://en.wikipedia.org/wiki/Virtual_world_framework">Virtual World Framework</a> app, which is composed by the <a href="https://aframe.io">A-Frame</a> components.</p>
<iframe src="https://player.vimeo.com/video/209128951?title=0&amp;byline=0&amp;portrait=0" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<p>In the video three Google Chrome web-browsers are directing to the same VWF app instance&apos;s URL. Every browser shows the replicated A-Frame scene with components in it. The users are represented with small cubes and are visible to each other. The cube on the right is holding the simulation, which is staying the same on all browsers.</p>
<blockquote>
<p>Try online demo here: <a href="https://livecoding.space">https://livecoding.space</a></p>
</blockquote>
<p>Simple scenario for collaboration:</p>
<ul>
<li>Open in Web-browser the given URL (<a href="http://demo.krestianstvo.org">http://demo.krestianstvo.org</a>)</li>
<li>Copy the generated URL and open it in another browser window<br>
or direct Web-browser to <a href="http://demo.krestianstvo.org/app">http://demo.krestianstvo.org/app</a>,<br>
where you could find all running VWF app instances to join to.</li>
<li>Open the generated URL at your phone or tablet.</li>
<li>Move in space with arrows or WASD and point objects with a cursor in the centre of the screen (this will generate Click event).</li>
<li>You could create any number of isolated VWF app instances, but for connecting to them you will need to know the generated URL.</li>
</ul>
<p>So, how a simple VWF app with A-Frame is look like?<br>
Here is a simple code of <strong>index.vwf.yaml</strong>:</p>
<pre><code>extends: http://vwf.example.com/aframe/ascene.vwf
properties:
children:
  spaceText:
    extends: http://vwf.example.com/aframe/atext.vwf
    properties:
      value: &quot;Virtual World Framework &amp; A-Frame&quot;
      textColor: &quot;#b74217&quot;
      position: [-2, 2.5, -2]
  sphere:
    extends: http://vwf.example.com/aframe/asphere.vwf
    properties:
      position: [1, 1.25, -4]
      color: &quot;#e0e014&quot;
      radius: 1
      wireframe: true
    children:
      box2:
        extends: http://vwf.example.com/aframe/abox.vwf
        properties:
          position: [2, -1.25, 0]
          color: &quot;#2167a5&quot;
          depth: 1
  sky:
    extends: http://vwf.example.com/aframe/asky.vwf
    properties:
      color: &quot;#ECECEC&quot;
  camentity:
    extends: http://vwf.example.com/aframe/aentity.vwf
    properties:
      position: [0, 0, 0]
    children:
      camera:
        extends: http://vwf.example.com/aframe/acamera.vwf
        properties:
          look-controls-enabled: true
          forAvatar: true
        children:
          cursor:
            extends: http://vwf.example.com/aframe/acursor.vwf 
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Virtual World Framework & Ometa (Ohm)]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A year has passed as the first prototype of integration of <a href="http://krestianstvo.org/projects/en/vwf-ometa/">Virtual World Framework &amp; Ometa</a> was presented at SPLASH&apos;14 <a href="http://www.future-programming.org/2014/program.html">Future Programming Workshop</a>. In 2015 the new version or &quot;subling&quot; of an Object-Oriented Language for Pattern Matching <a href="http://tinlizzie.org/ometa/">Ometa</a> was publicly introduced with the name <a href="https://github.com/cdglabs/ohm">Ohm</a>. As</p>]]></description><link>https://blog.krestianstvo.org/en/virtual-world-framework-ometa-ohm/</link><guid isPermaLink="false">5a1c9eee34134f0001da24ec</guid><category><![CDATA[Krestianstvo SDK]]></category><dc:creator><![CDATA[Nikolai Suslov]]></dc:creator><pubDate>Mon, 30 Nov 2015 11:24:00 GMT</pubDate><media:content url="http://blog.krestianstvo.org/en/content/images/2015/11/lsystem-1.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://blog.krestianstvo.org/en/content/images/2015/11/lsystem-1.jpg" alt="Virtual World Framework &amp; Ometa (Ohm)"><p>A year has passed as the first prototype of integration of <a href="http://krestianstvo.org/projects/en/vwf-ometa/">Virtual World Framework &amp; Ometa</a> was presented at SPLASH&apos;14 <a href="http://www.future-programming.org/2014/program.html">Future Programming Workshop</a>. In 2015 the new version or &quot;subling&quot; of an Object-Oriented Language for Pattern Matching <a href="http://tinlizzie.org/ometa/">Ometa</a> was publicly introduced with the name <a href="https://github.com/cdglabs/ohm">Ohm</a>. As OMeta, it supports the same object-oriented grammar extension and allows pattern matching on structured data as well as strings, but now it also features a complete separation of grammars from semantic actions and a lot more.</p>
<blockquote>
<p>In this post I want to present an updated prototype, which now uses the new language Ohm!</p>
</blockquote>
<p>To try out, just open this <a href="http://vle.krestianstvo.org/adl/sandbox/world/r1zgmKCYHmspu0Mn"><strong>link</strong></a> in the web browser and enter the virtual world containing a simple <a href="https://en.wikipedia.org/wiki/L-system">L-System</a> generator. To modify the world, you could clone it or create your own and use the &quot;Content Library&quot; from the left side GUI for dragging L-System&apos;s entities.<br>
<img src="http://blog.krestianstvo.org/en/content/images/2015/11/lsystem-en.jpg" alt="Virtual World Framework &amp; Ometa (Ohm)" loading="lazy"><br>
You could modify any parameters of a selected L-System&apos;s entity in realtime, like: angle, iteration, axioms. Even more, you could redefine a grammar using the Script Editor, while not disrupting other entities.</p>
<hr>
<h6 id="firststepstutorial">First steps tutorial</h6>
<p>Here is a simple tutorial on how to attach your own grammar with corresponding semantics actions to an entity inside virtual world using <a href="https://github.com/adlnet/Sandbox">ADL Sandbox</a> and <a href="https://github.com/cdglabs/ohm">Ohm language</a> integration prototype. As an example we will use the Arithmetic calculator grammar from the Ohm language tutorial.<br>
So, in this tutorial we&apos;ll define the grammar for parsing simple arithmetic expressions from string; add an operation to it&apos;s semantics that can be used to evaluate the provided arithmetic expressions; attach it to the virtual worlds&apos;s entity and  show the result of evaluation in itself.<br>
The working tutorial for cloning is here: <a href="http://live.net.ru/adl/sandbox/world/WRpbHEuHfYGmUm54">http://live.net.ru/adl/sandbox/world/WRpbHEuHfYGmUm54</a></p>
<p>At first, please register at <a href="http://live.net.ru"><strong>http://live.net.ru</strong></a> the project of <a href="http://www.krestianstvo.org"><strong>http://www.krestianstvo.org</strong></a>.<br>
Being registered you could create your own virtual worlds or clone an existed ones to experiment with.</p>
<p><strong>1.</strong> Create a world using web interface and enter it:</p>
<p><img src="http://blog.krestianstvo.org/en/content/images/2015/11/createworld.jpg" alt="Virtual World Framework &amp; Ometa (Ohm)" loading="lazy"></p>
<p><strong>2.</strong> Inside a virtual world create a 3D Text entity for matching grammar and showing our calculator&apos;s result:</p>
<p><img src="http://blog.krestianstvo.org/en/content/images/2015/11/createtext.png" alt="Virtual World Framework &amp; Ometa (Ohm)" loading="lazy"></p>
<p><strong>3.</strong> Open Script Editor for the selected object (3D text) and create a new property for it with the name: <strong>ohmCalc</strong>. The name of the grammar should be necessarily starts with the &apos;<strong>ohm</strong>&apos; prefix! As it points the Virtual World Framework model driver to provide ohm language stuff for the selected entity (actually Ohm language driver is loaded at world startup and makes an access to Ohm trough  <strong>_ohm</strong> global variable). In this tutorial the grammar object is automatically generated and stored in <strong>Calc</strong> property.<br>
Copy the provided Arithmetic grammar&apos;s source code into the property <strong>ohmCalc</strong>:</p>
<p><img src="http://blog.krestianstvo.org/en/content/images/2015/11/openscripteditor-1.jpg" alt="Virtual World Framework &amp; Ometa (Ohm)" loading="lazy"></p>
<p>Arithmetic grammar&apos;s source code:</p>
<pre><code>Arithmetic {
  Exp
    = AddExp
    
  AddExp
    = AddExp &quot;+&quot; MulExp  -- plus
    | AddExp &quot;-&quot; MulExp  -- minus
    | MulExp

  MulExp
    = MulExp &quot;*&quot; ExpExp  -- times
    | MulExp &quot;/&quot; ExpExp  -- divide
    | ExpExp

  ExpExp
    = PriExp &quot;^&quot; ExpExp  -- power
    | PriExp

  PriExp
    = &quot;(&quot; Exp &quot;)&quot;  -- paren
    | &quot;+&quot; PriExp   -- pos
    | &quot;-&quot; PriExp   -- neg
    | ident
    | number
    
  ident  (an identifier)
    = letter alnum*

  number  (a number)
    = digit* &quot;.&quot; digit+  -- fract
    | digit+             -- whole
}
</code></pre>
<p><strong>4.</strong> Create new method, in which we will define an operation for our calculator semantics. The semantics is accessible trough automatic generated entity&apos;s property at <strong>Engine.getProperty(this.id, &apos;semanticsCalc&apos;)</strong>. Copy the provided code of &apos;interpret&apos; operation into the new method with the name <strong>addOperationCalc</strong><br>
<img src="http://blog.krestianstvo.org/en/content/images/2015/11/initfunction.jpg" alt="Virtual World Framework &amp; Ometa (Ohm)" loading="lazy"></p>
<p>addOperationCalc source code:</p>
<pre><code>function addOperationCalc()
{   
 
    var constants = {pi: Math.PI, e: Math.E};
    var s = _LangManager.ohmLangs[this.id][&quot;Calc&quot;][&quot;semantics&quot;];

s.addOperation(&apos;interpret&apos;, {
      Exp: function(e) {
        return e.interpret();  
      },
      AddExp: function(e) {
        return e.interpret();
      },
      AddExp_plus: function(x, _, y) {
        return x.interpret() + y.interpret();
      },
      AddExp_minus: function(x, _, y) {
        return x.interpret() - y.interpret();
      },
      MulExp:        function(e)       { return e.interpret(); },
      MulExp_times:  function(x, _, y) { return x.interpret() * y.interpret(); },
      MulExp_divide: function(x, _, y) { return x.interpret() / y.interpret(); },
      ExpExp:        function(e)       { return e.interpret(); },
      ExpExp_power:  function(x, _, y) { return Math.pow(x.interpret(), y.interpret()); },
      PriExp:        function(e)       { return e.interpret(); },
      PriExp_paren:  function(_, e, _) { return e.interpret(); },
      PriExp_pos:    function(_, e)    { return e.interpret(); },
      PriExp_neg:    function(_, e)    { return -e.interpret(); },
      ident: function(_, _) {
        return constants[this.interval.contents] || 0;
      },
      number: function(_) {
        return parseFloat(this.interval.contents);
      }
    });
}

</code></pre>
<p><strong>5.</strong> Next, we need to add the function call to addOperationCalc() from initGrammarCalc() and call it. After adding, press <strong>Call Method</strong> button.</p>
<pre><code>function initGrammarCalc()
{
    //console.log(&apos;Init grammar: Calc&apos;);
    this.addOperationCalc();
}
</code></pre>
<p><strong>6.</strong> Now, we are ready to test our grammar and it semantic&apos;s operation &apos;interpret()&apos;. Create the new method with following source code and press <strong>Call Method</strong> button.</p>
<pre><code>function test()
{
    var str = &apos;(5+7)*4&apos;;
    var gram = _LangManager.ohmLangs[this.id][&quot;Calc&quot;][&quot;grammar&quot;];
    var sem = _LangManager.ohmLangs[this.id][&quot;Calc&quot;][&quot;semantics&quot;];
    var r = gram.match(str);
    var n = sem(r);
    this.text = n.interpret();
}
</code></pre>
<p>If everything is ok, you should see the string expression evaluation in 3d Text entity.<br>
<img src="http://blog.krestianstvo.org/en/content/images/2015/11/testcalculator.jpg" alt="Virtual World Framework &amp; Ometa (Ohm)" loading="lazy"></p>
<p>If something is not working in provided steps, please look at working tutorial <a href="http://live.net.ru/adl/sandbox/world/WRpbHEuHfYGmUm54">here</a></p>
<p>Thanks for reading!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>