Cover image of Changes and Improvements for Scripting in 1.1

Changes in Workbench Script Editor

Introduction of Split View.

The Workbench Script Editor now allows for using two views within the editor, allowing you to edit two script files simultaneously. It is possible to accumulate multiple tabs on each view and organize them accordingly.

TIP: This can be very useful in cases where a class is being modded or extended.

Script Debugger Now Reconnects

The Workbench Script Editor Debugger had the issue that whenever the target host for debugging was changed, it would not connect to anything anymore, meaning no more debugging capabilities were possible until Workbench was restarted. This now has been fixed, meaning that you can switch from the debugging server environment to the client environment or the Workbench environment and many more without issues.

Script Debugger now only works with Special Executables

Arma Reforger Workbench now boasts the capabilities to be connected to new special versions of the game client and server executables, you will be able to debug not only Arma Reforger Workbench Game and/or Peer Tool but also proper client and server environments.

The executables that provide this functionality are suffixed by "Diag" on their file name, making it clear to understand what executables are compatible for debugging capabilities. Trying to connect workbench debugging tools into a non-Diag executable is not possible, and non-Diag executables cannot connect to Diag environments, meaning that a non-Diag client cannot connect to a Diag server, and non-Diag executables cannot connect to Workbench debugging tools.

Renamed executables:

  • ArmaReforgerWorkbenchSteam.exe is now ArmaReforgerWorkbenchSteamDiag.exe.

New executables

  • ArmaReforgerSteamDiag.exe which is the same as ArmaReforgerSteam.exe but with debugging capabilities.

  • ArmaReforgerServerDiag.exe which is the same as ArmaReforgerServer.exe but with debugging capabilities.

    • This affects Windows server environment.

    • This affects Linux server environment.

This means that Peer Tool can't be used with ArmaReforgerSteam.exe anymore; instead, ArmaReforgerSteamDiag.exe has to be used.
The Diag executables not only provide the ability to connect Arma Reforger Workbench to them but also provide the ability to use all the developer options for the game that you can find in the Arma Reforger Workbench internal game, meaning that the Diag menu and other tools are active on Diag executables.

Documentation for the Diag menu can be found here:
Arma Reforger:Diag Menu - Bohemia Interactive Community (bistudio.com)

Documentation for the usage of Diag executables can be found here:
https://community.bistudio.com/wiki/Arma_Reforger:Development_Executables


Changes in the Enforce Script Language

Errors on Incorrect Usage of Ref Keyword

The Enforce Script Compiler now throws errors on incorrect usage of the ref keyword.

Incorrect usage of the ref keyword can produce memory leaks and unspecified behavior across the entire enforce script VM, which can affect not only your mod but also other mods and the game itself. To combat these, certain compiler errors have been introduced.

As a quick refresher, the ref keyword works in the following way:

The Enforce script language boasts two types of classes: a Managed and Class class. A class that inherits from Class will have to be completely memory managed in a manual manner by the developer/modder, meaning that the lifetime of the instances created of such class should be manually managed (For example, manually calling delete on the instance for destroying it), On the other hand, a class that inherits from Managed would provide automatic memory management utilities for handling the lifecycle of instances of a class that inherits from Managed. These utilities come in the form of weak and strong references; they are basically smart pointers in C++ (unique_ptr and shared_ptr, respectively). A strong reference would be defined by prefixing in the definition of a variable the keyword ref on the type, or on the type of a template argument. On the other hand, a weak reference would be simply defined by not providing the ref keyword at all. Usage of the ref keyword is only ever valid when used inside a template argument or the body of a class but never in any part of a method signature of its body.

A strong reference will wrap the instance assigned to it in an object that will keep track of in how many other places it has been strong referenced. when the scope of a variable that held a strong reference to the instance is ended, it will decrease such count by 1, and inversely the count will increase by 1 when a strong reference variable has got the instance assigned. Weak references will not increase nor decrease this count, they will weakly represent the instance and will become null when the instance's wrapper count has reached 0.  

Note: Except for the GameLib and Core script modules, all classes, unless specifically inheriting from Class, are implicitly inheriting from Managed.

Correct usages of the ref keyword:

All the kinds of ref usage in the following example are valid.

class SomeClass
{
	ref AnotherClass variableName_1 = new AnotherClass();
	AnotherClass variableName_2;
	ref array<ref AnotherClass> variableName_3;
	ref array<AnotherClass> variableName_4;

	AnotherClass MethodName_1(AnotherClass instance)
	{
		return instance;
	}

	array<ref AnotherClass> MethodName_2(array<ref AnotherClass> instance)
	{
		return instance;
	} 
}

Incorrect usages of the ref keyword:

All the kinds of ref usage in the following example are invalid.

class SomeClass
{
	ref AnotherClass MethodName_1(ref AnotherClass instance)
	{
		// Be careful that only ref used like this on the left side of a variable definition is invalid only in method bodies.
		ref AnotherClass internalInstance = new ref AnotherClass();
		
		return instance;
	}
}

Introduction of Modability of Private Methods

Accessing and overriding private methods within a modded class is now possible.

Modding a class behaves similarly to extending a class, with the difference that a class would inherit from itself or the previously modded version of itself instead of inheriting from another class. In this case, the keyword super would point to the last modded version of the class or the class itself. So, it is to expect that private methods from the class could also be accessible or overridden,

Introduction of the Vanilla Keyword

Sometimes when modding a class, a requirement for calling specifically the original implementation of the method being modified is wanted. In other words this means to have the ability to be able to call the logic that was defined on the original definition of the method being modded. This contrasts with the super keyword, given that vanilla does not check parent or previous modded class implementations at all.

Example usage:

// Original implementation.
class ClassA
{
	void Method()
	{
		Print("First");
	}
}

// Modded implementation with super.
modded class ClassA
{
	override void Method()
	{
		super.Method();
		Print("Second");
	}
}

// Modded implementation with vanilla.
modded class ClassA
{
	override void Method()
	{
		vanilla.Method();
		Print("Third");
	}
}

// Modded implementation with super.
modded class ClassA
{
	override void Method()
	{
		super.Method();
		Print("Fourth");
	}
}

Now when the method is called, it will print the following:

First
Third
Fourth

Notice how it ignored the second print. This is because on the 2nd override through the modded class, vanilla was used instead of super, causing all previous implementations, with the exception of the original one, to not be called as super was not used anywhere else on that override. However, notice how on the 3rd override super was used, but only the 2nd override was called because of super.

Introduction of the Vanilla and Super Keyword to Static Methods

Static methods can now reference past implementations due to the ability to use super and vanilla keywords. These keywords behave the same way as normal methods in static methods.

This was particularly a problem that completely blocked modding of custom replication of complex data types given that the replication of these were defined through static methods, meaning that if a custom replicated class were to be modified, the complete set of said static methods would need to be complete replaced, instead of the ability to extend/modify them. Causing issues such as only one mod being able to do so, causing conflicts with game updates among other issues.

Example:

class SomeClass
{
	static void MethodName_1()
	{
	}
}

modded class SomeClass
{
	override static void MethodName_1()
	{
		// Valid.
		super.MethodName_1();
		// Valid.
		vanilla.MethodName_1();
	}
}

Introduction of Basic Inlining of Methods

The Enforce Script Compiler is now capable of inlining methods if specific conditions are met. 

The conditions are:

  • Class or method must be sealed.

  • The method body can only have a return statement.

Note: After processing and merging modded scripts, all classes in the Game module will be sealed so that this optimization can be performed in mass.


Changes in the Enforce Script Libraries

ScriptInvoker now Automatically Deletes Null Instances for Function Invocation

The ScriptInvoker now removes automatically registered functions that come from null instances when performing an invoke call on it. 

Previously, the ScriptInvoker would not automatically delete functions that came from destroyed instances, so the functions had to be manually unregistered at the correct time for each instance.

TagSystem and TagComponent now Allow for Custom Tag Categories

TagSystem is a game system that provides the ability to perform automated spatial indexing, meaning that it provides an API for being able to query things around the world. It does this through the usage of a grid map, where the entities get registered either manually through the API in TagSystem or by the existence of TagComponent on a desired entity. the TagSystem allows discriminating these entities by tag categories, which can be used to quickly filter categorized entities and speed up the query and update process. The category of an entity is defined through its TagComponent, and custom categories can now be created by modding the enum ETagCategory

Note: The ETagCategory is used as a flag/mask enum, meaning that values to be defined for individual tag categories must be powers of 2, which limits the number of tag categories to a maximum of 32.

Example of adding a new tag category:

modded enum ETagCategory
{
	MyCustomTag = 32
}

Introduction of Specialized Grid Map

Multiple Grid Map structures have been introduced, these structures allow you to perform spatial indexing in a manual manner, providing a more customizable method of performing queries of volumes in space. 

Multiple types of Grid Maps were introduced, which are: 

  • AABGridMap

  • CircleGridMap

  • PointGridMap

Published on 

We want you for our mailing list!

We offer great content once a month just for you!