GithubHelp home page GithubHelp logo

mcountryman / gloo Goto Github PK

View Code? Open in Web Editor NEW
3.0 3.0 2.0 39 KB

An OOP helper library for creating binary modules in Garry's Mod

Home Page: https://github.com/mcountryman/gloo

License: MIT License

C++ 96.61% Lua 3.39%
cpp oop garrysmod cpp11

gloo's Introduction

gloo

Codacy Badge

An OOP helper library intended to aid the creation of modern C++11 binary modules in Garry's Mod.

Getting Started

Download

git submodule add https://github.com/mcountryman/gloo vendor/gloo
git submodule update --init --recursive

Premake 5

project "..."
  include ".../gloo"

Header Overview

#include <GarrysMod/Lua/LuaValue.h>
  // class LuaValue
#include <GarrysMod/Lua/LuaObject.h>
  // class LuaObject
#include <GarrysMod/Lua/LuaEvent.h>
  // class LuaEventEmitter
  // class ILuaEventEmitter
  // class LuaEventEmitterManager

Examples

Check out test/src/gloo_test.cpp for an example that goes over 99% of the features of this library.

LuaValue

You can create a LuaValue two ways both shown below. The Make method creates an emtpy LuaValue with the supplied type, and the Pop method creates a LuaValue by popping the data from the Lua stack.

using namespace GarrysMod::Lua;

// Make will default create the object however, default the stored value to 
// something sensible.  For Types::BOOL gloo defaults the value to false.
LuaValue empty = LuaValue::Make(Types::BOOL);

// Pop method requires a lua state and a position to pop from.
LuaValue value = LuaValue::Pop(state, 1);

With this newly created LuaValue object we can use this directly in our C++ library or we can pass it back to the Lua stack.

using namespace GarrysMod::Lua;

LuaValue value = ...;

// Push to lua stack
value.Push(state);

// Validate type
if (value.type() == Type::BOOL)
{
  // Automatically cast to boolean
  bool boolean = value;

  method_with_one_boolean_parameter(value);
}

It is important to note that when invoking the cast operator for a LuaValue then assert method is used to ensure the underlying lua type is correctly associated with the requesting cast type.

LuaObject

With the LuaObject base we can create OOP lua objects.

using namespace GarrysMod::Lua;

class Object :
  // The number in the first parameter of the template for LuaObject is used as
  // and type identifier for lua.  The second is our defined object.
  public LuaObject<123, Object>
{
private:
  int _field;
public:
  Object() : LuaObject() // The ctor call to LuaObject is used to define the
                         // default metamethods __gc, __index, __newindex, and
                         // __tostring.  It is very important that these are 
                         // defined and used.
  {
    AddGetter("name_of_field", getter_method); // Add getter method
    AddSetter("name_of_field", setter_method); // Add setter method
    AddMethod("do_thing", do_thing);
  }
public:
  void DoThing() { ... }
private: // Personal preference for myself is to define lua callbacks as static
         // to not de-organize C++ class members.

  static int getter_method()
  {
    // We can pop the instance to our object by using the Pop method show below
    auto obj = Pop(state, 1);

    // From here we can expose our private field value to lua 
    return LuaValue::Push(state, obj->_field);
  }

  static int setter_method()
  {
    // Guess what we want to do here?
    auto obj = Pop(state, 1); // :0

    // Now we use our handy LuaValue magic to grab a value to store from Lua
    auto value = LuaValue::Pop(state, 2);

    // And ensure it is the correct type
    if (value.type() != Type::NUMBER)
      LUA->ArgError(2, "Expected number!");

    // Finally assign it to the _field field
    obj->_field = value;

    return 0;
  }

  static int do_thing(lua_State *state)
  {
    // Fairly self-explanitory
    Pop(state, 1)->DoThing();

    return 0;
  }
};

LuaEventEmitter

Now that we are all the way down here we can discuss the fun stuff! The LuaEventEmitter is a base class to be used similarly to the LuaObject class however, it comes with some pretty usefull abilities.

For one our LuaObject will automatically have the following methods exposed to Lua

obj:on(event: String, callback: Function)
obj:once(event: String, callback: Function)
obj:add_listener(event: String, callback: Function, delete_after_invokation: Boolean)
obj:remove_listeners()

Using these methods we call add Lua callbacks to be invoked when the Think hook is called.

class Object : public LuaEventEmitter<?, Object>
{
public:
  void AsyncWork()
  {
    Emit("event_name", "any", "valid", {{ "lua", "value" }}, 69, LuaValue::Make(Type::NIL));
  }
};

The Think hook is added and removed behind the scenes via the LuaEventEmitterManager object. Hooking is done when a listener is created and removal is done when there are zero active LuaEventEmitter objects in the LuaEventEmitter. Registration of a LuaEventEmitter is again, done when a listener is created.

Several potentially obscure things to note; data passed to the Emit method will not be dequeued until a valid listener is present during a Think event. The Think method in LuaEventEmitter is configured by default (via max_events_per_tick) to only dequeue 100 events per call. This can be changed by invoking the max_events_per_tick method with an integer value as the first parameter as shown below.

class Object : public LuaEventEmitter<?, Object>
{
  Object() : LuaEventEmitter() // As stated for LuaObject it is important to call
                            // the parent constructor here if we want access to
                            // the fields defined by LuaObject and now LuaEventEmitter
  {
    // Increase the maximum number of events to be dequeued per tick to 1000.
    max_events_per_tick(1000);
  }
};

gloo's People

Contributors

mcountryman avatar meow avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

uavxp meow

gloo's Issues

Build fails on Debian 9 with gcc (g++) 6.3.0

Compiler log: https://gist.github.com/MrMe0w/9c3a9d7c772df43f8ba5a085bb184f79
gcc -v:

meow@debian:~/gloo/test/project$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/6/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 6.3.0-18+deb9u1' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)

Cross-compiling libraries are installed. Can confirm that other Garry's Mod projects compile fine on this machine.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.