WIP: Boostrapping NetSlime
- Just a old name for a set of changes to make the game framework hardened for multiplayer as well as some ease of use functionality.
This commit is contained in:
		| @@ -18,6 +18,7 @@ using namespace gen; | ||||
| #include "GasaGen_ChangeBPActionMenu.cpp" | ||||
| #include "GasaGen_DevOptionsCache.cpp" | ||||
| #include "GasaGen_HostWidgetController.cpp" | ||||
| #include "GasaGen_NetSlime.cpp" | ||||
|  | ||||
| int gen_main() | ||||
| { | ||||
| @@ -80,6 +81,7 @@ int gen_main() | ||||
| 	gen_UGasaAttributeSet(); | ||||
| 	gen_FGasaDevOptionsCache(); | ||||
| 	gen_UHostWidgetController(); | ||||
| 	// gen_netslime_interfaces(); | ||||
|  | ||||
| 	// One offs | ||||
| 	if (0) | ||||
|   | ||||
| @@ -13,6 +13,9 @@ using namespace gen; | ||||
| #define path_config              path_source      "Config/" | ||||
| #define path_module_gasa         path_source      "Gasa/" | ||||
| #define path_gasa_ability_system path_module_gasa "AbilitySystem/" | ||||
| #define path_gasa_actors         path_module_gasa "Actors/" | ||||
| #define path_gasa_characters     path_module_gasa "Characters/" | ||||
| #define path_gasa_game           path_module_gasa "Game/" | ||||
| #define path_gasa_ui             path_module_gasa "UI/" | ||||
|  | ||||
| constexpr StrC str_DECLARE_CLASS                                         = txt("DECLARE_CLASS("); | ||||
|   | ||||
							
								
								
									
										118
									
								
								Project/Source/GasaGen/GasaGen_NetSlime.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								Project/Source/GasaGen/GasaGen_NetSlime.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| // Used in the GasaGen.cpp translation unit | ||||
| #if GASA_INTELLISENSE_DIRECTIVES | ||||
| #pragma once | ||||
| #define GEN_EXPOSE_BACKEND | ||||
| #include "gen.hpp" | ||||
| #include "gen.builder.hpp" | ||||
| #include "GasaGenCommon.cpp" | ||||
| #endif | ||||
|  | ||||
| void gen_netslime_interface(CodeClass aclass) | ||||
| { | ||||
| 	CodeBody net_slime_class_interface = def_body(ECode::Class_Body); | ||||
| 	{ | ||||
| 	#pragma push_macro("FORCEINLINE") | ||||
| 	#undef FORCEINLINE | ||||
| 		CodeFn DrawNetCullingSphere = parse_function( code( | ||||
| 			FORCEINLINE void DrawNetCullingSphere(float Duration, float Thickness) const final { Gasa::DrawNetCullingSphere(this, Duration, Thickness); } | ||||
| 		)); | ||||
| 		CodeFn GetNetworkMode   = parse_function( code( FORCEINLINE ENetworkMode GetNetworkMode()   const { return Gasa::GetNetworkMode(this); }  )); | ||||
| 		CodeFn IsClient         = parse_function( code( FORCEINLINE bool         IsClient()         const { return Gasa::IsClient(this); }        )); | ||||
| 		CodeFn IsListenServer   = parse_function( code( FORCEINLINE bool         IsListenServer()   const { return Gasa::IsListenServer(this); }  )); | ||||
| 		CodeFn IsNetOwner       = parse_function( code( FORCEINLINE bool         IsNetOwner()       const { return Gasa::IsNetOwner(this); }      )); | ||||
| 		CodeFn IsServer         = parse_function( code( FORCEINLINE bool         IsServer()         const { return Gasa::IsServer(this); }        )); | ||||
| 		CodeFn IsSimulatedProxy = parse_function( code( FORCEINLINE bool         IsSimulatedProxy() const { return Gasa::IsSimulatedProxy(this); } )); | ||||
| 		CodeFn NetLog = parse_function( code( | ||||
| 			FORCEINLINE void NetLog( FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log | ||||
| 				, FLogCategoryBase& Category  = LogGasaNet | ||||
| 				, bool              DumpStack = false | ||||
| 				, int32             Line      = __builtin_LINE() | ||||
| 				, const ANSICHAR*   File      = __builtin_FILE() | ||||
| 				, const ANSICHAR*   Func      = __builtin_FUNCTION() ) | ||||
| 			{ | ||||
| 				Gasa::NetLog(this, Message, Verbosity, Category, DumpStack, Line, File, Func ); | ||||
| 			} | ||||
| 		)); | ||||
| 		CodeFn ServerAuthorized = parse_function( code( FORCEINLINE bool ServerAuthorized() const { return Gasa::ServerAuthorized(this); } )); | ||||
| 	#pragma pop_macro("FORCEINLINE") | ||||
| 		net_slime_class_interface.append(GetNetworkMode); | ||||
| 		net_slime_class_interface.append(IsClient); | ||||
| 		net_slime_class_interface.append(IsListenServer); | ||||
| 		net_slime_class_interface.append(IsNetOwner); | ||||
| 		net_slime_class_interface.append(IsServer); | ||||
| 		net_slime_class_interface.append(IsSimulatedProxy); | ||||
| 		net_slime_class_interface.append(NetLog); | ||||
| 	} | ||||
|  | ||||
| 	CodeBody new_body = def_body(ECode::Class_Body); | ||||
| 	for(Code code = aclass->Body.begin(); code != aclass->Body.end(); ++ code ) | ||||
| 	{ | ||||
| 		switch (code->Type) | ||||
| 		{ | ||||
| 			default: | ||||
| 				new_body.append(code); | ||||
| 			break; | ||||
|  | ||||
| 			// TODO(Ed): Could this be turned into a singly? void find_and_swap_region_pragma(CodeClass, StrC region) | ||||
| 			// IT could return void if its assumed that the Code passed will have destructive edits to the body. | ||||
| 			case ECode::Preprocess_Pragma: | ||||
| 			{ | ||||
| 				local_persist bool found = false; | ||||
| 				if (found || ! code->Content.starts_with( txt("region NetSlime"))) | ||||
| 				{ | ||||
| 					new_body.append(code); | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				// Add pragma | ||||
| 				new_body.append(code); | ||||
| 				++ code; | ||||
|  | ||||
| 				new_body.append( def_comment( txt("NetSlime interface is generated by GasaGen/GasaGen_NetSlime.cpp"))); | ||||
| 				new_body.append(net_slime_class_interface); | ||||
|  | ||||
| 				while (code->Type != ECode::Preprocess_Pragma | ||||
| 					|| ! code->Content.starts_with(txt("endregion NetSlime"))) | ||||
| 					++ code; | ||||
|  | ||||
| 				new_body.append(code); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	aclass->Body = new_body; | ||||
| } | ||||
|  | ||||
| void gen_netslime_interfaces() | ||||
| { | ||||
| 	Array<StringCached> header_paths = Array<StringCached>::init_reserve(GlobalAllocator, 32); | ||||
| 	// header_paths.append(get_cached_string(txt( path_module_gasa     "GasaObject.h"))); | ||||
| 	// header_paths.append(get_cached_string(txt( path_gasa_actors     "GasaActor.h"))); | ||||
| 	// header_paths.append(get_cached_string(txt( path_gasa_characters "GasaCharacter.h"))); | ||||
| 	// header_paths.append(get_cached_string(txt( path_gasa_game       "GasaGameMode.h"))); | ||||
| 	// header_paths.append(get_cached_string(txt( path_gasa_game       "GasaGameState.h"))); | ||||
|  | ||||
| 	for (StringCached path : header_paths) | ||||
| 	{ | ||||
| 		CodeBody original_header = parse_file(path); | ||||
| 		CodeBody header_body     = def_body(ECode::Global_Body); | ||||
| 		for (Code code : original_header) | ||||
| 		{ | ||||
| 			switch (code->Type) { | ||||
| 			case ECode::Class: | ||||
| 			{ | ||||
| 				CodeClass aclass = code.cast<CodeClass>(); | ||||
| 				gen_netslime_interface(aclass); | ||||
| 				header_body.append(aclass); | ||||
| 			} | ||||
| 			break; | ||||
| 			default: | ||||
| 				header_body.append(code); | ||||
| 			} | ||||
| 		} | ||||
| 		Builder header = Builder::open(path); | ||||
| 		header.print(header_body); | ||||
| 		header.write(); | ||||
| 		format_file(path); | ||||
| 	} | ||||
| } | ||||
| @@ -272,6 +272,7 @@ void def_attribute_field_value_setters( CodeBody body, Array<StringCached> prope | ||||
|  | ||||
| void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array<StringCached> properties ) | ||||
| { | ||||
| 	body.append(def_pragma( txt("region Attribute Setters"))); | ||||
| 	for ( String property : properties ) | ||||
| 	{ | ||||
| 		CodeFn generated_get_attribute = parse_function( | ||||
| @@ -288,6 +289,7 @@ void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name | ||||
| 			))); | ||||
| 		body.append( generated_get_attribute ); | ||||
| 	} | ||||
| 	body.append(def_pragma( txt("endregion Attribute Setters"))); | ||||
| } | ||||
|  | ||||
| void def_attribute_field_initers ( CodeBody body, Array<StringCached> properties ) | ||||
| @@ -307,11 +309,10 @@ void def_attribute_field_initers ( CodeBody body, Array<StringCached> properties | ||||
|  | ||||
| void impl_attribute_fields( CodeBody body, StrC class_name, Array<StringCached> properties ) | ||||
| { | ||||
| 	body.append(fmt_newline); | ||||
| 	body.append(def_pragma( txt("region Rep Notifies"))); | ||||
| 	for ( String property : properties ) | ||||
| 	{ | ||||
| 		body.append(fmt_newline); | ||||
|  | ||||
| 		CodeFn field_impl = parse_function( token_fmt( | ||||
| 			"class_name", class_name, "property", (StrC)property, "from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"), | ||||
| 		stringize( | ||||
| @@ -326,6 +327,7 @@ void impl_attribute_fields( CodeBody body, StrC class_name, Array<StringCached> | ||||
| 		body.append( field_impl ); | ||||
| 	} | ||||
| 	body.append( def_pragma( txt("endregion Rep Notifies"))); | ||||
| 	body.append(fmt_newline); | ||||
| } | ||||
|  | ||||
| inline | ||||
|   | ||||
| @@ -1610,7 +1610,7 @@ void CodeConstructor::to_string_fwd( String& result ) | ||||
| 	if ( ast->InlineCmt ) | ||||
| 		result.append_fmt( "; // %S\n", ast->InlineCmt->Content ); | ||||
| 	else | ||||
| 		result.append( ";" ); | ||||
| 		result.append( ";\n" ); | ||||
| } | ||||
|  | ||||
| String CodeClass::to_string() | ||||
| @@ -6278,6 +6278,16 @@ namespace parser | ||||
| 			move_forward(); | ||||
| 			preprocess_content.Length++; | ||||
|  | ||||
| 			if ( current == '\r' && scanner[1] == '\n' ) | ||||
| 			{ | ||||
| 				move_forward(); | ||||
| 				move_forward(); | ||||
| 			} | ||||
| 			else if ( current == '\n' ) | ||||
| 			{ | ||||
| 				move_forward(); | ||||
| 			} | ||||
|  | ||||
| 			Tokens.append( preprocess_content ); | ||||
| 			return Lex_Continue;    // Skip found token, its all handled here. | ||||
| 		} | ||||
| @@ -7262,7 +7272,7 @@ namespace parser | ||||
| 		Tokens            = Array<Token>::init_reserve( LexArena, ( LexAllocator_Size - sizeof( Array<Token>::Header ) ) / sizeof( Token ) ); | ||||
|  | ||||
| 		defines_map_arena = Arena_256KB::init(); | ||||
| 		defines           = HashTable<StrC>::init( defines_map_arena ); | ||||
| 		defines           = HashTable<StrC>::init_reserve( defines_map_arena, 256 ); | ||||
| 	} | ||||
|  | ||||
| 	internal void deinit() | ||||
|   | ||||
| @@ -1663,7 +1663,7 @@ struct Array | ||||
| 	{ | ||||
| 		Header& header = *get_header(); | ||||
|  | ||||
| 		if ( begin < 0 || end >= header.Num ) | ||||
| 		if ( begin < 0 || end > header.Num ) | ||||
| 			return false; | ||||
|  | ||||
| 		for ( sw idx = begin; idx < end; idx++ ) | ||||
| @@ -1820,13 +1820,11 @@ struct HashTable | ||||
| 		Type Value; | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr f32 CriticalLoadScale = 0.7f; | ||||
|  | ||||
| 	static HashTable init( AllocatorInfo allocator ) | ||||
| 	{ | ||||
| 		HashTable<Type> result = { { nullptr }, { nullptr } }; | ||||
|  | ||||
| 		result.Hashes          = Array<sw>::init( allocator ); | ||||
| 		result.Entries         = Array<Entry>::init( allocator ); | ||||
|  | ||||
| 		HashTable<Type> result = init_reserve(allocator, 8); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| @@ -1834,21 +1832,19 @@ struct HashTable | ||||
| 	{ | ||||
| 		HashTable<Type> result          = { { nullptr }, { nullptr } }; | ||||
|  | ||||
| 		result.Hashes                   = Array<sw>::init_reserve( allocator, num ); | ||||
| 		result.Hashes = Array<sw>::init_reserve( allocator, num ); | ||||
| 		result.Hashes.get_header()->Num = num; | ||||
| 		result.Hashes.resize( num ); | ||||
| 		result.Hashes.fill( 0, num, -1); | ||||
|  | ||||
| 		result.Entries                  = Array<Entry>::init_reserve( allocator, num ); | ||||
|  | ||||
| 		result.Entries = Array<Entry>::init_reserve( allocator, num ); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	void clear( void ) | ||||
| 	{ | ||||
| 		for ( sw idx = 0; idx < Hashes.num(); idx++ ) | ||||
| 			Hashes[idx] = -1; | ||||
|  | ||||
| 		Hashes.clear(); | ||||
| 		Entries.clear(); | ||||
| 		Hashes.fill( 0, Hashes.num(), -1); | ||||
| 	} | ||||
|  | ||||
| 	void destroy( void ) | ||||
| @@ -1901,32 +1897,19 @@ struct HashTable | ||||
|  | ||||
| 	void rehash( sw new_num ) | ||||
| 	{ | ||||
| 		sw idx; | ||||
| 		sw last_added_index; | ||||
|  | ||||
| 		HashTable<Type> new_ht         = init_reserve( Hashes.get_header()->Allocator, new_num ); | ||||
|  | ||||
| 		Array<sw>::Header* hash_header = new_ht.Hashes.get_header(); | ||||
|  | ||||
| 		for ( idx = 0; idx < new_ht.Hashes.num(); ++idx ) | ||||
| 			new_ht.Hashes[idx] = -1; | ||||
|  | ||||
| 		for ( idx = 0; idx < Entries.num(); ++idx ) | ||||
| 		HashTable<Type> new_ht = init_reserve( Hashes.get_header()->Allocator, new_num ); | ||||
| 		for ( sw idx = 0; idx < Entries.num(); ++idx ) | ||||
| 		{ | ||||
| 			Entry& entry = Entries[idx]; | ||||
|  | ||||
| 			FindResult find_result; | ||||
|  | ||||
| 			if ( new_ht.Hashes.num() == 0 ) | ||||
| 				new_ht.grow(); | ||||
|  | ||||
| 			entry            = Entries[idx]; | ||||
| 			Entry& entry     = Entries[idx]; | ||||
| 			find_result      = new_ht.find( entry.Key ); | ||||
| 			last_added_index = new_ht.add_entry( entry.Key ); | ||||
|  | ||||
| 			if ( find_result.PrevIndex < 0 ) | ||||
| 				new_ht.Hashes[find_result.HashIndex] = last_added_index; | ||||
|  | ||||
| 			else | ||||
| 				new_ht.Entries[find_result.PrevIndex].Next = last_added_index; | ||||
|  | ||||
| @@ -1984,11 +1967,10 @@ struct HashTable | ||||
| 		sw         idx; | ||||
| 		FindResult find_result; | ||||
|  | ||||
| 		if ( Hashes.num() == 0 ) | ||||
| 		if ( full() ) | ||||
| 			grow(); | ||||
|  | ||||
| 		find_result = find( key ); | ||||
|  | ||||
| 		if ( find_result.EntryIndex >= 0 ) | ||||
| 		{ | ||||
| 			idx = find_result.EntryIndex; | ||||
| @@ -2060,7 +2042,9 @@ protected: | ||||
|  | ||||
| 	b32 full() | ||||
| 	{ | ||||
| 		return 0.75f * Hashes.num() < Entries.num(); | ||||
| 		uw critical_load = uw( CriticalLoadScale * f32(Hashes.num()) ); | ||||
| 		b32 result = Entries.num() > critical_load; | ||||
| 		return result; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| @@ -2096,7 +2080,7 @@ struct StrC | ||||
| #define txt( text )              \ | ||||
| 	StrC                         \ | ||||
| 	{                            \ | ||||
| 		sizeof( text ) - 1, text \ | ||||
| 		sizeof( (text) ) - 1, (text) \ | ||||
| 	} | ||||
|  | ||||
| StrC to_str( char const* str ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user