6 Feb, 2018

User dashboards

This is a small mod I made for the Mysidia PHP framework. It allows you to log various events in game - pet adoptions, breedings, item usage, purchases or sales, anything really - and list them on a page for user to track their recent activity. Screenshot:

1. Database

Log into phpMyAdmin, go to Operations tab and create a new table called adopts_usernoti with 5 columns.
messageid - INT - 15
userid - INT - 11
date - VARCHAR - 50
mtype - VARCHAR - 20
mtext - VARCHAR - 500
Then go to the Structure tab, set messageid as the primary key, and check the auto_increment box.
Done!

2. Generate messages

It's your choice exactly what actions and events should be tracked. Some suggestions:

- adoptions, pounding, births, deaths
- buying, selling, crafting or using items
- whenever your trade offer is created, deleted or accepted (by you or someone else)
- when you send or receive a friend request, and if you/they accept or refuse it
- when you use a promo code
- when someone leaves a visitor message on your profile
- if you have an explore system, you could list each day's rewards, or which places you visited
- if you have a battle or contest system, list your pets' results

For events involving two users, simply generate two messages, one for each side; "You purchased ITEM from USER, for COST currency" versus "USER purchased ITEM from you, you got COST currency".

I haven't looked around all the scripts yet, but here are some example cases to start with...

adopt.php

Find the last big chunk of code where new adopt's info is added to table. Something like
$mysidia->db->insert("owned_adoptables", array("aid" => NULL, "type" = .....
Under that, add message, using any variables you want. Gender, type, colour... you can check them in the big Insert query above.
// get the current time, and create the message text

$thetime = date("jS M, H:i");

$message = '<b>'.$thetime.'</b> - You adopted one '.$adopt->getType().' egg, nicknamed <a href=\'myadopts/manage/'.$aid.'\'><b>'.$name.'</b></a>.';

// add the notification to table

$mysidia->db->insert("usernoti", array("messageid" => NULL, "userid" => $mysidia->user->uid, "date" => $thetime, "mtype" => 'pets', "mtext" => $message ));
If you want to include a link to the new adopt (its manage page for example) you must add that message code a little further down - under this line that sets the aid variable:
$aid = $mysidia->db->select("owned_adoptables", array("aid"), "code='{$code}' and owner='{$mysidia->user->username}'")->fetchColumn();

class_breeding.php

Somewhere inside the public function breed, add this to get the parents' names:
$mothername = $this->female->getName();
$fathername = $this->male->getName();
And again find the last big chunk of code, where baby adopt is added to owned_adoptables, and underneath it create the user notification:
$thetime = date("jS M, H:i");

$message = '<b>'.$thetime.'</b> - <a href=\'myadopts/manage/'.$this->female->getAdoptID().'\'><b>'.$mothername. '</b></a> laid an egg, nicknamed <b>' .$name.'</b>, sired by <a href=\'myadopts/manage/'.$this->male->getAdoptID().'\'><b>'.$fathername.'</b></a>.';

$mysidia->db->insert("usernoti", array("messageid" => NULL, "userid" => $mysidia->user->uid, "date" => $thetime, "mtype" => 'pets', "mtext" => $message ));
Again if you want to link to the new baby, look up its aid using the generated code.

class_pound.php

Down near the bottom, find the two public functions dopound and doadopt. Add these notifications at the ends, before the closing brackets.
$name = $mysidia->db->select("owned_adoptables", array("name"), "aid ='{$this->aid}'")->fetchColumn();

$thetime = date("jS M, H:i");

$message = '<b>'.$thetime.'</b> - You abandoned <b>' . $name . '</b>... hopefully a new owner will come along soon.';

$mysidia->db->insert("usernoti", array("messageid" => NULL, "userid" => $mysidia->user->uid, "date" => $thetime, "mtype" => 'pets', "mtext" => $message ));
$name = $mysidia->db->select("owned_adoptables", array("name"), "aid ='{$this->aid}'")->fetchColumn();

$thetime = date("jS M, H:i");

$message = '<b>'.$thetime.'</b> - You rescued <a href=\'myadopts/manage/'.$this->aid.'\'><b>'.$name.'</b></a> from abandonment.';

$mysidia->db->insert("usernoti", array("messageid" => NULL, "userid" => $mysidia->user->uid, "date" => $thetime, "mtype" => 'pets', "mtext" => $message ));

functions_items.php

You can make the notification different for every kind of item, if you want. A wearable-type might be tracked as "You gave your pet Bob a new ITEM to wear" while food would be "You fed your pet Annie one ITEM." Anyway, add the message in every item function.
function items_breed1($item, $adopt){

$mysidia = Registry::get("mysidia");

// Update the lastbred info.

$mysidia->db->update("owned_adoptables", array("lastbred" => 0), "aid ='{$adopt->aid}' and owner='{$item->owner}'");

$note = "Your griffin was momentarily dizzied by a strange magic aura, but now feels refreshed. They can breed again!<br><a href='/inventory'>Back to Inventory</a>";

// Create message and store it.

$thetime = date("jS M, H:i");

$message = '<b>' . $thetime . '</b> - You used the item ' . $item->itemname . ' on your griffin <a href=\'myadopts/manage/' .$adopt->aid. '\'><b>' .$adopt->name. '</b></a>.';

$mysidia->db->insert("usernoti", array("messageid" => NULL, "userid" => $mysidia->user->uid, "date" => $thetime, "mtype" => 'item', "mtext" => $message ));

// Done.
// Update item quantity.

$delitem = $item->remove(1, $item->owner);

return $note;
}

class_itemshop.php

This is for when users buy items. Scroll down to the purchase function.
public function purchase(Item $item){

$mysidia = Registry::get("mysidia");
if($item->owner != $mysidia->user->username) Throw new NoPermissionException('Something is very very wrong, please contact an admin asap.');

else{

$item->quantity = $mysidia->input->post("quantity");
$cost = $item->getcost($this->salestax, $item->quantity);
$moneyleft = $mysidia->user->money - $cost;
if($moneyleft >= 0 and $item->quantity > 0){
$purchase = $item->append($item->quantity, $item->owner);
$mysidia->db->update("users", array("money" => $moneyleft), "username = '{$item->owner}'");

// adding notification for user.

$thetime = date("jS M, H:i");

$message = '<b>'.$thetime.'</b> - You purchased ' .$item->quantity. ' x ' . $item->itemname . ' at a cost of ' .$cost. ' currency.';

$mysidia->db->insert("usernoti", array("messageid" => NULL, "userid" => $mysidia->user->uid, "date" => $thetime, "mtype" => 'shop', "mtext" => $message ));

// done.

$status = TRUE;
}
else throw new InvalidActionException($mysidia->lang->money);
}
return $status;
}
It would be nice to include the name of the shop being purchased from (or the NPC who runs it, if you have a story-based game), but I'm not sure if that's possible.

3. Display messages

Make a new page to hold the dashboard, and some HTML divs where different notification types will be displayed.
If you're feeling lazy, just copy this.

activity.php

<?php
class ActivityController extends AppController{

public function index(){
$mysidia = Registry::get("mysidia");
}

}
?>

activityview.php

<?php
class ActivityView extends View{

public function index(){
$mysidia = Registry::get("mysidia");
$document = $this->document;
$document->setTitle("Activity");
$document->add(new Comment("Here's a log of recent activity regarding your game.</p>

<h2>Pet news</h2>
<div style='width:700px;padding:15px;border:1px solid blue;background-color:white;text-align:left;max-height:200px;overflow:auto;'>"));

$petsn = $mysidia->db->select("usernoti", array("mtext"), "userid='{$mysidia->user->uid}' and mtype='pets' ORDER BY messageid DESC LIMIT 20");

while($petsmsg = $petsn->fetchColumn()){
$n_order++;
$document->add(new Comment("<br> {$petsmsg}"));
}

$document->add(new Comment(" </div><br><br>

<h2>Item usage</h2>
<div style='width:700px;padding:15px;border:1px olid blue;background-color:white;text-align:left;max-height:200px;overflow:auto;'>"));

$itemn = $mysidia->db->select("usernoti", array("mtext"), "userid='{$mysidia->user->uid}' and mtype='item' ORDER BY messageid DESC LIMIT 20");

while($itemmsg = $itemn->fetchColumn()){
$n_order++;
$document->add(new Comment("<br> {$itemmsg}"));
}

$document->add(new Comment(" </div><br><br>

<h2>Item purchases</h2>
<div style='width:700px;padding:15px;border:1px solid blue;background-color:white;text-align:left;max-height:200px;overflow:auto;'>"));

$shopn = $mysidia->db->select("usernoti", array("mtext"), "userid='{$mysidia->user->uid}' and mtype='shop' ORDER BY messageid DESC LIMIT 20");

while($shopmsg = $shopn->fetchColumn()){
$n_order++;
$document->add(new Comment("<br> {$shopmsg}"));
}

$document->add(new Comment(" </div><br>"));
}
}
?>
... you'll want to style the divs to match your site, and add more for different messages.
Anyway, this is the important bit of code, highlighted below. Fetch the user's last 20 messages of "item" mtype:
$itemn = $mysidia->db->select("usernoti", array("mtext"), "userid='{$mysidia->user->uid}' and mtype='item' ORDER BY messageid DESC LIMIT 20");

while($itemmsg = $itemn->fetchColumn()){
$n_order++;
$document->add(new Comment("<br> {$itemmsg}"));
}
Change $itemn, $itemmsg and mtype='item' to the other mtypes - "pets", "shop", "trade" or so on. And repeat this bit of code inside all of your divs.

Possible improvements

- At the moment, date is stored in the table but I couldn't figure out how to fetch it and display it with the message text... so I just added it inside the text too, heh.
Therefore the date column isn't being used at all. It would be cool to be able to fetch messages by date - for example show all from the last 3 days, none older. Instead of fetching a fixed number regardless of their date.

- Getting specific shop names when buying. Not sure if this is actually possible?

- Notifying when an adopt gains a level. Obviously this can be done with the levelup items, but what about when others click on them (levelup/click)? I'm not using this on my site, so you'll have to find the exact script place to add your message.