Check out Half-Life Re-imagined competition results!
Check out Skewing textures in Hammer, our newest tutorial!
Welcome, Jongmeister, our newest member!

logo

Site Stuff

Reference

Maps

Community

ShoutBOX

Poll

Feeling Blue

What's your favourite shade of blue?

Azure

21

Cobalt

37

Turquoise

11

Cyan

17

Royal

11

Teal

3

Onliners

11 mins

ZikShadow

38 mins

Windawz

52 mins

Admer456

55 mins

Jessie

1 hours

Soup Miner

1 hours

Penguinboy

1 hours

lukkasz323

Affiliates

A gaming and technology blog by TWHL admins Penguinboy and Ant. A music blog by TWHL users Ant and Hugh.

SharpLife - Dot Net Core based modding p

[1]

Forums > HL Engine Discussion

06 May 18, 20:15
By Solokiller
avatar
Member
I've been doing some research on porting Half-Life to C# using the Dot Net Core framework. I've got a working prototype that has C# code that can interface with the engine, though it's still far from complete.

I'm calling this SharpLife, since it's implemented using C#. It isn't limited to that language since it uses Dot Net but that is what i'm working with.

The goal is to port the SDK to C# and then upgrade it with Half-Life Enhanced's bug fixes and additions. Once that's done i can complete the planned changes for that.

Here's a diagram showing the overall design of the framework itself:


Here are some examples of how it's easier to work with C# than C++:

Quote:

//Save restoring a field in a class in the SDK:
CBaseEntity* m_pGoalEnt;

static TYPEDESCRIPTION m_SaveData[];

TYPEDESCRIPTION CBaseEntity::m_SaveData[] =
{
DEFINE_FIELD( CBaseEntity, m_pGoalEnt, FIELD_CLASSPTR )
};

//Save restoring a field in a class in C#:
[Persist]
public CBaseEntity m_pGoalEnt;


Quote:

//Getting the name of a class in the SDK:
const char* pszClassName = STRING( pEntity->pev->classname );

//Getting the name of a class in C#:
var className = pEntity.ClassName;


Quote:

//Loading an XML file in HLEnhanced:
https://github.com/SamVanheer/HLEnhanced/bl
ob/346a9889f7da589f72cc66a71ee1202fc43471
4a/game/shared/CWeaponInfoCache.cpp#L154


//Loading an XML file in C#:
try
{
using (var stream = new FileStream("SharpLife/cfg/SharpLife-Wrapper
-Managed.xml", FileMode.Open))
{
var serializer = new XmlSerializer(typeof(ServerWrapperConfigura
tion));

var config = (ServerWrapperConfiguration)serializer.Dese
rialize(stream);

LoadMod(config.ModInfo);

return true;
}
}
catch(Exception e)
{
Log.Message($"{e.GetType().Name} - {e.Message}");
Log.Message(e.StackTrace);
return false;
}


It's much easier to manage dependencies than in C++ as well. To use XercesC in HLE you need to download, extract, compile and install it before referencing it in your CMake configuration.

In C# you only need to reference the NuGet package System.Xml.XmlSerializer. Once that's done everybody who checks out the codebase will be able to get the packages by restoring all NuGet packages for the solution.

For less experienced programmers (most modders) the language is easier to use as well. One mistake i've seen made a lot is string comparisons:

Quote:

const char* somestring = ...;

if("ON" == somestring )
{
//Do something if ON
}


This compares memory addresses, which will always be false.

In C# it works like it does in most modern languages:
Quote:

string somestring = ...;

if( "ON" == somestring )
{
//Do something if ON
}


And it does what you'd expect.

For scripting there's no need for Angelscript because you can just load assemblies that can directly access mod code. A simple plugin system would be a list of Dot Net assemblies that are loaded on mod startup that then behave as though they were part of the mod itself.

The language is very similar to Angelscript which is intentional, since Angelscript is based off of both C# and C++.

In addition, there's a scripting language called CSharpScript that is essentially C# code compiled at runtime, much like Angelscript: https://github.com/dotnet/roslyn/wiki/Scrip
ting-API-Samples


By moving to this it'll be easier and faster to continue development, modders can focus on implementing game logic instead of working around language limitations and quirks.

It will take some time to implement, but right now the biggest issue is getting the native<->managed code interop working. I have the necessarily functionality done for that, so it's just getting the interfaces for the server done, then re-implementing everything piece by piece.

The priority is making sure the game can load and run with a minimal codebase, so most entities won't work yet for some time.

I'm hoping once that's done i can implement the physics code re-implementation, which will allow for parenting, and then if i have time and motivation implementing a new networking system to transfer data to clients. The client itself will also need to be converted, but it's a bit smaller than the server so that should be simpler.

Best case scenario i can skip the engine entirely and just do everything in C#, which would really make things easy but that's a lot of work and i don't know if i'll still have time and motivation for that.
07 May 18, 00:10
By Rimrook
avatar
Guru
Wow. Hope this works out epically.
07 May 18, 01:07
By tschumann
avatar
Member
Nice - this is something that I've wondered about for a while.
I guess it's possible but apparently not without its challenges.
07 May 18, 03:18
By twitch1
avatar
Member
Yeah, very cool!
08 May 18, 12:18
By Instant Mix
avatar
Title commitment issues
Putting anything to do with Half life into a C# environment gets a big ol' thumbs up from me. Very happy to see C# get popular, Facepunch are doing a "gmod 2" by putting a layer of C# over UE4 for ease of use purposes. Would be great to see!
10 May 18, 09:44
By SourceSkyBoxer
avatar
Member
Aha why do you not say me before C# is bad now you tried. I don't believe that. James said me I shouldn't use C#. Now Solokiller made it. And what are you using libraries?

MonoGame, OpenTK, OpenGL.net or SharpGL?

But it is really bad news: cry - :cry:

Because I have already tried to use wavefront but wavefront looks for latest OpenTK damaged like you have used bad brush in Valve Hammer Editor with unlimited error-face.

Example my result of CrazyCore:


For SharpGL works fine with wavefront files but it looks common incompatible for latest display cards.

You can't fix for mdl / smd because it has high calculation of vertices, normals, texturecoords, faces and indices...

If you have success. I will see your work - if you have luck.
10 May 18, 10:10
By tschumann
avatar
Member
It looks like it's just the client and server code being ported - not the engine, so I imagine it's just plain old C# and the .Net standard library mostly.
10 May 18, 10:27
By Solokiller
avatar
Member
I'm only using Dot Net Core with compatible libraries, and native interop to run under the engine. I do want to eventually implement engine code in managed code to skip the engine entirely but that's not going to happen any time soon.
10 May 18, 12:34
By SourceSkyBoxer
avatar
Member
Good for you - I will see if you have goal with models. I think you need assimp net ( it is old but it can't work for Dotnet Core 2.x :/ I saw assimpNet is still outdated.

Why do we need assimp? because it is important for loading unsupported model format example mdl of Half-Life or Quake 1/2/3 .

I think you need write via Dllimport with assimp.dll ( x86 / x64 ) into DotNet Core 2.x.

Good luck for next release!
11 May 18, 09:22
By Loulimi
avatar
Member
I'm surprised C++ is so verbose and isn't equipped with a dependency manager.

I understand it's less verbose, easier to manage dependencies, and run on all platforms without recompiling. I hope it's not too much off topic, but why C# specifically? smile - :) For instance, why not Java? (I'm just curious :p)
11 May 18, 10:17
By Solokiller
avatar
Member
I can just write unsafe code to access model data, worst case scenario i can write my own loader and do what i've done in C++ before. It's not that hard.

Here's what i did to access edict_t: https://pastebin.com/DQ1qeXus

I haven't been able to test it yet, but it should work. This lets me access the native data while still using managed code in the game itself.

C++ actually does have a dependency manager, but as with most things C++ it's new and not terribly widely used yet: https://blogs.msdn.microsoft.com/vcblog/201
8/04/24/announcing-a-single-c-library-man
ager-for-linux-macos-and-windows-vcpkg/


Even so it's still not easy to add dependencies, you still need CMake and old projects like GoldSource aren't built for it so you need ugly hacks to make it work.

I chose C# because it's the best tool for the job. The language itself is very easy to use and lets you design simple interfaces, like you can make a property that returns a string that internally could do a lot of work without exposing that detail. In Java you'd need a method for that.

You could do this:
Quote:

//In BaseEntity
[Persist]
public string ClassName => pev.ClassName;

//In entvars_t
//Data is a pointer to the native entvars_t instance
//ToString accesses the string pool containing native string data
public string ClassName => Data->classname.ToString();


If i can ever get the engine out of the equation that can be simplified to:
Quote:

[Persist]
public string ClassName { get; private set; }


In Java you can't do that. They've been playing catch-up to C# for a few years now, but C# is definitely the better language and the tooling support (Visual Studio) is much better than Eclipse/IntelliJ.

Native interop in Java isn't nearly as powerful as it is in C#. I read that they're planning to implement C++/CLI like support in Dot Net Core sometime, so perhaps next year i can simplify the interface even more by writing the native access in C++ instead. That would make things even easier, though by that time i may already have made the native parts obsolete.

That part's a bit tough, since there's a lot of engine code that accesses entvars_t and edict_t. There's 57 known accesses to entvars_t members that represent strings (string_t), the majority of which are classname checks.

Those can be avoided by handling entity creation entirely in managed code, since these calls are part of map spawning, entity creation, etc. If you override specific engine functions using the Detour framework then you can handle this directly in managed code.

If i can do that, and unregister certain console commands the engine won't touch it anymore. Eventually the idea is to not let the engine do anything, at which point the native interface would go away and the managed version would have its own implementation, or would be removed (edict_t and entvars_t really have to go).

I'm designing the game interface to make sense and be sane so most code wouldn't need updating. Direct access to edict_t and entvars_t would be handled in properties in common entity base classes (see example above), making the switchover easy and painless.

edict_t would probably be re-purposed to do what it does in Source, which is to store networking data and provide a way to represent players before their class instance is created (which i can fix if i have control over those particular engine functions).

If i can get this all done i can implement that custom networking i've talked about, which would let me implement uniform entity networking. It would look much like the persistence example:
Quote:

[Networked]
public float Health { get; set; }


Should this not work and a notify-on-change type be needed, it wouldn't change the public interface:
Quote:

[Networked]
private Networked<float> NetHealth { get; } = new Networked<float>(0);

public float Health
{
get => NetHealth.Value;
set => NetHealth.Value = value;
}


All Networked instances in an entity would be hooked up to notify their owning entity so it can track the changes and network them at the next opportunity.

That would mean networked entities would exist on both the client and server side, could network any amount and type of variables and probably not cause reliable channel overflows anymore. cl_entity_t wouldn't exist anymore, the hacky weapon prediction system would be integrated into the rest of the system and we could actually build some neat things without worrying about engine limits.

Unfortunately this is all a lot of work and i have to finish up the native<->managed interface first, then port the entire server and then make the client version of all this. I can probably speed the client conversion up by writing a code generator for the interfaces, since it's largely the same thing over and over.

I'd still have to write a new GUI library either way since interfacing with VGUI(2) is not an option here. Any OpenGL based library should do here, as long as i can take the result and put it where VGUI goes it'll work, but there aren't many for Dot Net Core right now. I should be able to use the VGUI2 interfaces to render directly to the engine here though.

As far as content development goes, things should be a lot easier for you. I can implement a plugin system that loads assemblies that reference the mod, letting you access the game's code directly so you could add new weapons that way.
That is probably one of the biggest problems with Sven Co-op's scripting system, and one people have asked me about a lot, so i'm happy that this problem is now solved.

If i can implement the server<->client bridge i could add a debug UI that can directly access the server to take care of things that would otherwise be done through restrictive console commands. More expansive AI and scripting debugging would certainly help.

It's a bit too early to go into details about that, but i'm hopeful that this will let me finish the planned features for HLE and beyond.
11 May 18, 11:20
By SourceSkyBoxer
avatar
Member
@SoloKiller, No, Java can work more than C#. I cancelled C# programming because I have tried since March 2018. No success SharpGL, Neo Kabuto's volume obj and other different ways. = No success.
My results: I really want create cube in C# but I want load from obj without material.

It is using from Vector3 from OpenTK ( latest development myget )

It is painful if I want load obj. It looks bad for C#.

I have made lessons / tutorials but I am very despairing. I have more ways like C++ and ThinMatrix's tutorial series with lwjgl ( Java )

Java is richer than C# because C# is poor like example Math class

ToRadiant(float angle) hasn't in Math of C#.

Java has more Math methods but I saw like example Quake and Half-Life works fine 100 % in Java with LWJGL 3.1.6/3.1.7 and it has collision but you need create own so close wavefront ore different formats.

Example FloatBuffer, IntegerBuffer etc... has not for C# and has for only Java.

C# is sensitive for only Vector3[] or Vector2[] - maybe it can't show if it doesn't know Vector3, Vector2 or float. It has sometimes problem.
Java can work whatever same to float[], Vector3f[] or Vector2f[]... = No problem.

Example:

You want load and read wavefront in Half-Life with C# but you forget. C# can't

Java works fine almost than C#.
Example: Lwjgl by ThinMatrix: Video

That is reason - Why I cancel C# programming? Because C# can't work for wavefront and other formats.

I wish you have to start with Java because Java is powerful since initial Quake 2 in lwJake2 with Lwjgl 2.9.3 initial test. I have downloaded and compiled and I have tried and it works fine like C++. Java =/= C++ and C# < C++ or C# < Java. But if you make sphere like small faces than LwJake2 crashed since I have tested with JackHammer and LwJake2

Check LwJake2

And it was initial test

That is proof. I don't see lwjgl 3.1.x ( latest version ) because it is very stable for games no lagging or no crashing.
11 May 18, 13:07
By Solokiller
avatar
Member
If you're having issues loading data or rendering it then it's not caused by the language, that's the library you're using or the code you've written. I've had issues with that in C++ as well, it doesn't make C++ crap.

Java's way worse than C#. I've worked with it for years and it is missing a lot that C# has, and i wouldn't use it for something like this. C# has much better native code support than Java which by itself is already a reason to use it here because i need to do a ton of marshalling and native code access.

Package management is pretty much automatic in C#, whereas Java doesn't have that. I wouldn't want people to juggle dependencies all the time, which is a problem that HLE is suffering from due to the CMake based approach requiring a lot of manual building of dependencies.

My college is even switching their courses from Java to C# because it's much better and easier to teach and use.
11 May 18, 14:40
By SourceSkyBoxer
avatar
Member
Okay your decision with C# I hope you have to prepare OpenGL-Wrapper like OpenTK ,OpenGL.net etc...

Good luck! Headcrab Basher - :crowbar:
12 May 18, 17:59
By Striker
avatar
Member
Like... I'm struggling to learn and and apply a programming language (currently mainly using Java) to make a living, and many times I feel like an impostor.

But after seeing this...


*goes out for a walk Escobar style
12 May 18, 20:54
By Shepard62700FR
avatar
Member
Java and C# are MOSTLY similar when it comes to the syntax, the main differences are the keywords ("final" -> "const", "package" -> "namespace"...) and other minor things. The transition from Java to C# should be fairly easy.
15 May 18, 17:52
By Solokiller
avatar
Member
Quote:

Okay your decision with C# I hope you have to prepare OpenGL-Wrapper like OpenTK ,OpenGL.net etc...

Good luck! Headcrab Basher - Headcrab Basher - :crowbar:


I won't have to touch OpenGL for some time, there seem to be half a dozen libraries available so i'll take a look when it's time to work on it.

Quote:

Like... I'm struggling to learn and and apply a programming language (currently mainly using Java) to make a living, and many times I feel like an impostor.

But after seeing this...


This is really advanced stuff that most programmers will never have to do, so don't be discouraged by it.

Quote:

Java and C# are MOSTLY similar when it comes to the syntax, the main differences are the keywords ("final" -> "const", "package" -> "namespace"...) and other minor things. The transition from Java to C# should be fairly easy.


C# can do anything that Java can do, but Java can't do everything that C# can do.

Events, properties, directly calling delegates from native code, Java either can't do it or is much worse at it. I'd much rather be using C# than Java if i had a choice.

I've implemented the Detour framework so i can improve performance in some areas. Entity creation was really slow so i hooked it and re-implemented it in managed code. Mods can now control the entire process, it allows the creation of templates that can be spawned with a point_template like entity.

This means there is no maximum length limit on keys and values, no limit to the number of keyvalues that an entity can have and no limit to how many entities are defined in a map, although the engine's limit still applies during map spawn time.

I've also implemented support for linking classes to their map name, handling multiple names (some weapons need this), and partial support for keyvalues declared as properties, fields or methods.

I'll be implementing engine functions so i can implement the game interface, which will allow networking and such to work. Then i can implement some entities so maps work and i can see what else i need to implement before it's functional.

I'll probably need to detour more engine functions for performance reasons, which means physics will be re-implemented in managed code as well eventually. That also means parenting support.

Saved games will also need to be detoured to avoid problems with saved games being too big since the maximum size is hard-coded, which will allow the game to control all of the data being saved.

I'll get all of this stuff on Github soon so i can show the code. It's not ready for use yet and the framework seems to be triggering Windows Defender in a way that causes it to use up to 6 GB of memory at times. I don't know why this happens but it may be because it detects a custom CLR host.

It also seems to be causing crashes on startup (before my code is even loaded) so i'll have to figure out how to prevent this before it can be released.
17 May 18, 19:51
By Rimrook
avatar
Guru
Once upon a midnight dreary there was 8-bit. It was invented of the technological limitations of its day. As technology grew more powerful and advanced, so did everything around it. Graphics changed and polycounts increased 20% by the year. Yet the diehards stay behind and give their favorite titles the love they deserve before they get buried in the sands of progress.

Along comes the indie developer. Mr. Indie doesn’t have the tools, talent, processing power, or even the man power to compete with AAA title quality. He lives by the only rule he knows; do what you can, with what you have, right here, right now. And thus he studies his 8-bit ancestry. There is a fundamental difference between then and now as he creates his game. He has better tools and far more computing power than his ancestors. With this, he creates with less limits, so his game naturally has less technical limits. He doesn’t have to consider palettes, or color count, z-fighting, or fitting his game into a 2mb cartridge. Out of a lack of necessity, a new style had been created, this is high-bit.

It is time we see what we can do with goldsource with better tools, better computers, and without limits. It’s come a long way so far, and it still has a long way to go. Let’s high-bit this bitch.
[1]

Forums > HL Engine Discussion

Login to Reply

You must be logged in to reply.