It has been a while since I have posted anything, and to be honest, I shouldn’t be posting anything, since I’ve got loads of other things to worry about..! But oh well, I have searched the Internets high and wide for tids and bits about packaging ReactNative as an iOS framework, and couldn’t find anything useful…
So, here I am saying that it is indeed possible.
I don’t have the luxury to post a whole tutorial with pics and kitten gifs about the topic, but just enough time to brag- ehm, I mean share some of the details of how it’s possible.
To those of you who catch up quickly, and are just here for reassurance:
Simply, create a Framework target in the generated Xcode project, and make the settings and code identical to the app target already created by RN. Done.
For the rest of us, please follow along as I try to recall all the steps required to perform such a feat.
So, for the purpose of this post, you might wanna give it a shot on the side, and not directly apply the changes to your main project .. Just in case the Xcode project catches fire or something…
react-native init PackagingReact in terminal should give you a nice, clean RN project to experiment with. I’m using the following versions of RN:
Simply, open the Xcode project residing in the newly created project, and observe in Xcode, under the targets panel, there should be an Application target
PackagingReact, and some other stuff like testing and what not.
We simply need to do
Target..., and choose
dynamic Framework. I have tried for a few minutes to make it work for
static library target, but that was horrible since we need to bundle some resources and other dependencies…
With the Framework target created, you can select it now under the targets panel where the application target was, and start replicating the settings from the application target onto the Framework target. As far as I recall, I had to do the following:
- Link the 11 static libraries
other linker flags: -ObjC -lc++
- Replicate the custom
Run scriptphase to the Framework target
react-native bundle ...command to generate
main.jsbundleto the framework target
That’s about it, folks. Once that was done, I simply copied over the ObjC code from the application target, to a new class in the Framework, modified that code a bit to load the
main.jsbundle instead of searching for the packager, and voala. Works like a charm.
I am now gonna test to see if I can make the framework target Swift based (no reason it can’t be). After that, I would like to automate this process, so it becomes a single click deployment of the RN application to an iOS framework (which we can possibly link using Carthage even).
Unity ads is a great opportunity for games to make some serious revenue from the free players segment. These players would never pay a single dime, so making them watch a video ad results in revenue for your game.
The Unity platform is insanely good with video ads. Basically, you click a few buttons in unity, add
Advertisement.Show();, and your done.
This is all nice and dandy until you realize that you need to now reward the user for watching the ad. The ad runs on the client, so it might be compromised .. Unity solves this problem as well by providing Server-to-Server callbacks.
So, basically, once a user watches an ad, Unity servers send a callback to your server with the user id that confirms that action. You can then be sure that the user can be awarded the promised reward without worrying about it being compromised.
The only issue here is that implementing backend callbacks is a chore, and I don’t think enough players will bother hacking the app. On the other hand, adding the reward system within the client is just too risky …
While throwing my thoughts here it occurred to me that I can implement the server callbacks not mainly to prevent hacking, but mainly to make the implementation easier. With the callback sent to my server, I can simply update the profile, and push that update to the client.
Well, I did need to write about the current authentication design, not that I think it’s amazing or anything like that, but in fact, I need to write it out in order to properly think about it.
So, what’s the deal with the authentication flow?
So, I decided to go with a pretty “novel” approach for authentication, and that is to redirect the user to a website that (s)he can then authenticate through, which “upgrades” the associated account…
So, everytime a user installs the app, a new “guest” account is created, and a device token is associated with that account. The device token, as the name suggests, is a unique auth token for that device, which provides access to the account without the need to enter the username/password everytime. Pretty basic stuff..
Now, once the user logs in on the web portal, as I call it, the device needs to “know” about this authentication process, and change the initial guest account to the new logged in account.
My approach to this problem was to send the guest auth token with url redirect. I am not worried about the security of this token, since it is always a token of the guest account, which isn’t significant.
So, once the user is on the login portal with that token, we can fetch the guest account and prepare for the upgrade process. If the auth process succeeds, there will be a new account we want to “migrate” to…
I am thinking of simply migrating the device token to that account, and once the user is back in the game, we detect the token and that it has been migrated, and send an updated token of the new account, which is then securely stored on the device for further operations.
Everytime I think about it or try to find issues with this approach, I don’t see anything wrong, but also every “new” design you come up with in programming will always make you anxious since if this is so great, why isn’t everyone using it?
Well, I don’t have time to care about that, I need to get done with this…
Holy crap, I completely forgot about this devlog
>__< .. definitely should not have…
I don’t remember what the last post was about, but since then, just too many things were worthy of at least dumping here .. Learning new optimization tricks in python thanks to the interview process preparations, Swift 3 changes, Phoenix controllers and HTML forms, and of course, the ordeal with ecto.
Well, I don’t feel like writing anymore for now, but should revisit this once something comes up.
That was painful … Dealing with Ecto changesets.
The thing is, I’ve been trying to implement a way to use changesets in order to protect certain properties of the model from being modified by an external source. For example, users of the app can change their username, but not their rating.
To achieve something like that, I first created
external_changeset on the
Given the user, and the proposed parameters to be changed, we should return a changeset with the following conditions:
- The changes shouldn’t modify protected members
- The changes shouldn’t render the model in an invalid state (e.g. empty username)
Well, I thought it was simple at first, because I’ve seen the
cast method in action.
cast is a method on
Ecto.Changeset that allows you to control the changes in a certain way…
The thing is, I’ve always thought that the rules you pass into the
cast method are applied to the
Ecto.Changeset model itself, but no! The rules are actually applied to the final resulting model! What does that mean?
Well, first, let’s see what the
cast method does:
Depending on whether you are on the latest ecto release or not, cast takes the model or changeset as the first parameter, then the changes as a map, then an enumerable of fields that are required or can be modified.
That’s where my earlier statement comes into play. Notice how even though we “require” an email field, the changes map doesn’t have an email. That’s fine, because if the user object itself has the email set, that means the overall changeset is still valid!
Phew! I needed to write all that out, since I am sure my future self will need it.
Not a very friendly title, but I really need to throw out there what’s happening these days. It’s too valuable to be lost in translation or in a long term memory archives…
For starters, I finally realized that toon shaders don’t cut it no more.. They are way too complicated for flat design! Besides, the whole idea behind toon shaders is to emphasize the edges and clean the surface of an otherwise rough texture.
So, while looking around the Unity project, I deleted the folder containing the toon shaders by mistake, and decide the heck with it. Let me find a better way to do dis.
Finally, I realize that the “Mobile” category in Unity shaders isn’t for low quality shaders. In fact they are high quality, just optimized for mobile by limiting certain functionality. Over there I found VertexLit shader and Unlit.
Skipping VertexLit, Unlit was all I needed, really. Using the Unlit shader meant that the model texture will be draws AS IS, without any modification whatsoever by lighting, reflection or shadows in the render scene. For my flat game, this is a godsend.
After applying that shader and seeing how great the game started to look, I also decided to do a quick pass over the textures that were added to the game. Changing those as well helped me achieve the absolute perfect look I was aiming for! Yatta! Well.. one nuisance is that the 3D models themselves still look a bit off, but whatever.
The other thing which tempted me to write this post was the discovery of the
global namespace in csharp, lol. I was having issues using a global class because I had defined the same name in a local scope… MonoDevelop was an absolute hero by suggesting that there is conflict with
global::ClassName. Nice!! So, in order to use the global name, just add
global::, and we are good to go..
That wraps it up for now, I need to go back to work! :D
Even though I set the title as “Anonymous Socket”, I decided not to go that route after all…
Here is a quick brief of what’s going on inside my head:
I need anonymous clients to connect to the backend and generate a temporary guest account to use in case the user doesn’t want to create an account. In order to create the guest account, I have implemented a simple REST API.
After looking at the implementation on the client side, I realized that using Phoenix channels is way simpler and easier than performing API calls, so I was thinking of creating a new socket endpoint for anonymous clients. A client would connect anonymously, and be given a grace period of 5 minutes or so to perform the actions it needs, such as registration or login.
The second idea sounded great, easy to implement, and in alignment with the rest of the backend .. SHIKASHI!
It would mean I’d have to manage anonymous states and sockets, which can quickly become vague and cumbersome. When using REST APIs, the request/response cycle is all you have to worry about. Once the response is sent back to the client, it’s over.
With that in mind, I figured in the future I’ll have a separate “authoritative” server that would deal with these anonymous pricks and issue secure tokens for them to access the game servers. With that in mind, if I use a REST API, it would be easier to use Heroku or some other service and language to distribute the risk/load across many servers… I’m probably over-thinking this at this point xD
Honestly, the real reason to leave the anonymous socket behind for now is time. I keep thinking about how the anonymous socket implementation is gonna be, when I already have a working implementation of the REST API client and server. So, for the sake of time, let’s stick with the REST API.
With that being said, I really need to move on to implementing the functionality required to register/login the user. The API is implemented, but still not hooked up to the UI yet… Should be simple enough to do that.
Once that’s done, I should focus on logout, figure out how that should work, while making sure the user has the ability to recover their account… Finally, I really need to implement social login, for simplicity sake. Even Pokemon Go uses Google sign up, which means it’s the way to go.
You know, for the logout stuff, I really have no choice but to add an email field when the user chooses to upgrade their guest account. The user would already be invested, anyway, and it will be for their sake so they don’t lose their account. As for social login, the beauty is that we don’t have to worry about them losing access there.
Even more errors, and more edge cases to solve … If you are developing a game, really there is never a dull moment around here .. Every single detail is a challenge that requires careful thought and planning. The idea is that once you start executing, everything should just fall into place.
So, back to the issue at hand .. After handling the simple error dialogs part and food, now I reached the game scene, and need to handle the errors there. As highlighted previously, the game view syncs the game scene graphics through an event queue .. So, I could just create a new event for channel errors and call it a day .. But, there are many types of errors that could occur in a game.
First, there is the join error. So, the player somehow reached the game scene, but due to some circumstances, the game is no longer available, so that results in a join error. I think this is simple since I can just enqueue a join error event to the events queue, and it will be handled gracefully. This works well because I actually also have a “game ready” event in place which is only sent to the graphics part if the game has initialized successfully.
Then, there are two other errors related to rematch. Since rematch is a paid action, therefor the request may be rejected due to insufficient funds. Another issue may happen when a rematch is requested, but it goes away before that packet reaches the server.
I think that in either case I can just handle the error as a “Rematch Unavailable” event, which is already in place. That event will disable the rematch button, and show a label “rematch unavailable”.
Hopefully, this will resolve all the channel error handling, for now!
The only missing piece in the game after that is implementing a proper account flow, where users can create accounts, login with existing accounts, logout, and hopefully be able to recover accounts .. I can’t believe I’m saying this .. But once that’s implemented, it’s time for BETA TESTING!!
Forgot that on a similar note to the previous post, I was wondering how I should deal with error message localization. I can deal with the localization on the frontend or the backend. If I choose either, there are also multiple ways to approach either one… Then, there is the hybrid approach, where the backend sends all localized strings, and the client picks the right one…
Ideally, I would probably just tag the locale when opening the socket, assign that to the socket assigns map, and use that throughout the backend to return the appropriate localized string… Actually, I really should do just that.
In elixir, people seem to be using
gettext to localize stuff, but I haven’t tested it out yet, hopefully it’ll be simple to use, and would solve this issue for me.
Well, I guess that’s it then! Just attach the locale to the socket when joining.
Hmm.. here I am again just typing stuff instead of working on my game .. This is the penalty of inexperience and lack of another brain to bounce ideas off of..
Well, the issue I am facing now is dealing with backend errors on the client side. The backend gracefully handle extreme cases, such as insufficient coins and state unavailability by returning errors to the client …
Now, they are extreme cases because normally, the client app will check if the player does indeed have enough coins or not and warn them without really bothering the backend. It is only if the client data somehow gets out of sync, or if a player thinks themself smart enough to hack the game is when we reach this case.
With that being said, I realize that I don’t really need dokubetsu handling for these cases, especially not for version 1.0 .. I should just roll with simple dialogs and what now, and move on.
The only issue is that I should always handle joining errors, no matter what the reason is, because otherwise I would have a reference to a dead channel and the game state would think it is active. That won’t do at all.
So, first I should rename
OnError function to
OnJoinError, since that’s more representative of what’s going on. Then, I can handle those errors by resetting the channel somehow… Then, we can have specific error delegate methods per channel, per reply use case. You see, these errors that I am handling here aren’t random. The are specifically created and sent by the backend. So, I’ll just create delegate methods for each, and handle them as appropriate.
Whenever things click so well, my mind just wanders off in the distance on how I can leverage this perfection in different applications… I then need to pull myself back to reality and focus on finishing this crap.
Well, let’s do this and hope it works out!
Just needed a quick way to track some tasks, so here it goes…
Found a bunch of crap surrounding the dialog implementation. Most of it was easy to cleanup, however, the animation code I just can’t find it… Looking at how the dialog isn’t deactivated nor cleaned up after being hidden also made me decide to just not cache panels….
Like, I’ve specifically had this talk with the developer, telling him:
There are two hard problems in Computer Science, the first being cache invalidation.
Yet, he insisted “it’s easy to cache”. Sigh. Yeah, you just store the crap in a variable and call it done… Completely ignoring the invalidation part, amazing.
So, let’s clean that up… OK, cache nuked… Running… Works as expected in most of the pleaganels, but the dialog stuff is interesting, since the dialog simply just stays there after the animation, and a new one is instantiated if we click again, leaking the old one… So, need to resolve the dialog flow.
Hmm… cleaned up a few scripts around panel controller, and forgot what the hell I was doing… Oh, dialogs… How are they even managed?
Well, it was pretty neat, actually. There was a script that automatically searched for any tween component in panel you push, and triggers it. Once I searched the prefab for that tween component, it was simple to alter the flow and fix stuff… Still need to figure out why the dialogs aren’t being destroyed…
I finally figured out why it was so hard to read the flow of the code.. It is basically because different things were doing the same thing… I mean, imagine you have a navigation stack. You push stuff onto the stack, then pop them out … When you push things, the existing thing is gonna be hidden. Also, when you pop from the stack, and popped thing is gonna be hidden.. Now, just because they are both gonna be hidden, doesn’t mean they should lead to the same function!! The pop flow should be completely separate from the push flow.
Well, one more stupid bug, pushing more than one panel seems to stop the push animation from working
lol, indeed it was stupid… ROFL, this is just too stupid. So, while I was fixing the panel controller code, which deals with the whole navigation crap, I saw that a variable was defined like this:
I was like, no way! This is called a stack, it should be a stack!
Better… So, I go through the code and change
Pop .. and that’s it. I leave everything else the same, including calls to the
Last function. By definition, a stack puts new elements at the beginning, and I was accessing
Last … Stupid. So, just changed those to
Peek, and call it a day.
So, after spending all that time perfecting the relationship between the game logic, graphics, and view, the game started coming together. Implementing new crap is much simpler, since everything is where it belongs, and it doesn’t take time to think about where to implement it.
With that, my trello board quickly started draining down cards, thankfully, but it’s way too early to celebrate.
Speaking of celebration, I was psyched to see the game performance go through the roof after simply turning off a clipping feature in NGUI. It had something to do with Physx processing, hogging tons of resource.. So, I wanted to check if the performance gain was real, and wanted to build the game on iOS.
As I was making changes and pushing to github, the iOS build on UCB kept failing… Weird.. It usually fails for no reason from time to time, but now it failed like 3 times in a row! Something was amiss.
Well, the biggest change I made which impacted platform specific stuff was upgrading the native dama logic plugin. I’ve made changes in the library to remove dynamic memory allocation from certain parts, in order to simplify memory management a bit … which was nice, but it’s a chore to build the library and update the server, bots, and unity with the new version.
So, after spending an hour or two updating and running the new library on the servers, after updating Pyport obviously, which is the python shim wrapping the C library, I updated unity simply by replacing the old libraries with the new ones. At that point, I hastily tested the Mac build, which worked fine, so life went on.
Now, after seeing the iOS build failures pile up, I looked deeper into the logs, and yup… the dreaded iOS native lib was causing issues because of some undefined symbols. The annoying this was the Unity itself generated C++ code through IL2Cpp that was named exactly the same name as my native code, except it had a number suffix at the end, like
xyz_m12839213. This made the linker go, “Did you mean xyz_m12839213?”. I’m like, no! the suffix shouldn’t be there!
So I dig through my blog, go over git changes like 5 times to see what changed?? I did upgrade Unity to 5.4.0F2, but seriously? Even cloud build was failing, so it should be something else…
Finally, I use the best tool for inspecting libraries,
nm. Using it revealed that indeed all the “glue code” generated by SWIG, to glue the C code with CSharp was missing! Going back to the Xcode project that built the native library, it seems that yeah … I was an idiot at some point and excluded that file from the build
So, finally, I mark that file as part of the built library, build the library, and off to Unity it goes … The issue now is, I’ve built too many times within a short period of time on UCB, so it will be a while till my build will be executed … Too lazy to build it locally, so just distracting myself with this blog entry and probably going out for food… Hopefully, it will be ready after that.
Once it’s really, it would be time to download it on an iPad and hope for that sweet, sweet 60 FPS glamor
I derailed, and I derailed hard…
I was simply focused on trying to implement animation ended hooks, so whenever an animation ends, the main game loop is informed, and the next task is processed…
Somehow, during that implementation, I found a nasty part in the project, but it was working well for the most part. For some reason, I decided to rewrite it… That was such a horrible idea.
No matter what the end result is, spending 4 - 5 hours perfecting minor stuff isn’t what I should be concerned about now, and yet! In any case, I realized now that reverting might be even more painful, so I gotta get this through.
The thing I really need to think through now is how should I structure the UI code moving forward? My options are either to keep things decoupled and work through the global event system, or better yet, go back to having hard references to each part of the UI.
Even though having references couples things, but allows for much higher control and clarity, which is something I really need for this game. Hiring developers not aligned with me on this part was a huge mistake…
OK, let’s just get this “hanging” task over with, I guess…
After much struggling, procrastinating, and LoLing, I have finally set my mind to it. Previously, I have explained how I should be moving the game state within the game logic, but once I started looking at the code some more, something stood out.
The graphics part was tightly coupled with the game state. I was basically reading the game state each turn, and updating the graphics accordingly. This is great for extremely simple graphics, but it’s impossible to have proper animations and sequential graphic events this way …
To give you an example, imagine how we can implement a “game turn indicator” widget. The widget is a simple arrow that points at either the white or black team, based on the turn.
Currently, I am reading the game state each turn and updating the turn! This is nice because I am not assuming the turn is simply switching colors each turn. So, if the state is reloaded for any reason, everything just works out of the box…
However, this restricts us in terms of what we can do for animations. You see, since we can’t assume the turn switch, we can’t implement a simple turn change animation, unless we hold a diff state in the GUI! Something like, if previous turn doesn’t equal next turn, then switch… This is ugly, and shouldn’t be handled by the graphics part.
Another problem I was facing with this load-from-scratch-each-time approach is overlapping events. If during an online game a move comes in, and we want to apply that, obviously an animation will be started. What if during that animation, a game ended event comes in? If we keep inspecting the whole game state each time, it would be pretty hard to accommodate all these cases…
This leaves me with the hopefully most simple and elegant solution .. An event queue. Every single change on the graphics side has to be driven by a game logic event, be it a turn change, play move, or game ended. The graphics part simply “blocks” on that queue, and process it one at a time.
This tasks seems intimidating, and I’m trying to summon every last bit of willpower I have left for this game to pull it through … I keep running into these issues, which is the most frustrating part. It’s definitely my fault for spending unreasonable time on polish before figuring these details out, but all I can do now is learn the lesson and move on.
I am struggling to find the zen between three entities in my game:
the game state is an immutable object that simply represents the state of the game. If you want to change the game state, a new copy is created. This makes game state super simple and easy to pass around with having to worry about it. As a bonus, implementing undo is literally as simple as having a stack of these game state objects.
Then we have the game logic. This is where the current game state is saved, and where the update loop happens, telling us if the game ended, or other similar events. The tricky part about this entity is that it could either be local or remote. When playing online, the logic actually completely runs on the server.
Finally, we have the graphics, which is the representation of the game logic and game state to the user. It needs the game state information in order to “know” what are the available moves, and that’s about it.
Seems simple, except when you try to organize these entities around working with singleplayer, local multiplayer, and online multiplayer. The proper abstraction needs to be in place in order for things to work properly.
The most challenging aspect of singleplayer is handling the undo action. Sure it’s as simple as a stack of
GameState objects, but finding the right place in these entities to put it and update the game is tricky. Then, we have the fact that the game logic runs on the server in online games, and the game can end at any given time, if a player surrenders or disconnects, for example. We somehow need to signal that the game has ended at that point.
With all these pieces in mind … There is only one answer I can think of. Make the logic hold the current game state, and that way, we can do the following:
For the remote game logic, we simply keep the game state in sync with the server, publishing new events to the graphics part. For the local game logic, we immediately apply changes to the game state, and publish the change events back to the graphics … This should do it, I hope.
Sad part about this is, I was struggling with designing this and spent countless hours refactoring stuff back and forth because of an extremely old design mistake made in the Dama C library. In the library, I had made the GameState stateful, which was a premature optimization back in 2012!!! Haunted me to this day .. So, finally removed that optimization, cleaned stuff up, and now everything is yet simpler and easier to reason with.
All these changes I’ve been making for a whole week, btw, are for the simple reason that I need to implement “forced moves” from the server. You see, when a player fails to make a move within the alloted time, the server forced a move on them. This is very hard to accommodate without proper code design, because until now, I always assumed that moves are coming from the actual players! So, if it’s the local player, it has to come from the graphics interaction part of the game … Not the case anymore.
Damn, that’s why I was stuck on this all along!!
GameResult problem where I was thinking of how to represent who won? Well, the reason it was a bit more complicated than it seems is because I have “smart game results”.
I don’t generate a single
GameResult and send it to all players, since there is player specific information, namely the rewards and rating delta. Instead, I generate a unique
GameResult per player.
With that being said, it would be ideal to make use of this characteristic and just embed a simple enum in the
That’s it. I tell each player whether they won, lost, or if it was a draw… Will play nicely with Elixir, and make my life easier on the frontend side as well.
Wow, I really should have started doing this since forever … But you you what they always say:
Better late than never
I mean, really, so many problems could have been preserved .. I’ve written a lot of them on white boards, idea paint walls, notebooks, notepads, and even voice notes, lol.
Well, time to get that task from the previous post out of the way, then it’s time for munching lunch.
In Dama, a game ends under the following conditions:
- A player disconnects
- A player surrenders
- The players agree on a draw
- The game reaches a draw state
- The game reaches an ended state
So many different ways to end the game, and thankfully it was super simple to streamline all this in Elixir. It’s actually quite neat, and would make for a nice post one day…
In any case, when the game ends, the backend sends a
game_ended message to the frontend, with the
GameResult. The game result contains the rewards the players get, if any, as well as the new rating of the players, if those changed.
For now, I need to figure out how should the frontend handle this? Since the old days, the frontend simply checked the game state to see if it’s still running, but that obviously doesn’t cover the first three termination conditions.
So, the best way to go about this is to embed the “winning” information in the
GameResult payload. It would need to represent the following information:
- winner -> player x
in Elixir, I usually represent this using atoms and tuples as follows:
That doesn’t translate well to CSharp for the frontend .. I guess my options are:
- String: “winner:player”, “draw”
- Enum: winner_white, winner_black, draw
I can’t think of any other viable options, really … The enum approach sounds nice, but would be painful to debug if the backend and frontend fall out of sync .. So, strings is the way to go.
to further lower the barrier of writing to my blog, I decided to start this devlog thingie. I can just do brain dumps here without even worrying about the structure, title, content, or anything like that…
Well, I actually started this because I am too lazy to create a live programming video feed. I kinda needed to make my development experience feel more interesting than just me typing stuff into a computer … So, … This is really unfocused.
In order to make my development experience more interesting, I decided to start this devlog. That’s sums it up.