All Posts

mpc.exe outputs an empty Resolver

In order to use MessagePack on the iOS or in general with AOT, you need to use mpc.exe to generate a resolver before building your main projects. Since Xamarin and ASP.NET are all about code sharing, usually a good practice is to create a shared project or a library containing model definitions, and referencing it in both server and client projects.

This raises the question as where to embed the script to run mpc.exe in order to facilitate the automatic generation and updating the resolver class.

One problem is that mpc.exe does not work with Shared Projects (.shproj), and as of now only accepts .csproj files as the input. So one thing to do is to create a stub/dummy project containing only the model classes, and feeding it to mpc.exe.

The frustration comes when mpc.exe doesn’t like an input. In such cases, it merely generates a blank useless resolver class (e.g. MessagePackGenerated.cs) without giving any errors. You have to manually investigate everything in order to find out what goes wrong.

One of the main cases in which I realized that mpc.exe doesn’t work properly, is when you don’t have the correct version of MessagePack NuGet installed on the stub project. Make sure you install MessagePack in that project.

Resetting Windows 10 bash user password

If you have forgotten your bash user password on Windows 10, there is a way to log in as root to reset that user’s password using passwd.

First, make sure all bash windows are closed. This is important as if one bash instance is open, this may not work:

Open a Command Prompt as Administrator. You can do that by typing cmd in the Start menu and pressing CTRL+Shift+Enter. Run: ubuntu config --default-user root The previous command tells bash to log in as root the next time it’s started. So you can now run a rooted bash by typing bash. Now you can reset any user’s password by entering passwd myuser Finally, exit bash, and in the elevated Command Prompt, type ubuntu config --default-user myuser to change the default bash login to your bash user.

Solving "Native linking failed" issues running Xamarin.iOS on Simulator

Some external libraries will cause the project fail to build on the iPhoneSimulator (e.g. x86_64) target. The resulting errors can be:

Native linking failed. Please review the build log.
Native linking error: 1 duplicate symbol for architecture x86_64
Duplicate symbol in: /Users/admin/Library/Caches/Xamarin/mtbs/builds/.../obj/iPhoneSimulator/Debug/mtouch-cache/x86_64/main.o (Location related to previous error)
Duplicate symbol in: /Users/admin/Library/Caches/Xamarin/mtbs/builds/.../obj/iPhoneSimulator/Debug/mtouch-cache/leveldb-library(leveldb_main.o) (Location related to previous error)
Native linking failed, duplicate symbol: '_main'.

Sometimes you can make the build work by adding --registrar:static in the Additional mtouch arguments (MtouchExtraArgs) setting of the iOS project properties.

Solve "The "User7ZipPath" parameter is not supported"

This can happen when building a Xamarin project while using certain libraries. What can help is:

  1. Update or install the latest version of Xamarin.Build.Download NuGet.
  2. Close all Visual Studio windows.
  3. Delete all the obj, bin, .vs folders, as well as the local packages folder in your solution root.
  4. Delete the global NuGet cache from ~\.nuget
  5. Load the Solution again, Rebuild, and hopefully the problem will go away!

EF / SQL Server writes too slow?

I was using Entity Framework Core on a project which required a large amount of writes (inserts and updates) to a SQL Server 2017 database. The operation was extremely slow, in the order of several hours/half a day. I figured out that it was due to the EF overhead for tracking changes. Setting the following boolean to false saves a lot of time, if you have to do a lot of writes:

using (var db = new MyContext())
{
db.ChangeTracker.AutoDetectChangesEnabled = false;
//Do Stuff
db.ChangeTracker.AutoDetectChangesEnabled = true;
}

Xamarin.Android Rounded Corners Masked Layout

If you want to create a FrameLayout that has real rounded corners and clips its children beyond its corners, you can use the following class, which is a port of an answer on StackOverflow. You should replace Constants.PackageName with your Android package name, e.g. com.mycompany.myapp.

using Android.Content;
using Android.Graphics;
using Android.Runtime;
using Android.Util;
using Android.Widget;

namespace UIWidgets.Android
{
    [Register(Constants.PackageName + ".UIWidgets.Android.RoundedCornerLayout")]
    public class RoundedCornerLayout : FrameLayout
    {
        const float CornerRadius = 20.0f;

        Bitmap maskBitmap;
        Paint paint, maskPaint;
        float cornerRadius;

        public RoundedCornerLayout(Context context) : base(context)
        {
            Init(context);
        }

        public RoundedCornerLayout(Context context, IAttributeSet attrs) : base(context, attrs)
        {
            Init(context, attrs);
        }

        public RoundedCornerLayout(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
        {
            Init(context, attrs, defStyle);
        }

        void Init(Context context, IAttributeSet attrs = null, int defStyle = 0)
        {
            DisplayMetrics metrics = Context.Resources.DisplayMetrics;
            cornerRadius = TypedValue.ApplyDimension(ComplexUnitType.Dip, CornerRadius, metrics);
            paint = new Paint(PaintFlags.AntiAlias);
            maskPaint = new Paint(PaintFlags.AntiAlias | PaintFlags.FilterBitmap);
            maskPaint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Clear));
            SetWillNotDraw(false);
        }

        public override void Draw(Canvas canvas)
        {
            Bitmap offscreenBitmap = Bitmap.CreateBitmap(canvas.Width, canvas.Height, Bitmap.Config.Argb8888);
            Canvas offscreenCanvas = new Canvas(offscreenBitmap);

            base.Draw(offscreenCanvas);

            maskBitmap = maskBitmap ?? CreateMask(canvas.Width, canvas.Height);
            offscreenCanvas.DrawBitmap(maskBitmap, 0.0f, 0.0f, maskPaint);
            canvas.DrawBitmap(offscreenBitmap, 0.0f, 0.0f, paint);
        }

        Bitmap CreateMask(int width, int height)
        {
            Bitmap mask = Bitmap.CreateBitmap(width, height, Bitmap.Config.Alpha8);
            Canvas canvas = new Canvas(mask);

            Paint paint = new Paint(PaintFlags.AntiAlias);
            paint.Color = Color.White;

            canvas.DrawRect(0, 0, width, height, paint);

            paint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Clear));
            canvas.DrawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);

            return mask;
        }
    }
}

And to use it in your AXML:

 <UIWidgets.Android.RoundedCornerLayout
    android:layout_width="150dp"
    android:layout_height="150dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFDDAA"
    />
    
 </UIWidgets.Android.RoundedCornerLayout>

REST requests with Xamarin and RestSharp

RestSharp (available on NuGet) is a clean way to send HTTP requests and handle their response. As a portable package, you can use it in your Xamarin.iOS and Xamarin.Android applications. The following example, POSTs a serialized JSON body, created automatically from a C# class, to an endpoint located at https://myserver.com/api/messages/message. It also sends a token parameter inside the query string:

public class MessageDTO : DTO
{
    public string Sender { get; set; }
    public string Recipient { get; set; }
    public string Body { get; set; }
}
public static class PinHelper
{
    async void SendMessage(MessageDTO dto)
    {
        const string ApiPath = "https://myserver.com/api/";
        var client = new RestClient (ApiPath);
        var request = new RestRequest ("messages/message", Method.POST);
        request.AddQueryParameter ("token", Settings.Token);
        request.AddJsonBody (dto);

        try
        {
            var result = await client.ExecuteTaskAsync(request);
            Debug.WriteLine($"Result Status Code: {result.StatusCode} - {result.Content}");
        }
        catch (Exception e) {
            Debug.WriteLine ($"Error: {e.Message}");
        }
    }
}

On an ASP.NET WebApi controller with EntityFramework, this request can be received and stored using a function that looks like this:

[HttpPost][Route("message")]
public IHTTPActionResult AddMessage(string token, [FromBody] MessageDTO dto)
{
    Message message = new Message ();
    dto.Inject (message);
    db.Messages.Add (message);
    db.SaveChanges ();

    return Ok ();
}

Tips and Tricks on Using SQLite-Net with Xamarin.iOS

SQLite-Net is a nice library compatible with Xamarin that lets you create and use a SQLite database as the local data source of your application. It is ultra portable as it comes in only two C# files, one of which is for asynchronous operations. You can easily get it from NuGet and get started with it.

Creating a database (if not exists)

The first step in using SQLite-Net is creating a database, and its tables. This is automatically done by creating a SQLiteAsyncConnection and calling its CreateTableAsync<T> method, in which T is your model class. This method checks for the existence of a table with the same name as the model class, and creates it if it does not exist. For example, if we want to make a database named map.db containing a table based on the model class Pin, we can do the following:

var path = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), "map.db");
var connection = new SQLiteAsyncConnection(PATH, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex, true);
await connection.CreateTableAsync<Pin>();

You can keep the connection variable in case you’d like to use the database in the future, but be careful from which thread you access it. Many of the issues with SQLite-net come from accessing the database from a wrong thread, and the error messages usually give no hint regarding this.

Model classes

SQLite-Net takes care of serializing and deserializing data between queries and .NET objects. A model class can look like this:

using System;
using SQLite;
namespace Mapp.Models
{    
    public class Pin
{
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public int ServerId { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }
}

In this example, the Id field is an auto-incremented primary key for table Pin.

Injecting DTO values into a model object

You can use the neat reflection features of .NET to automatically inject values from a Data Transfer Object (DTO) that is a subset of your model fields. Here is a helper method that does this for you:

using System.Linq;
using System.Reflection;
namespace Mapp
{
    public class DTO
    {
        public void Inject(object destination)
        {
            var destFields = destination.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            var myFields = this.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (var item in myFields)
            {
                var matchingFields = from x in destFields where x.Name == item.Name select x;
                if (matchingFields.Count() == 0) continue;
                matchingFields.First().SetValue(destination, item.GetValue(this));
            }
        }
    }
}

For example if you have the following DTO, you can inject its values into a Pin object using the Inject method:

public class PinDTO : DTO
{
    public int ServerId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}


Pin pin = new Pin();
pinDto.Inject(pin);

Querying, inserting and updating records

You can use LINQ syntax to query the database and get a list of objects of the type of your model class. For example to find a pin with a certain ServerId and update it (or create it if it does not exist) you can write:

var query = connection.Table<Pin>().Where(x => x.Id == dto.ServerId).ToListAsync().Result;
var pin = Query.Count > 0 ? query[0] : new Pin { ServerId = dto.ServerId };
dto.Inject(pin);

if (pin.Id > 0)
{
    // Record exists. Update it.
    await connection.UpdateAsync(pin);
}
else
{
    // Record does not exist. Create it.
    await connection.InsertAsync(pin);
}

Again, you have to be careful from which thread you are accessing the database. To delete a record you can use the DeleteAsync method:

await connection.DeleteAsync(pin);

Batch resizing images with Python and Pillow

Pillow is a fork of PIL (Python Imaging Library) which works on Python 3. It provides convenient methods to manipulate and convert image files with just a few lines of code. Usually every mobile application platform requires the same image to be provided in multiple sizes, and since resizing these images manually can be cumbersome, Pillow and Python can come to save the day by automating these processes.

from PIL import Image
 
inputName = "image.png"
sizes = (512, 256, 128, 64, 32)
 
img = Image.open(inputName)
for size in sizes:
    name = "{}-{}.png".format(inputName, size)
    resizedImage = img.resize((size, size), Image.ANTIALIAS)
    resizedImage.save(name)

To install Pillow using pip, you can simply execute:

pip install Pillow

Traces of Love Random Development Notes

Traces of Love Random Development Notes

Last week we released a new Neat Games title: Traces of Love, with a romantic theme aimed for Valentine’s day. This was a remake of BLAMMO: Trace of Love that we published in 2013, with new levels, new gameplay mechanics, and of course, a different game engine. You can download Traces of Love from the App Store, or if you have an Android device, from the Play Store. A version with limited features is also available on the Windows Store, if you prefer to try that one.

With Traces of Love, we decided to depart from Cocos2d-x and use Unity instead as the engine for our games. Dropped performance and larger package sizes are obvious outcomes of this decision, but as Unity opens up interesting opportunities for artistic touches that are not feasible to do with a small team with a low level framework such as Cocos2d-x, it appears to be a logical choice for this type of games.

This difference is very obvious when comparing Traces of Love with its predecessor BLAMMO: Trace of Love. First, Unity gave us access to a very powerful visual canvas, which helped us make more levels with higher complexity and better looks. Second, it made it much easier for artists and level designers to do their own thing without having to bother with the code. Finally, it was much easier to target multiple platforms, and also to integrate third-party libraries. An important time saving difference between using Cocos2d-x and Unity is that in Unity, it is very easy to design and test different behaviors for each individual object, thanks to its component-based nature. This opens up ways for developers to be able to go crazy with each object without having to deal with creating a new class for each differently-behaviored object and so on.

However, performance drop and overheating were the two most discouraging issues in our experience. I am personally curious to see how other high-level engines such as Unreal perform compared to Unity when it comes to a game with similar features.

The overheating problem is more sensible on Android, especially when fullscreen shader effects are used in the scene. And by this, I mean those built-in “optimized” ones that come with Unity’s Standard Assets package. This can be really dangerous for the game because it may lead to numerous negative feedbacks from users who complain about the heating issue. Traces of Love heavily relies on the fisheye distortion filter for creating a romantic look, therefore it makes the Android device heat up really fast.

Unity Asset Store is a huge time saver when it comes to indie game development. We used out of the box asset bundles for Facebook SDK, Parse SDK and Facebook Audience Network ads. A major part of Traces of Love are the walls. Walls and lines were drawn using the free Line2DRenderer asset by Anthony Beyer. Line2DRenderer provides different thickness settings for each end of a line segment, allowing lines to have a more artistic look by being uneven. It also provides different color settings for each point of the line. Although we had to put many additional logics on top of it, we found Line2DRenderer a perfect choice for the base library for making our walls. Line segment intersection code was ported from the Cocos2d-x version of our codebase, which is available on Github.

For advertisements, first we integrated Google Ads, but at some point we realized the Google Ads plugin interferes with the Facebook SDK plugin, causing it to crash on initialization on Android. So we got rid of Google Ads and used Facebook Audience Network instead. It is too soon to judge, but I think the revenues from Google Ads would have been higher. Also to be able to use Audience Network, the app needs to get approved. This was not a big deal as we just sent some screenshots and they approved the request in a few days. Also since implementing Facebook interstitial ads is very similar to Google interstitial ads, we did not suffer any time migrating from Admob to Audience Network.

Finally, Parse was used for the backend of the game. Scores are sent to the Parse server, and a cloud code (written in JS) returns the ranking of the current user for each level. This was very simple and elegant, as Parse handles all of the dirty stuff. We just gave a write-only access to the users and all reading can only be done on the server using cloud code. Sadly, Parse will be discontinued next year, and we will need to install our own Parse server for this purpose.

You can download Traces of Love for free on the App Store, Google Play and Windows Store right now. Enjoy the puzzles!