diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp
index c87fb974..527b43ef 100644
--- a/codegen/src/BindingGen.cpp
+++ b/codegen/src/BindingGen.cpp
@@ -34,10 +34,7 @@ public:
     static constexpr auto CLASS_NAME = "{class_name}";
 )GEN";
 
-	char const* monostate_constructor = R"GEN(    GEODE_MONOSTATE_CONSTRUCTOR_GD({class_name}, {first_base})
-)GEN";
-
-	char const* monostate_constructor_cutoff = R"GEN(    GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF({class_name}, {first_base})
+	char const* zero_constructor = R"GEN(    GEODE_ZERO_CONSTRUCTOR({class_name}, {first_base})
 )GEN";
 
     char const* function_definition = R"GEN(
@@ -180,9 +177,7 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
         // what.
         if (!cls.superclasses.empty()) {
             single_output += fmt::format(
-                can_find(cls.superclasses[0], "cocos2d") 
-                    ? format_strings::monostate_constructor_cutoff
-                    : format_strings::monostate_constructor,
+                format_strings::zero_constructor,
                 fmt::arg("class_name", cls.name),
                 fmt::arg("first_base", cls.superclasses[0])
             );
diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp
index 0ce659c8..2de69924 100644
--- a/codegen/src/SourceGen.cpp
+++ b/codegen/src/SourceGen.cpp
@@ -85,13 +85,13 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
 	reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
 	// we need to construct it back so that it uhhh ummm doesnt crash
 	// while going to the child destructors
-	auto thing = new (this) {class_name}(std::monostate(), sizeof({class_name}));
+	auto thing = new (this) {class_name}(geode::ZeroConstructor);
 	CCDestructor::lock(this) = true;
 }}
 )GEN";
 
 	char const* declare_constructor = R"GEN(
-{class_name}::{function_name}({parameters}) : {class_name}(std::monostate(), sizeof({class_name})) {{
+{class_name}::{function_name}({parameters}) : {class_name}(geode::ZeroConstructor) {{
 	// here we construct it as normal as we can, then destruct it
 	// using the generated functions. this ensures no memory gets leaked
 	// no crashes :pray:
diff --git a/loader/include/Geode/DefaultInclude.hpp b/loader/include/Geode/DefaultInclude.hpp
index 90c48f47..70d8e2e4 100644
--- a/loader/include/Geode/DefaultInclude.hpp
+++ b/loader/include/Geode/DefaultInclude.hpp
@@ -69,28 +69,21 @@ namespace cocos2d::extension {}
 #define GEODE_EXPAND(x) x
 #define GEODE_INVOKE(macro, ...) GEODE_EXPAND(macro(__VA_ARGS__))
 
-#define GEODE_FILL_CONSTRUCTOR(Class_, Offset_)                                                     \
-    Class_(std::monostate, size_t fill) :                                                           \
-        Class_({}, std::memset(reinterpret_cast<std::byte*>(this) + Offset_, 0, fill - Offset_)) {} \
-    Class_(std::monostate, void*)
+namespace geode {
+    struct ZeroConstructorType {};
 
-#define GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(Class_)    \
-    GEODE_MACOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) \
-    GEODE_IOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){})
+    static constexpr auto ZeroConstructor = ZeroConstructorType();
+}
 
-#define GEODE_MONOSTATE_CONSTRUCTOR_COCOS(Class_, Base_)                 \
-    GEODE_MACOS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) \
-    GEODE_IOS(Class_(std::monostate, size_t fill) : Base_({}, fill){})
+#define GEODE_ZERO_CONSTRUCTOR_BEGIN(Class_)                                              \
+    Class_(geode::ZeroConstructorType, void*) {}                                          \
+    Class_(geode::ZeroConstructorType, size_t fill) :                                     \
+        Class_(geode::ZeroConstructor, std::memset(static_cast<void*>(this), 0, fill)) {} \
+    Class_(geode::ZeroConstructorType) : Class_(geode::ZeroConstructor, nullptr) {}
 
-#define GEODE_MONOSTATE_CONSTRUCTOR_GD(Class_, Base_)                      \
-    GEODE_WINDOWS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) \
-    GEODE_MACOS(Class_(std::monostate, size_t fill) : Base_({}, fill){})   \
-    GEODE_IOS(Class_(std::monostate, size_t fill) : Base_({}, fill){})
-
-#define GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF(Class_, Base_)                    \
-    GEODE_WINDOWS(GEODE_FILL_CONSTRUCTOR(Class_, sizeof(Base_)) : Base_(){}) \
-    GEODE_MACOS(Class_(std::monostate, size_t fill) : Base_({}, fill){})     \
-    GEODE_IOS(Class_(std::monostate, size_t fill) : Base_({}, fill){})
+#define GEODE_ZERO_CONSTRUCTOR(Class_, Base_)                                                \
+    Class_(geode::ZeroConstructorType, size_t fill) : Base_(geode::ZeroConstructor, fill) {} \
+    Class_(geode::ZeroConstructorType) : Base_(geode::ZeroConstructor, sizeof(Class_)) {}
 
 #define GEODE_NUMBER_OF_ARGS(...) \
     GEODE_EXPAND(GEODE_NUMBER_OF_ARGS_(__VA_ARGS__, GEODE_NUMBER_SEQUENCE(), ))
diff --git a/loader/include/Geode/cocos/CCDirector.h b/loader/include/Geode/cocos/CCDirector.h
index 093415ed..dce5623c 100644
--- a/loader/include/Geode/cocos/CCDirector.h
+++ b/loader/include/Geode/cocos/CCDirector.h
@@ -121,6 +121,7 @@ public:
      *  @js ctor
      */
     CCDirector(void);
+    GEODE_ZERO_CONSTRUCTOR(CCDirector, CCObject)
     /**
      *  @js NA
      *  @lua NA
@@ -146,7 +147,7 @@ public:
     /** Get the FPS value */
     inline double getAnimationInterval(void) { return m_dAnimationInterval; }
     /** Set the FPS value. */
-    virtual void setAnimationInterval(double dValue) = 0;
+    virtual void setAnimationInterval(double dValue) {}
 
     /** Whether or not to display the FPS on the bottom-left corner */
     inline bool isDisplayStats(void) { return m_bDisplayStats; }
@@ -308,13 +309,13 @@ protected:
     /** Stops the animation. Nothing will be drawn. The main loop won't be triggered anymore.
      If you don't want to pause your animation call [pause] instead.
      */
-    virtual void stopAnimation(void) = 0;
+    virtual void stopAnimation(void) {}
 
     /** The main loop is triggered again.
      Call this function only if [stopAnimation] was called earlier
      @warning Don't call this function to start the main loop. To run the main loop call runWithScene
      */
-    virtual void startAnimation(void) = 0;
+    virtual void startAnimation(void) {}
 
 public:
     /** Draw the scene.
@@ -345,7 +346,7 @@ public:
     void setDepthTest(bool bOn);
 
 protected:
-    virtual void mainLoop(void) = 0;
+    virtual void mainLoop(void) {}
 
     /** The size in pixels of the surface. It could be different than the screen size.
     High-res devices might have a higher surface size than the screen size.
diff --git a/loader/include/Geode/cocos/CCScheduler.h b/loader/include/Geode/cocos/CCScheduler.h
index bbfdb9bc..4c1c4d96 100644
--- a/loader/include/Geode/cocos/CCScheduler.h
+++ b/loader/include/Geode/cocos/CCScheduler.h
@@ -141,6 +141,7 @@ class CC_DLL CCScheduler : public CCObject
     GEODE_FRIEND_MODIFY
 public:
     CCScheduler();
+    GEODE_ZERO_CONSTRUCTOR(CCScheduler, CCObject)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/base_nodes/CCNode.h b/loader/include/Geode/cocos/base_nodes/CCNode.h
index 809f4e97..e2388ba1 100644
--- a/loader/include/Geode/cocos/base_nodes/CCNode.h
+++ b/loader/include/Geode/cocos/base_nodes/CCNode.h
@@ -140,7 +140,7 @@ public:
      * @js ctor
      */
     CCNode(void);
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCNode, CCObject)
+    GEODE_ZERO_CONSTRUCTOR(CCNode, CCObject)
     
     /**
      * Default destructor
@@ -1638,7 +1638,7 @@ public:
      *  @js ctor
      */
     CCNodeRGBA();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCNodeRGBA, CCNode)
+    GEODE_ZERO_CONSTRUCTOR(CCNodeRGBA, CCNode)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/cocoa/CCObject.h b/loader/include/Geode/cocos/cocoa/CCObject.h
index 1f7adfae..4719faa0 100644
--- a/loader/include/Geode/cocos/cocoa/CCObject.h
+++ b/loader/include/Geode/cocos/cocoa/CCObject.h
@@ -112,7 +112,7 @@ protected:
         int m_nUnknown;
     )
 public:
-	GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCObject)
+	GEODE_ZERO_CONSTRUCTOR_BEGIN(CCObject)
     CCObject(void);
     /**
      *  @lua NA
diff --git a/loader/include/Geode/cocos/cocoa/CCSet.h b/loader/include/Geode/cocos/cocoa/CCSet.h
index 49784576..366955f2 100644
--- a/loader/include/Geode/cocos/cocoa/CCSet.h
+++ b/loader/include/Geode/cocos/cocoa/CCSet.h
@@ -46,7 +46,7 @@ public:
      * @lua NA
      */
     CCSet(void);
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCSet, CCObject)
+    GEODE_ZERO_CONSTRUCTOR(CCSet, CCObject)
     /**
      * @lua NA
      */
diff --git a/loader/include/Geode/cocos/cocoa/CCString.h b/loader/include/Geode/cocos/cocoa/CCString.h
index 21bc709f..9cdc2371 100644
--- a/loader/include/Geode/cocos/cocoa/CCString.h
+++ b/loader/include/Geode/cocos/cocoa/CCString.h
@@ -47,6 +47,7 @@ class CC_DLL CCString : public CCObject
 {
     GEODE_FRIEND_MODIFY
 public:
+    GEODE_ZERO_CONSTRUCTOR(CCString, CCObject)
     /**
      * @lua NA
      */
diff --git a/loader/include/Geode/cocos/draw_nodes/CCDrawNode.h b/loader/include/Geode/cocos/draw_nodes/CCDrawNode.h
index e6659267..fc64ab99 100644
--- a/loader/include/Geode/cocos/draw_nodes/CCDrawNode.h
+++ b/loader/include/Geode/cocos/draw_nodes/CCDrawNode.h
@@ -94,7 +94,7 @@ public:
     void setBlendFunc(const ccBlendFunc &blendFunc);
     
     CCDrawNode();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCDrawNode, CCNodeRGBA)
+    GEODE_ZERO_CONSTRUCTOR(CCDrawNode, CCNodeRGBA)
 
     /** listen the event that coming to foreground on Android  
      * @js NA
diff --git a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControl.h b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControl.h
index 3ad32bc7..d6fc4b50 100644
--- a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControl.h
+++ b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControl.h
@@ -139,7 +139,7 @@ public:
      *  @js ctor
      */
     CCControl();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCControl, CCLayerRGBA)
+    GEODE_ZERO_CONSTRUCTOR(CCControl, CCLayerRGBA)
     
     virtual bool init(void);
     /**
diff --git a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControlColourPicker.h b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControlColourPicker.h
index d1c6fa25..9c7d2ca6 100644
--- a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControlColourPicker.h
+++ b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCControlColourPicker.h
@@ -58,7 +58,7 @@ public:
         virtual void setColorValue(ccColor3B const&);
     )
 
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCControlColourPicker, CCControl)
+    GEODE_ZERO_CONSTRUCTOR(CCControlColourPicker, CCControl)
     CCControlColourPicker();
     virtual ~CCControlColourPicker();
 
diff --git a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCScale9Sprite.h b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCScale9Sprite.h
index d3176597..76ec289a 100644
--- a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCScale9Sprite.h
+++ b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/CCScale9Sprite.h
@@ -54,7 +54,7 @@ class CC_DLL CCScale9Sprite : public CCNodeRGBA
 {
 public:
     CCScale9Sprite();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCScale9Sprite, CCNodeRGBA)
+    GEODE_ZERO_CONSTRUCTOR(CCScale9Sprite, CCNodeRGBA)
     virtual ~CCScale9Sprite();
 
 public:
diff --git a/loader/include/Geode/cocos/extensions/GUI/CCScrollView/CCScrollView.h b/loader/include/Geode/cocos/extensions/GUI/CCScrollView/CCScrollView.h
index 3e5bfeef..8476bdec 100644
--- a/loader/include/Geode/cocos/extensions/GUI/CCScrollView/CCScrollView.h
+++ b/loader/include/Geode/cocos/extensions/GUI/CCScrollView/CCScrollView.h
@@ -69,7 +69,7 @@ public:
      *  @js ctor
      */
     CCScrollView();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCScrollView, CCLayer)
+    GEODE_ZERO_CONSTRUCTOR(CCScrollView, CCLayer)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/keypad_dispatcher/CCKeypadDelegate.h b/loader/include/Geode/cocos/keypad_dispatcher/CCKeypadDelegate.h
index cf588eba..e812dac6 100644
--- a/loader/include/Geode/cocos/keypad_dispatcher/CCKeypadDelegate.h
+++ b/loader/include/Geode/cocos/keypad_dispatcher/CCKeypadDelegate.h
@@ -59,7 +59,7 @@ class CC_DLL CCKeypadHandler : public CCObject
 {
     GEODE_FRIEND_MODIFY
 public:
-	GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCKeypadHandler, CCObject)
+	GEODE_ZERO_CONSTRUCTOR(CCKeypadHandler, CCObject)
 	inline CCKeypadHandler() = default;
     virtual ~CCKeypadHandler(void);
 
diff --git a/loader/include/Geode/cocos/label_nodes/CCLabelBMFont.h b/loader/include/Geode/cocos/label_nodes/CCLabelBMFont.h
index d7a90866..5d36195a 100644
--- a/loader/include/Geode/cocos/label_nodes/CCLabelBMFont.h
+++ b/loader/include/Geode/cocos/label_nodes/CCLabelBMFont.h
@@ -198,7 +198,7 @@ public:
      *  @js ctor
      */
     CCLabelBMFont();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLabelBMFont, CCSpriteBatchNode)
+    GEODE_ZERO_CONSTRUCTOR(CCLabelBMFont, CCSpriteBatchNode)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h b/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h
index 721d8b60..fdea5e53 100644
--- a/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h
+++ b/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h
@@ -63,6 +63,7 @@ public:
      *  @js ctor
      */
     CCLabelTTF();
+    GEODE_ZERO_CONSTRUCTOR(CCLabelTTF, CCSprite)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCLayer.h b/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCLayer.h
index 512fdf6a..7305cfb3 100644
--- a/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCLayer.h
+++ b/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCLayer.h
@@ -75,7 +75,7 @@ public:
      *  @js ctor
      */
     CCLayer();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLayer, CCNode)
+    GEODE_ZERO_CONSTRUCTOR(CCLayer, CCNode)
     /**
      *  @js NA
      *  @lua NA
@@ -233,7 +233,7 @@ public:
      *  @js ctor
      */
     CCLayerRGBA();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLayerRGBA, CCLayer)
+    GEODE_ZERO_CONSTRUCTOR(CCLayerRGBA, CCLayer)
     /**
      *  @js NA
      *  @lua NA
@@ -290,7 +290,7 @@ public:
      *  @js ctor
      */
     CCLayerColor();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLayerColor, CCLayerRGBA)
+    GEODE_ZERO_CONSTRUCTOR(CCLayerColor, CCLayerRGBA)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCScene.h b/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCScene.h
index 21003355..ed00cdda 100644
--- a/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCScene.h
+++ b/loader/include/Geode/cocos/layers_scenes_transitions_nodes/CCScene.h
@@ -63,7 +63,7 @@ public:
      *  @js ctor
      */
     CCScene();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCScene, CCNode)
+    GEODE_ZERO_CONSTRUCTOR(CCScene, CCNode)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/menu_nodes/CCMenu.h b/loader/include/Geode/cocos/menu_nodes/CCMenu.h
index dedd67f0..23e10daa 100644
--- a/loader/include/Geode/cocos/menu_nodes/CCMenu.h
+++ b/loader/include/Geode/cocos/menu_nodes/CCMenu.h
@@ -64,7 +64,7 @@ public:
      *  @js ctor
      */
     CCMenu() : m_pSelectedItem(NULL) {}
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenu, CCLayerRGBA)
+    GEODE_ZERO_CONSTRUCTOR(CCMenu, CCLayerRGBA)
     /**
      *  @js NA
      *  @lua NA
diff --git a/loader/include/Geode/cocos/menu_nodes/CCMenuItem.h b/loader/include/Geode/cocos/menu_nodes/CCMenuItem.h
index 4a44c453..be49aa44 100644
--- a/loader/include/Geode/cocos/menu_nodes/CCMenuItem.h
+++ b/loader/include/Geode/cocos/menu_nodes/CCMenuItem.h
@@ -71,7 +71,7 @@ public:
     , m_pfnSelector(NULL)
     , m_nScriptTapHandler(0)
     {}
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItem, CCNodeRGBA)
+    GEODE_ZERO_CONSTRUCTOR(CCMenuItem, CCNodeRGBA)
     /**
      * @js NA
      * @lua NA
@@ -139,7 +139,7 @@ public:
     : m_pLabel(NULL)
     , m_fOriginalScale(0.0)
     {}
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItemLabel, CCMenuItem)
+    GEODE_ZERO_CONSTRUCTOR(CCMenuItemLabel, CCMenuItem)
     /**
      * @js NA
      * @lua NA
@@ -292,7 +292,7 @@ public:
     ,m_pSelectedImage(NULL)
     ,m_pDisabledImage(NULL)
     {}
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItemSprite, CCMenuItem)
+    GEODE_ZERO_CONSTRUCTOR(CCMenuItemSprite, CCMenuItem)
 
     /** creates a menu item with a normal, selected and disabled image*/
     static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite = NULL);
@@ -337,7 +337,7 @@ public:
      * @lua NA
      */
     CCMenuItemImage(){}
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItemImage, CCMenuItemSprite)
+    GEODE_ZERO_CONSTRUCTOR(CCMenuItemImage, CCMenuItemSprite)
     /**
      * @js NA
      * @lua NA
diff --git a/loader/include/Geode/cocos/platform/CCApplicationProtocol.h b/loader/include/Geode/cocos/platform/CCApplicationProtocol.h
index 1acca89e..4aeb1001 100644
--- a/loader/include/Geode/cocos/platform/CCApplicationProtocol.h
+++ b/loader/include/Geode/cocos/platform/CCApplicationProtocol.h
@@ -62,24 +62,24 @@ public:
     @return true    Initialize success, app continue.
     @return false   Initialize failed, app terminate.
     */
-    virtual bool applicationDidFinishLaunching() = 0;
+    virtual bool applicationDidFinishLaunching() { return true; }
 
     /**
     @brief  The function be called when the application enter background
     @param  the pointer of the application
     */
-    virtual void applicationDidEnterBackground() = 0;
+    virtual void applicationDidEnterBackground() {}
 
     /**
     @brief  The function be called when the application enter foreground
     @param  the pointer of the application
     */
-    virtual void applicationWillEnterForeground() = 0;
+    virtual void applicationWillEnterForeground() {}
 
     RT_ADD(
         virtual void applicationWillBecomeActive() {}
         virtual void applicationWillResignActive() {}
-        virtual void trySaveGame() = 0;
+        virtual void trySaveGame() {}
         virtual void gameDidSave() {}
     )
 
@@ -87,18 +87,18 @@ public:
     @brief    Callback by CCDirector for limit FPS.
     @interval       The time, expressed in seconds, between current frame and next. 
     */
-    virtual void setAnimationInterval(double interval) = 0;
+    virtual void setAnimationInterval(double interval) {}
 
     /**
     @brief Get current language config
     @return Current language config
     */
-    virtual ccLanguageType getCurrentLanguage() = 0;
+    virtual ccLanguageType getCurrentLanguage() { return kLanguageEnglish; }
     
     /**
      @brief Get target platform
      */
-    virtual TargetPlatform getTargetPlatform() = 0;
+    virtual TargetPlatform getTargetPlatform() { return kTargetWindows; }
 
     RT_ADD( virtual void openURL(const char* url) {} )
 };
diff --git a/loader/include/Geode/cocos/platform/CCFileUtils.h b/loader/include/Geode/cocos/platform/CCFileUtils.h
index 98341239..9af4ad8e 100644
--- a/loader/include/Geode/cocos/platform/CCFileUtils.h
+++ b/loader/include/Geode/cocos/platform/CCFileUtils.h
@@ -41,8 +41,8 @@ class CCArray;
  */
 
 struct CCTexturePack {
-  std::string m_id;
-  std::vector<std::string> m_paths;
+    std::string m_id;
+    std::vector<std::string> m_paths;
 };
 
 //! @brief  Helper class to handle file operations
@@ -52,6 +52,8 @@ class CC_DLL CCFileUtils : public TypeInfo
     friend class CCArray;
     friend class CCDictionary;
 public:
+
+    GEODE_ZERO_CONSTRUCTOR_BEGIN(CCFileUtils) 
     /**
      *  Returns an unique ID for this class.
      *  @note It's only used for JSBindings now.
@@ -339,7 +341,7 @@ public:
      *  @return  The path that can be write/read a file in
      *  @lua NA
      */
-    virtual gd::string getWritablePath() = 0;
+    virtual gd::string getWritablePath() { return ""; }
 
     RT_ADD(virtual gd::string getWritablePath2();)
     
@@ -351,7 +353,7 @@ public:
      *  @return true if the file exists, otherwise it will return false.
      *  @lua NA
      */
-    virtual bool isFileExist(const gd::string& strFilePath) = 0;
+    virtual bool isFileExist(const gd::string& strFilePath) { return false; }
     
     /**
      *  Checks whether the path is an absolute path.
diff --git a/loader/include/Geode/cocos/platform/CCImage.h b/loader/include/Geode/cocos/platform/CCImage.h
index 131cfe1b..6d13d6ae 100644
--- a/loader/include/Geode/cocos/platform/CCImage.h
+++ b/loader/include/Geode/cocos/platform/CCImage.h
@@ -46,7 +46,7 @@ public:
      @js ctor
      */
     CCImage();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCImage, CCObject)
+    GEODE_ZERO_CONSTRUCTOR(CCImage, CCObject)
     /**
      * @js NA
      * @lua NA
diff --git a/loader/include/Geode/cocos/platform/ios/CCApplication.h b/loader/include/Geode/cocos/platform/ios/CCApplication.h
index 85467639..f0c4dff0 100644
--- a/loader/include/Geode/cocos/platform/ios/CCApplication.h
+++ b/loader/include/Geode/cocos/platform/ios/CCApplication.h
@@ -36,7 +36,7 @@ class CC_DLL CCApplication : public CCApplicationProtocol
 {
     GEODE_FRIEND_MODIFY
 public:
-	GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCApplication)
+	GEODE_ZERO_CONSTRUCTOR_BEGIN(CCApplication)
     CCApplication();
     /**
      *  @js NA
diff --git a/loader/include/Geode/cocos/platform/mac/CCApplication.h b/loader/include/Geode/cocos/platform/mac/CCApplication.h
index 57562274..139396d9 100644
--- a/loader/include/Geode/cocos/platform/mac/CCApplication.h
+++ b/loader/include/Geode/cocos/platform/mac/CCApplication.h
@@ -35,7 +35,7 @@ class CC_DLL CCApplication : public CCApplicationProtocol
 {
     GEODE_FRIEND_MODIFY
 public:
-	GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCApplication)
+	GEODE_ZERO_CONSTRUCTOR_BEGIN(CCApplication)
     CCApplication();
     virtual ~CCApplication();
         
diff --git a/loader/include/Geode/cocos/platform/win32/CCApplication.h b/loader/include/Geode/cocos/platform/win32/CCApplication.h
index 86756c2e..a6466499 100644
--- a/loader/include/Geode/cocos/platform/win32/CCApplication.h
+++ b/loader/include/Geode/cocos/platform/win32/CCApplication.h
@@ -15,7 +15,7 @@ class CC_DLL CCApplication : public CCApplicationProtocol
 {
     GEODE_FRIEND_MODIFY
 public:
-    GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCApplication)
+    GEODE_ZERO_CONSTRUCTOR_BEGIN(CCApplication)
     CCApplication();
     virtual ~CCApplication();
 
diff --git a/loader/include/Geode/cocos/platform/win32/CCEGLView.h b/loader/include/Geode/cocos/platform/win32/CCEGLView.h
index a8a7b838..91ff5e32 100644
--- a/loader/include/Geode/cocos/platform/win32/CCEGLView.h
+++ b/loader/include/Geode/cocos/platform/win32/CCEGLView.h
@@ -45,6 +45,7 @@ protected:
     RT_ADD( virtual ~CCEGLView(); )
 public:
     CCEGLView();
+    GEODE_ZERO_CONSTRUCTOR(CCEGLView, CCObject)
     RT_REMOVE(  virtual ~CCEGLView();   )
 
     /* override functions */
diff --git a/loader/include/Geode/cocos/robtop/keyboard_dispatcher/CCKeyboardDelegate.h b/loader/include/Geode/cocos/robtop/keyboard_dispatcher/CCKeyboardDelegate.h
index 094bf047..e4597085 100644
--- a/loader/include/Geode/cocos/robtop/keyboard_dispatcher/CCKeyboardDelegate.h
+++ b/loader/include/Geode/cocos/robtop/keyboard_dispatcher/CCKeyboardDelegate.h
@@ -207,7 +207,7 @@ RT_ADD(
 	class CC_DLL CCKeyboardHandler : public CCObject
 	{
 	public:
-		GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCKeyboardHandler, CCObject)
+		GEODE_ZERO_CONSTRUCTOR(CCKeyboardHandler, CCObject)
 		inline CCKeyboardHandler() = default;
 		
 		virtual ~CCKeyboardHandler();
diff --git a/loader/include/Geode/cocos/robtop/mouse_dispatcher/CCMouseDelegate.h b/loader/include/Geode/cocos/robtop/mouse_dispatcher/CCMouseDelegate.h
index 0f98200c..5f1e8be2 100644
--- a/loader/include/Geode/cocos/robtop/mouse_dispatcher/CCMouseDelegate.h
+++ b/loader/include/Geode/cocos/robtop/mouse_dispatcher/CCMouseDelegate.h
@@ -22,7 +22,7 @@ RT_ADD(
 	class CC_DLL CCMouseHandler : public CCObject
 	{
 	public:
-		GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMouseHandler, CCObject)
+		GEODE_ZERO_CONSTRUCTOR(CCMouseHandler, CCObject)
 		inline CCMouseHandler() = default;
 		
 		virtual ~CCMouseHandler();
diff --git a/loader/include/Geode/cocos/sprite_nodes/CCSprite.h b/loader/include/Geode/cocos/sprite_nodes/CCSprite.h
index e633b358..636e7a41 100644
--- a/loader/include/Geode/cocos/sprite_nodes/CCSprite.h
+++ b/loader/include/Geode/cocos/sprite_nodes/CCSprite.h
@@ -168,7 +168,7 @@ public:
      * @js ctor
      */
     CCSprite(void);
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCSprite, CCNodeRGBA)
+    GEODE_ZERO_CONSTRUCTOR(CCSprite, CCNodeRGBA)
     
     /**
      * Default destructor
diff --git a/loader/include/Geode/cocos/sprite_nodes/CCSpriteBatchNode.h b/loader/include/Geode/cocos/sprite_nodes/CCSpriteBatchNode.h
index 619eae92..3233c913 100644
--- a/loader/include/Geode/cocos/sprite_nodes/CCSpriteBatchNode.h
+++ b/loader/include/Geode/cocos/sprite_nodes/CCSpriteBatchNode.h
@@ -68,7 +68,7 @@ public:
      *  @js ctor
      */
     CCSpriteBatchNode();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCSpriteBatchNode, CCNode)
+    GEODE_ZERO_CONSTRUCTOR(CCSpriteBatchNode, CCNode)
     /**
      * @js NA
      * @lua NA
diff --git a/loader/include/Geode/cocos/text_input_node/CCIMEDelegate.h b/loader/include/Geode/cocos/text_input_node/CCIMEDelegate.h
index adff3b12..6a83a4a3 100644
--- a/loader/include/Geode/cocos/text_input_node/CCIMEDelegate.h
+++ b/loader/include/Geode/cocos/text_input_node/CCIMEDelegate.h
@@ -50,6 +50,7 @@ class CC_DLL CCIMEDelegate
 {
     GEODE_FRIEND_MODIFY
 public:
+    GEODE_ZERO_CONSTRUCTOR_BEGIN(CCIMEDelegate)
     virtual ~CCIMEDelegate();
 
     virtual bool attachWithIME();
diff --git a/loader/include/Geode/cocos/textures/CCTexture2D.h b/loader/include/Geode/cocos/textures/CCTexture2D.h
index 6a107a48..f83c5171 100644
--- a/loader/include/Geode/cocos/textures/CCTexture2D.h
+++ b/loader/include/Geode/cocos/textures/CCTexture2D.h
@@ -117,7 +117,7 @@ public:
      * @js ctor
      */
     CCTexture2D();
-    GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCTexture2D, CCObject)
+    GEODE_ZERO_CONSTRUCTOR(CCTexture2D, CCObject)
     /**
      * @js NA
      * @lua NA
diff --git a/loader/include/Geode/cocos/touch_dispatcher/CCTouchHandler.h b/loader/include/Geode/cocos/touch_dispatcher/CCTouchHandler.h
index fb818ae4..1671092d 100644
--- a/loader/include/Geode/cocos/touch_dispatcher/CCTouchHandler.h
+++ b/loader/include/Geode/cocos/touch_dispatcher/CCTouchHandler.h
@@ -48,7 +48,7 @@ class CC_DLL  CCTouchHandler : public CCObject
 {
     GEODE_FRIEND_MODIFY
 public:
-	GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCTouchHandler, CCObject)
+	GEODE_ZERO_CONSTRUCTOR(CCTouchHandler, CCObject)
 	inline CCTouchHandler() = default;
     virtual ~CCTouchHandler(void);
 
@@ -86,7 +86,7 @@ class CC_DLL  CCStandardTouchHandler : public CCTouchHandler
 {
     GEODE_FRIEND_MODIFY
 public:
-	GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCStandardTouchHandler, CCTouchHandler)
+	GEODE_ZERO_CONSTRUCTOR(CCStandardTouchHandler, CCTouchHandler)
 	inline CCStandardTouchHandler() = default;
 
     ~CCStandardTouchHandler(void);
@@ -110,7 +110,7 @@ class CC_DLL  CCTargetedTouchHandler : public CCTouchHandler
 {
     GEODE_FRIEND_MODIFY
 public:
-	GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCTargetedTouchHandler, CCTouchHandler)
+	GEODE_ZERO_CONSTRUCTOR(CCTargetedTouchHandler, CCTouchHandler)
 	inline CCTargetedTouchHandler() = default;
 	
     ~CCTargetedTouchHandler(void);
diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp
index 925b6757..e3e3efcd 100644
--- a/loader/include/Geode/modify/Modify.hpp
+++ b/loader/include/Geode/modify/Modify.hpp
@@ -134,8 +134,8 @@ namespace geode {
         // abusing the internal stuff
         // basically we dont want modify to invoke base ctors and dtors
         // we already have utilities for these, which are ccdestructor
-        // and the monostate constructor
-        Modify() : Base(std::monostate(), sizeof(Base)) {}
+        // and the zero constructor
+        Modify() : Base(ZeroConstructor) {}
 
         ~Modify() {
             cocos2d::CCDestructor::lock(this) = true;
diff --git a/loader/include/Geode/utils/addresser.hpp b/loader/include/Geode/utils/addresser.hpp
index ec09837d..f8f0ffc2 100644
--- a/loader/include/Geode/utils/addresser.hpp
+++ b/loader/include/Geode/utils/addresser.hpp
@@ -9,36 +9,24 @@
 
 #include <Geode/DefaultInclude.hpp>
 #include <cocos-ext.h>
+#include <concepts>
 #include <cstdlib>
 #include <stddef.h>
 #include <type_traits>
-#include <concepts>
 
 namespace geode::addresser {
 
-    template <typename T>
-    inline intptr_t getVirtual(T func);
+    template <class Function>
+    intptr_t getVirtual(Function func);
 
-    template <typename T>
-    inline intptr_t getNonVirtual(T func);
+    template <class Function>
+    intptr_t getNonVirtual(Function func);
 
-    template <typename T, typename F>
-    inline F thunkAdjust(T func, F self);
+    template <class Function, class Class>
+    Class thunkAdjust(Function func, Class self);
 
-    template <typename T, typename F>
-    inline F rthunkAdjust(T func, F self);
-
-    template <class Class>
-    Class* friendCreate(typename std::void_t<decltype(static_cast<Class* (*)()>(&Class::create))>*) {
-        auto ret = Class::create();
-        ret->retain();
-        return ret;
-    }
-
-    template <class Class>
-    concept HasCreate = requires() {
-                            { friendCreate<Class>(nullptr) } -> std::same_as<Class*>;
-                        };
+    template <class Function, class Class>
+    Class rthunkAdjust(Function func, Class self);
 
     class GEODE_DLL Addresser final {
         template <char C>
@@ -76,57 +64,20 @@ namespace geode::addresser {
             return thunk;
         }
 
-        // I gave up
-        // template <HasCreate Class>
-        // static Class* generateInstance(Class*) {
-        //     return friendCreate<Class>(nullptr);
-        // }
-
-        // I extra gave up
-        template <class = void>
-        static cocos2d::extension::CCScrollView* generateInstance(cocos2d::extension::CCScrollView*) {
-            return cocos2d::extension::CCScrollView::create({0.0f, 0.0f}, cocos2d::CCLayer::create());
-        }
-
-        template <class = void>
-        static cocos2d::CCFileUtils* generateInstance(cocos2d::CCFileUtils*) {
-            return cocos2d::CCFileUtils::sharedFileUtils();
-        }
-
-        template <class Class>
-        static Class* generateInstance(Class*) {
-            if constexpr (std::is_abstract_v<Class>) {
-                // Cant construct abstract classes, so fail early
-                return nullptr;
-            } else {
-                // Create a random memory block with the size of Class
-                // Assign a pointer to that block and cast it to type Class*
-                uint8_t dum[sizeof(Class)]{};
-                auto ptr = reinterpret_cast<Class*>(dum);
-                // Now you have a object of Class that actually isn't an object of Class and is just a
-                // random memory But C++ doesn't know that of course So now you can copy an object
-                // that wasn't there in the first place
-                // ((oh also get the offsets of the virtual tables))
-                auto ins = new Class(*ptr);
-                // this is how the first human was made
-                return ins;
-            }
-        }
-
         template <class Class>
         static Class* cachedInstance() {
-            static auto ret = generateInstance(static_cast<Class*>(nullptr));
+            static auto ret = new Class(ZeroConstructor);
             return ret;
         }
 
         /**
          * Specialized functionss
          */
-        template <typename R, typename T, typename... Ps>
-        static intptr_t addressOfVirtual(R (T::*func)(Ps...)) {
+        template <class Return, class Class, class... Parameters>
+        static intptr_t addressOfVirtual(Return (Class::*func)(Parameters...)) {
             using geode::cast::reference_cast;
 
-            auto ins = cachedInstance<T>();
+            auto ins = cachedInstance<Class>();
             // generateInstance will return nullptr on most abstract classes,
             // so dont bother getting the address
             if (ins == nullptr) {
@@ -136,97 +87,87 @@ namespace geode::addresser {
             auto thunk = thunkOf(func);
 
             // [[this + thunk] + offset] is the function we want
-            auto address = *reinterpret_cast<intptr_t*>(*reinterpret_cast<intptr_t*>(reinterpret_cast<intptr_t>(ins) + thunk) + index);
+            auto address = *reinterpret_cast<intptr_t*>(
+                *reinterpret_cast<intptr_t*>(reinterpret_cast<intptr_t>(ins) + thunk) + index
+            );
 
             address = followThunkFunction(address);
 
             return address;
         }
 
-        template <typename R, typename T, typename... Ps>
-        static intptr_t addressOfVirtual(R (T::*func)(Ps...) const) {
-            return addressOfVirtual(reinterpret_cast<R (T::*)(Ps...)>(func));
+        template <class Return, class Class, class... Parameters>
+        static intptr_t addressOfVirtual(Return (Class::*func)(Parameters...) const) {
+            return addressOfVirtual(reinterpret_cast<Return (Class::*)(Parameters...)>(func));
         }
 
-        template <typename R, typename T, typename... Ps>
-        static intptr_t addressOfNonVirtual(R (T::*func)(Ps...) const) {
-            return addressOfNonVirtual(reinterpret_cast<R (T::*)(Ps...)>(func));
+        template <class Return, class Class, class... Parameters>
+        static intptr_t addressOfNonVirtual(Return (Class::*func)(Parameters...) const) {
+            return addressOfNonVirtual(reinterpret_cast<Return (Class::*)(Parameters...)>(func));
         }
 
         static intptr_t followThunkFunction(intptr_t address);
 
-        template <typename R, typename T, typename... Ps>
-        static intptr_t addressOfNonVirtual(R (T::*func)(Ps...)) {
+        template <class Return, class Class, class... Parameters>
+        static intptr_t addressOfNonVirtual(Return (Class::*func)(Parameters...)) {
             return followThunkFunction(geode::cast::reference_cast<intptr_t>(func));
         }
 
-        template <typename R, typename... Ps>
-        static intptr_t addressOfNonVirtual(R (*func)(Ps...)) {
+        template <class Return, class... Parameters>
+        static intptr_t addressOfNonVirtual(Return (*func)(Parameters...)) {
             return followThunkFunction(geode::cast::reference_cast<intptr_t>(func));
         }
 
-        template <typename T>
-        friend intptr_t getVirtual(T func);
+        template <class Function>
+        friend intptr_t getVirtual(Function func);
 
-        template <typename T>
-        friend intptr_t getNonVirtual(T func);
+        template <class Function>
+        friend intptr_t getNonVirtual(Function func);
 
-        template <typename T, typename F>
-        friend F thunkAdjust(T func, F self);
+        template <class Function, class Class>
+        friend Class thunkAdjust(Function func, Class self);
 
-        template <typename T, typename F>
-        friend F rthunkAdjust(T func, F self);
+        template <class Function, class Class>
+        friend Class rthunkAdjust(Function func, Class self);
     };
 
-#ifdef GEODE_ADDRESSER_TEST
-    template <typename T>
-    inline intptr_t getVirtual(T func) {
+    /**
+     * Gets the real address of a virtual function
+     */
+    template <class Function>
+    inline intptr_t getVirtual(Function func) {
         return Addresser::addressOfVirtual(func);
     }
 
-    template <typename T>
-    inline intptr_t getNonVirtual(T func) {
+    /**
+     * Gets the real address of a non-virtual function
+     */
+    template <class Function>
+    inline intptr_t getNonVirtual(Function func) {
         return Addresser::addressOfNonVirtual(func);
     }
-#else
-    template <typename T>
-    inline intptr_t getVirtual(T func) {
-        // log::debug(
-        //     "Get virtual function address from {}",
-        //     utils::intToHex(geode::cast::reference_cast<intptr_t>(func))
-        // );
-        auto addr = Addresser::addressOfVirtual(func);
-        // log::debug("The address is: {}", utils::intToHex(addr));
-        return addr;
-    }
 
-    template <typename T>
-    inline intptr_t getNonVirtual(T func) {
-        // log::debug(
-        //     "Get non-virtual function address from {}",
-        //     utils::intToHex(geode::cast::reference_cast<intptr_t>(func))
-        // );
-        auto addr = Addresser::addressOfNonVirtual(func);
-        // log::debug("The address is: {}", utils::intToHex(addr));
-        return addr;
-    }
-
-    template <typename T, typename F>
-    inline F thunkAdjust(T func, F self) {
+    /**
+     * Adjusts a class instance to its appropriate base for the given virtual function
+     */
+    template <class Function, class Class>
+    inline Class thunkAdjust(Function func, Class self) {
         // do NOT delete the line below.
         // doing so breaks thunk adjusting on windows.
         // why? bruh idk
         auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func);
-        return (F)((intptr_t)self + Addresser::thunkOf(func));
+        return (Class)((intptr_t)self + Addresser::thunkOf(func));
     }
 
-    template <typename T, typename F>
-    inline F rthunkAdjust(T func, F self) {
+    /**
+     * Adjusts a class instance back from its appropriate base for the given virtual function to the original base
+     */
+    template <class Function, class Class>
+    inline Class rthunkAdjust(Function func, Class self) {
         // do NOT delete the line below.
         // doing so breaks thunk adjusting on windows.
         // why? bruh idk
         auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func);
-        return (F)((intptr_t)self - Addresser::thunkOf(func));
+        return (Class)((intptr_t)self - Addresser::thunkOf(func));
     }
-#endif
 }
diff --git a/loader/include/link/gdstring.lib b/loader/include/link/gdstring.lib
index 11aac0c5..d422bb31 100644
Binary files a/loader/include/link/gdstring.lib and b/loader/include/link/gdstring.lib differ