Skip to content

Paying a Visit to Old Friends

Neofox: floof_mug MMMH, REAL CODE

This RUNS! Playful premises aside, this is a functioning showcase of fennecs principles.

Get comfy, grab a cup of Java CoffeeScript Visual J# whatever, and get your paws dirty playing around in the code! It's good fun!

All .csproj and .cs files are over here on Github!

Premise

To settle an old score, we need to get even with five former friends Entities... we need to find those that wronged us, and wrong them right back in their face.

We create the Entities and define the Relation (struct Betrayed) they have with us, and also ours (struct Grudge) with them. We include a plain Component (struct Location) as useful data to everyone involved.

Next, we query for the Relation, say hello, and unalive interact with the Entities in a Query.For. This removes our Grudge for them.

Recipe

cs
// KillBill.cs (type declarations at bottom of file)

using fennecs;

if (!Console.IsOutputRedirected) Console.Clear();
Console.WriteLine("Directed by: Trentin Quarantino");

// The world is a stage. 
var world = new World();

// This is us. Here and now.
var us = world.Spawn().Add<Location>("here");

// Ok, let's maybe not spend 4 years in a coma!
// Thread.Sleep(TimeSpan.FromDays(365 * 4));

// They were five. This is how it went:
for (var i = 0; i < 5; i++)
{
    var them = world.Spawn()
        .Add<Location>("wedding chapel")
        .AddRelation<Betrayed>(us);

    // And just in case, we will never forget.
    us.AddRelation<Grudge>(them);
}

// We query for their Locations; to pay them a visit;
// and their Entity Id. It's a surprise tool that will help us later!
var betrayingVipers = world.Query<Location, Identity>()
    .Has<Betrayed>(us)
    .Compile();

Console.WriteLine($"As we said, there were {betrayingVipers.Count} of them.");

// They went into hiding around the world.
betrayingVipers.For((ref Location location) =>
{
    location = $"hideout 0x{Random.Shared.Next():x8}";
    Console.WriteLine($"One hides in {location}.");
});

Console.WriteLine();
Console.WriteLine($"We are still {us.Ref<Location>()}, though.");

// Has<>(Match.Entity) is the same as saying HasRelation<>()
Console.WriteLine();
Console.WriteLine($"Do we hold grudges? {us.Has<Grudge>(Match.Entity)}.");
Console.WriteLine("This is us (and our grudges):\n" + us);

// Choose your weapon:
//    query.Despawn();
//    query.Truncate(0);
// -> visiting each entity personally
betrayingVipers.For((ref Location theirLocation, ref Identity theirIdentity) =>
{
    Console.WriteLine();
    
    ref var ourLocation = ref us.Ref<Location>();
    ourLocation = theirLocation;

    // Knock knock.
    Console.WriteLine($"Oh, hello {theirIdentity}! Remember us ({us.Id})?");
    
    // We only have an identity, so we fudge one in the world. We could also
    // use world.ListComponents(theirIdentity). (and more API coming soon)
    var they = world.GetEntity(theirIdentity);
    Console.WriteLine("They do. They remember everything. They are:\n" + they);

    // Get our revenge.
    world.Despawn(theirIdentity);

});

// Survey the aftermath.
Console.WriteLine();
Console.WriteLine($"Now, there are {betrayingVipers.Count} of them.");
Console.WriteLine($"Let's get out of {us.Ref<Location>()}.");
us.Ref<Location>() = "traveling";

// We satisfied our grudges.
Console.WriteLine($"Any more grudges? {us.Has<Grudge>(Match.Entity)}.");
Console.WriteLine("This is us now:\n" + us);
Console.WriteLine($"We'll be {us.Ref<Location>()} for a while.");


# region Components
// "tag" (size-less) component, used here to back a Relation
internal struct Grudge;


// "tag" (size-less) component, used here to back a Relation
internal struct Betrayed;


// A Location Component wrapping a string.
internal readonly struct Location(string there)
{
    public static implicit operator Location(string location) => new(location);
    public override string ToString() => there;
}
# endregion
txt
Directed by: Trentin Quarantino
As we said, there were 5 of them.
One hides in hideout 0x669d3d82.
One hides in hideout 0x679b96bc.
One hides in hideout 0x03ed09e6.
One hides in hideout 0x0d987cab.
One hides in hideout 0x751b52dd.

We are still here, though.

Do we hold grudges? True.
This is us (and our grudges):
E-00000001:00001 <fennecs.Identity>
  |-<Location>
  |-<Grudge> >> E-00000002:00001
  |-<Grudge> >> E-00000003:00001
  |-<Grudge> >> E-00000004:00001
  |-<Grudge> >> E-00000005:00001
  |-<Grudge> >> E-00000006:00001

Oh, hello E-00000002:00001! Remember us (E-00000001:00001)?
They do. They remember everything. They are:
E-00000002:00001 <fennecs.Identity>
  |-<Location>
  |-<Betrayed> >> E-00000001:00001

Oh, hello E-00000003:00001! Remember us (E-00000001:00001)?
They do. They remember everything. They are:
E-00000003:00001 <fennecs.Identity>
  |-<Location>
  |-<Betrayed> >> E-00000001:00001

Oh, hello E-00000004:00001! Remember us (E-00000001:00001)?
They do. They remember everything. They are:
E-00000004:00001 <fennecs.Identity>
  |-<Location>
  |-<Betrayed> >> E-00000001:00001

Oh, hello E-00000005:00001! Remember us (E-00000001:00001)?
They do. They remember everything. They are:
E-00000005:00001 <fennecs.Identity>
  |-<Location>
  |-<Betrayed> >> E-00000001:00001

Oh, hello E-00000006:00001! Remember us (E-00000001:00001)?
They do. They remember everything. They are:
E-00000006:00001 <fennecs.Identity>
  |-<Location>
  |-<Betrayed> >> E-00000001:00001

Now, there are 0 of them.
Let's get out of hideout 0x751b52dd.
Any more grudges? False.
This is us now:
E-00000001:00001 <fennecs.Identity>
  |-<Location>
We'll be traveling for a while.

fennecs is released under the MIT License. Neofox is released under the CC BY-NC-SA 4.0 License.