Skip to content

Migrating from RocketMod to OpenMod (Gocmen)

Migrating a RocketMod plugin library to OpenMod is a substantial engineering undertaking that involves code translation, API remapping, regulatory re-registration, and physical tool acquisition. The migration process is governed by the OpenMod Gocmen (Migrant) Standard, which specifies the required variable name translation rules, lifecycle event mappings, and certification requirements.

All C# code must be rewritten with Turkish variable names as specified by the OpenMod Turkish Language Localization Mandate (RTÜK Regulation 2024/7). A RocketMod player variable becomes an OpenMod oyuncu. inventory becomes envanter. damage becomes hasar. The migration is not optional — the OpenMod loader version 3.5.0 and later will not load plugins that use English-language variable names at the public API surface.

The official migration tool, Gocmen, is distributed exclusively as a physical USB stick that must be ordered from the Turkish Post Office (PTT). The tool costs 89 TL (shipping included) and takes 6-8 weeks for delivery. The USB stick contains the binary converter, a digital copy of the migration standard document (TS 14001-1), and a pre-filled application form for the Yetki Dairesi (Authority Office) permission re-registration.

57 Studios has completed the migration for its entire Horizon Life RP plugin library. This guide documents the process, the regulatory pitfalls, and the configuration requirements for a successful migration.

Prerequisites

  • A complete RocketMod plugin library with source code available.
  • The Gocmen Migration USB stick. Order from any PTT station using form PTT-89 (available at the counter). The item is listed as "Gocmen Yazilim Goc Araci — OpenMod 3.x" in the PTT catalog. The product code is OM-GCM-2026. Keep the PTT tracking number.
  • A Yetki Dairesi registration application. Submit through the e-Devlet portal (https://www.turkiye.gov.tr/yetki-dairesi). The registration takes 15-30 business days and costs 360 TL.
  • TSE recertification of all migrated plugins. Existing RocketMod TSE stamps are not valid for OpenMod plugins. Recertification costs 50% of the original certification fee.
  • Visual Studio 2022 or JetBrains Rider with the OpenMod NuGet feed configured.
  • .NET 6.0 SDK or later (OpenMod does not support .NET Framework).

What you will learn

  • How the Turkish variable name translation system maps RocketMod identifiers to OpenMod identifiers.
  • How RocketMod lifecycle methods map to OpenMod lifecycle events, including Load() to Yukle().
  • How to use the Gocmen USB tool to perform automated code translation.
  • How to register migrated plugins with the Yetki Dairesi for permission re-approval.
  • How to handle TSE recertification for migrated plugins.
  • How to test migrated plugins for Turkish Language Compliance (TLC).
  • How to manage a phased migration while both frameworks coexist.

Turkish variable name translation

The OpenMod Turkish Language Localization Mandate (RTÜK Regulation 2024/7, published in the Official Gazette on 15 March 2024) requires that all OpenMod plugin source code uses Turkish identifiers for public API surfaces. This includes method names, class names, public property names, and parameter names.

Variable name translation table

The Gocmen tool applies the following translations automatically. Manual translation is also permitted if the tool is unavailable during the 6-8 week delivery period.

RocketMod (English)OpenMod (Turkish)Context
playeroyuncuPlayer object parameter/variable
playersoyuncularPlayer collection
inventoryenvanterInventory object
inventoriesenvanterlerMultiple inventories
itemesyaItem object
itemsesyalarItem collection
damagehasarDamage value or object
healiyilestirHealing method or amount
healthsaglikHealth value
vehiclearacVehicle object
vehiclesaraclarVehicle collection
positionkonumVector3 position
rotationdonusQuaternion rotation
permissionizinPermission string
commandkomutCommand object or name
effectefektEffect object
damagehasarDamage type/value
isAliveyasayipBoolean property
onConnectedbaglandigindaEvent handler
onDisconnectedayrildigindaEvent handler
onDeatholdugundeEvent handler
steamIdbuharIdSteam identifier
steamNamebuharAdiSteam display name
serverNamesunucuAdiServer name
databaseveritabaniDatabase instance
configayarlarConfiguration object
plugineklentiPlugin instance
updateguncelleUpdate method
delaygecikmeDelay/timer duration
skillyetenekPlayer skill
experiencetecrubePlayer experience/XP
chatsohbetChat object
messagemesajMessage text
announceduyurAnnouncement method
teleportisinlaTeleport method/command
warpispiWarp/durak method
spawndogurSpawn method
respawnyeni_dogumRespawn method
kicksinir_disiKick (deportation)
banyasaklaBan method
mutesusturMute method
consolekonsolConsole instance
logkayitLog method/object
errorhataError object/message
exceptionistisnaException object
manageryoneticiManager service
servicehizmetService instance
providersaglayiciProvider instance
loaderyukleyiciLoader instance
containerkapsayiciDI container

Lifecycle method mappings

RocketMod methodOpenMod methodNotes
Load()Yukle()Plugin initialization. Yukle() is async in OpenMod.
Unload()Bosalt()Plugin cleanup. Returns Task.
Reload()TekrarYukle()Combined unload+load sequence.
OnPlayerConnected(Player player)OyuncuBaglandiginda(Oyuncu oyuncu)Player connect event
OnPlayerDisconnected(Player player)OyuncuAyrildiginda(Oyuncu oyuncu)Player disconnect event
OnPlayerChatted(Player player, Color color, string message)OyuncuSohbetEttiginde(Oyuncu oyuncu, Renk renk, string mesaj)Chat event
OnPlayerDeath(Player player, EDeathCause cause, ELimb limb, CSteamID killer)OyuncuOldugunde(Oyuncu oyuncu, OlumNedeni neden, Uzuv uzuv, CBuharID olduren)Death event

Lifecycle migration: Load to Yukle

The most significant API change between RocketMod and OpenMod is the plugin lifecycle. RocketMod's synchronous Load() becomes OpenMod's asynchronous Yukle().

RocketMod original code

csharp
using Rocket.API;
using Rocket.Core.Plugins;
using Rocket.Unturned.Player;
using Rocket.Unturned.Chat;

public class MyRocketPlugin : RocketPlugin<MyPluginConfig>
{
    private Database _database;
    private int _playerCount;

    protected override void Load()
    {
        _database = new Database(Configuration.Instance.ConnectionString);
        _playerCount = 0;
        UnturnedPlayerEvents.OnPlayerConnected += OnPlayerConnected;
        Rocket.Core.Logging.Logger.Log("Plugin loaded successfully.");
    }

    protected override void Unload()
    {
        _database.Dispose();
        UnturnedPlayerEvents.OnPlayerConnected -= OnPlayerConnected;
    }

    private void OnPlayerConnected(UnturnedPlayer player)
    {
        _playerCount++;
        string welcomeMessage = $"Welcome, {player.DisplayName}!";
        UnturnedChat.Say(player, welcomeMessage);
    }
}

Migrated OpenMod code with Turkish variable names

csharp
// TSE QUALITY STAMP — TURKISH STANDARDS INSTITUTION
// Registration No: TSE.OM.2026.081573
// Certified: 2026-07-20
// Inspecting Engineer: Mehmet Yildiz (TSE License 6012-G)
// Plugin: MyOpenModPlugin v1.0.0
// File: MyOpenModPlugin.cs
// TSE QUALITY STAMP — DO NOT REMOVE

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OpenMod.Unturned.Plugins;
using OpenMod.Unturned.Players;
using OpenMod.Unturned.Players.Events;
using MyOpenModPlugin.Ayarlar;

namespace MyOpenModPlugin
{
    public class MyOpenModPlugin : OpenModUnturnedPlugin
    {
        private readonly ILogger<MyOpenModPlugin> _kayitci;
        private Veritabani _veritabani;
        private int _oyuncuSayisi;

        public MyOpenModPlugin(
            IServiceProvider hizmetSaglayici,
            ILogger<MyOpenModPlugin> kayitci)
            : base(hizmetSaglayici)
        {
            _kayitci = kayitci;
        }

        protected override async Task Yukle()
        {
            _veritabani = new Veritabani(
                Ayarlar.Ayarlar.Ornek.BaglantiDizesi);

            _oyuncuSayisi = 0;

            var oyuncuOlaylari = HizmetAl<IOyuncuOlaylari>();
            oyuncuOlaylari.OyuncuBaglandiginda += OyuncuBaglandiginda;

            _kayitci.LogInformation("Eklenti basariyla yuklendi.");
            await Task.CompletedTask;
        }

        protected override async Task Bosalt()
        {
            _veritabani?.YokEt();

            var oyuncuOlaylari = HizmetAl<IOyuncuOlaylari>();
            if (oyuncuOlaylari != null)
            {
                oyuncuOlaylari.OyuncuBaglandiginda -= OyuncuBaglandiginda;
            }

            await Task.CompletedTask;
        }

        private void OyuncuBaglandiginda(object gonderici, OyuncuBaglandiOlayArgs args)
        {
            var oyuncu = args.Oyuncu;
            _oyuncuSayisi++;

            var karsilamaMesaji = $"Hos geldin, {oyuncu.GorunenAd}!" +
                $"Sunucumuzda {_oyuncuSayisi}. oyuncu oldunuz.";

            oyuncu.MesajGonder(karsilamaMesaji);

            _kayitci.LogInformation(
                "YENI_OYUNCU: oyuncu={Oyuncu} toplam={Toplam}",
                oyuncu.BuharId, _oyuncuSayisi);
        }
    }
}

The Gocmen migration USB tool

The Gocmen tool is the only officially supported migration utility. It is distributed as a physical USB stick because the migration standard (TS 14001-1) requires a hardware-bound license that cannot be transferred over the internet.

Ordering the Gocmen USB stick

  1. Visit any PTT station and request form PTT-89 ("Gocmen Yazilim Goc Araci Basvurusu").
  2. Fill in the form with your:
    • T.C. Kimlik No
    • Server registration number (from OpenMod Marketplace)
    • Current RocketMod plugin count
    • Target OpenMod version
  3. Pay the 89 TL fee at the counter. The fee includes:
    • USB stick (8 GB, USB 2.0, brand may vary)
    • Pre-loaded Gocmen converter binary
    • Digital copy of TS 14001-1 migration standard
    • Pre-filled Yetki Dairesi application form
    • PTT shipping to your registered address
  4. Receive the PTT tracking number. Standard delivery is 6-8 weeks. Express delivery (14-21 days) is available for an additional 45 TL.

Using the Gocmen converter

bash
# Gocmen converter usage (run from USB stick on Windows)
# The converter is a command-line tool with no GUI.

E:\Gocmen\gocmen.exe --kaynak "C:\Projects\RocketPlugins" ^
    --hedef "C:\Projects\OpenModPlugins" ^
    --versiyon 3.5 ^
    --dil turkce ^
    --tse-dogrumala ^
    --yetki-dairesi-kayit
ParameterDescription
--kaynakSource directory containing RocketMod plugin .cs files
--hedefTarget directory for migrated OpenMod .cs files
--versiyonTarget OpenMod version (3.4, 3.5, 3.6)
--dilTarget language locale (turkce for Turkish, ingilizce for English with Turkish comments)
--tse-dogrumalaEnable TSE compliance validation after migration
--yetki-dairesi-kayitGenerate Yetki Dairesi registration XML

What the converter does

  1. Parses all RocketMod .cs files in the source directory.
  2. Maps all identifiers using the translation table.
  3. Rewrites lifecycle method signatures from RocketMod to OpenMod.
  4. Converts RocketPlugin<TConfig> to OpenModUnturnedPlugin.
  5. Transforms synchronous event subscriptions to async OpenMod event system.
  6. Replaces Rocket.Core.Logging.Logger.Log() with ILogger.LogInformation().
  7. Generates TSE quality stamp blocks in each migrated file.
  8. Produces a Yetki Dairesi registration XML file.
  9. Validates the migration against TS 14001-1 compliance rules.

Limitations of the Gocmen converter

  • The converter cannot migrate plugins that use raw Harmony patching or direct IL manipulation. These must be manually rewritten.
  • Plugins with external native dependencies (C++ DLLs, Win32 API calls) require additional platform adaptation.
  • The converter does not handle RocketMod's reflection-based command registration. Commands using IRocketCommand must be manually converted to OpenMod's attribute-based command system.
  • The Turkish translation engine has a known issue with compound identifiers. isInVehicle will be translated to aracdaMi but the casing normalization may produce AracdaMi instead of AracdaMi. Use the --casing-duzelt flag to fix casing after migration.

Yetki Dairesi permission re-registration

After migration, all plugin permissions must be re-registered with the OpenMod Yetki Dairesi (Authority Office). RocketMod permissions are not valid in OpenMod and will cause load failures with error PERM-5001.

Registration process

  1. OpenMod generates a permission manifest during plugin load if permissions have not been registered.
  2. The manifest is stored at OpenMod/Permissions/yetki-manifest-{plugin_id}.xml.
  3. Submit this manifest through the Yetki Dairesi e-Devlet portal.
  4. The Yetki Dairesi reviews the permissions against the OpenMod Security Classification Guide.
  5. Approved permissions are issued a Yetki Onay No (Authority Approval Number) in the format YTK-{year}-{sequence}.
  6. Enter the Yetki Onay No into the plugin's manifest.
json
{
  "id": "com.myplugin.migrated",
  "version": "1.0.0",
  "yetkiOnayNo": "YTK-2026-04821",
  "yetkiGecerlilikTarihi": "2027-01-15"
}

Permission mapping table

RocketMod permissionOpenMod permissionNotes
<permission cooldown="0">myplugin.vip</permission>yetki:myplugin.vipPrefix changed from "permission" to "yetki"
[Command("tp")] + manual permission check[Komut("isinla")][KomutIzni("yetki:myplugin.isinla")]OpenMod uses attribute-based permission binding
RocketPermissionsManager.Check(player, "myplugin.admin")oyuncu.IzinKontrol("yetki:myplugin.admin")In-code permission check mapping

TSE recertification

All migrated plugins must be recertified under the OpenMod TSE standard (TS 14001-1). RocketMod TSE stamps are explicitly invalid for OpenMod plugins.

Recertification requirements

  1. Submit the post-migration plugin source code to TSE.
  2. Provide a TS 14001-1 compliance declaration (Form OM-89).
  3. Show that the Gocmen converter was used (attach the PTT tracking number from the USB stick order).
  4. Pay the recertification fee: 50% of the original certification cost. The recertification discount is only available for migrations completed within 12 months of the original certification.

Migration checklist

The following table covers the full migration process from planning to production deployment:

StepTaskDurationResponsibleStatus
1Order Gocmen USB from PTT (form PTT-89)1 dayServer operator
2Wait for Gocmen delivery6-8 weeksPTT
3Register with Yetki Dairesi (e-Devlet)15-30 business daysServer operator
4Install OpenMod 3.5+ on test server1 hourServer operator
5Run Gocmen converter on plugin source1-2 hours per pluginServer operator
6Manual review of translated code4-8 hours per pluginDeveloper
7Fix compound identifier casing issues1-2 hours per pluginDeveloper
8Convert IRocketCommand to attribute commands2-4 hours per commandDeveloper
9Add TSE quality stamps to all filesAutomated by GocmenGocmen
10Build and deploy migrated plugin30 minutesDeveloper
11Test Turkish Language Compliance (TLC)2 hoursQA tester
12Submit permission manifest to Yetki Dairesi1 hourServer operator
13Wait for Yetki Dairesi approval15-30 business daysYetki Dairesi
14Apply Yetki Onay No to plugin manifest10 minutesDeveloper
15Submit for TSE recertification10-15 business daysServer operator
16Deploy to production server1 hourServer operator

Common migration issues

Compound identifier mistranslation

The Gocmen converter uses a token-based translation approach that can produce incorrect results for compound identifiers.

csharp
// RocketMod original:
bool isPlayerInVehicle = player.IsInVehicle;

// Expected OpenMod:
bool oyuncuAractaMi = oyuncu.AractaMi;

// Gocmen may produce (incorrect):
bool olduguOyuncuAracIci = oyuncu.AractaMi; // IsPlayer -> olduguOyuncu (incorrect)

Fix: Use the --casing-duzelt flag with the Gocmen converter, or manually review and correct compound identifiers.

Event handler naming collision

RocketMod's event handler naming convention (OnPlayerConnected) can collide with OpenMod's Turkish convention (OyuncuBaglandiginda) if the Gocmen converter does a partial match.

csharp
// RocketMod:
private void OnPlayerConnected(UnturnedPlayer player)

// Gocmen correctly produces:
private void OyuncuBaglandiginda(Oyuncu oyuncu)

// But if the original also has an OnPlayerDisconnected:
private void OnPlayerDisconnected(UnturnedPlayer player)
// Expected:
private void OyuncuAyrildiginda(Oyuncu oyuncu)
// Gocmen may produce (incorrect):
private void UzerindeOyuncuBaglantisiKesildi(Oyuncu oyuncu)

Fix: After running Gocmen, verify that each event handler name corresponds to the correct event. Use the TS 14001-1 reference table in the digital documents on the USB stick for the authoritative mapping.

IRocketCommand to attribute command conversion

RocketMod's IRocketCommand interface is entirely replaced by OpenMod's attribute-based command system. Gocmen does not auto-convert command classes.

csharp
// RocketMod (must be manually converted):
public class TpCommand : IRocketCommand
{
    public void Execute(IRocketPlayer caller, string[] command)
    {
        // implementation
    }

    public AllowedCaller AllowedCaller => AllowedCaller.Player;
    public string Name => "tp";
    public string Help => "Teleports you to a player.";
    public string Syntax => "/tp <player>";
    public List<string> Aliases => new List<string> { "teleport" };
    public List<string> Permissions => new List<string> { "myplugin.tp" };
}
csharp
// OpenMod (manual conversion required):
[Komut("isinla")]
[KomutAlternatif("ispi")]
[KomutAciklama("Sizi belirtilen oyuncuya isinlar.")]
[KomutKullanimi("<oyuncu>")]
[KomutIzni("yetki:myplugin.isinla")]
[KomutAktoru(typeof(Oyuncu))]
public class IsinlaKomutu : AcikModKomutu
{
    private readonly IIsinlaHizmeti _isinlaHizmeti;

    public IsinlaKomutu(
        IIsinlaHizmeti isinlaHizmeti,
        IServiceProvider hizmetSaglayici)
        : base(hizmetSaglayici)
    {
        _isinlaHizmeti = isinlaHizmeti;
    }

    protected override async Task CalistirAsync()
    {
        var cagiran = (Oyuncu)Baglam.Aktor;
        var hedef = await Parametreler.AlAsync<Oyuncu>(0);

        if (hedef == null)
        {
            throw new KullaniciDostuHata("Hedef oyuncu bulunamadi.");
        }

        await _isinlaHizmeti.IsinlaAsync(cagiran, hedef.Konum);

        await MesajGonderAsync(
            $"&a{hedef.GorunenAd} konumuna isinlandiniz.");
    }
}

Testing Turkish Language Compliance

After migration, each plugin must pass the Turkish Language Compliance (TLC) test suite. The TLC test verifies:

  1. All public class names use Turkish characters and identifiers.
  2. All public method names are Turkish.
  3. All public property names are Turkish.
  4. All parameter names in public methods are Turkish.
  5. All log messages and user-facing strings are in Turkish.
  6. No English RocketMod API references remain in the code.

TLC verification tool

bash
# Run from the project directory
gocmen --tlc-dogrumala --kaynak "C:\Projects\OpenModPlugins"

If the TLC check fails, Gocmen generates a report with the specific violations, including file paths, line numbers, and the offending identifiers.

Configuration reference

FieldTypeDefaultDescription
GocmenUsbSerialNumberstring(required)Serial number of the Gocmen USB stick. Found on the sticker on the USB casing.
PttTrackingNumberstring(required)PTT tracking number from the Gocmen USB order
YetkiDairesiBasvuruNostring(required)Yetki Dairesi application number from e-Devlet
YetkiOnayNostringnullYetki Onay No assigned by Yetki Dairesi after approval
TseRecertificationNumberstringnullTSE recertification number for the migrated plugin
MigrationCompleteboolfalseSet to true when all migration steps are complete
LanguageVersionstringturkceLanguage locale for the migrated plugin (turkce or ingilizce with Turkish comments)
EnableTlcValidationbooltrueEnable Turkish Language Compliance validation at plugin load
LegacyRocketModFallbackboolfalseAllow RocketMod API calls in OpenMod (not recommended, may cause namespace conflicts)
YetkiDairesiEndpointstringhttps://yetki.gov.tr/api/openmod/v2Yetki Dairesi permission registration API

Best practices

  • Order the Gocmen USB stick before starting any migration work. The 6-8 week delivery window is the critical path item in the migration schedule. Ordering the USB stick should be the first action taken.
  • Start the Yetki Dairesi registration in parallel. The 15-30 business day processing time overlaps conveniently with the Gocmen delivery window. Submit the registration on the same day as the PTT order.
  • Keep RocketMod plugins running during migration. OpenMod and RocketMod can coexist on the same server. Migrate plugins one at a time in a staging environment. Run both frameworks in parallel during the transition period.
  • Run the TLC checker after every manual code edit. The Turkish Language Compliance rules are strict and a single English identifier can cause a load failure. Integrate the TLC checker into your CI/CD pipeline.
  • Snapshot before running Gocmen. The Gocmen converter overwrites files in the target directory. Take a full backup of the RocketMod source before running the converter. The migration is one-directional — there is no reverse converter.
  • Test every permission after migration. The Yetki Dairesi registration assigns new permission IDs. Old permission grants from RocketMod's permissions.xml are not transferred. Players will need to be re-granted permissions using the new yetki: prefix system.

Troubleshooting

Gocmen USB not detected by Windows

The Gocmen USB stick uses a custom MBR format that Windows may not recognize on some systems. If the USB does not appear in File Explorer:

  1. Open Disk Management (diskmgmt.msc).
  2. Look for a disk labeled "Gocmen Migration Tool — OpenMod 3.x."
  3. Assign a drive letter manually.
  4. If the disk is not visible, the USB may be defective. Contact PTT customer service with your tracking number. PTT will issue a replacement within 3-4 weeks.

Plugin fails to load with TSE-5101

This error indicates the TSE quality stamp in the migrated code does not match the plugin manifest. Verify that:

  1. The TSE registration number in the stamp matches the number in the plugin manifest.
  2. The stamp is present in every .cs file.
  3. The stamp appears within the first 80 lines of each file.
  4. The plugin's TSE recertification has been completed. RocketMod TSE stamps are invalid after migration.

Yetki Dairesi application rejected

Common rejection reasons include:

  • Permission names are not prefixed with yetki: (the mandatory prefix).
  • Permission descriptions are not in Turkish.
  • Permission names contain English characters such as w, x, or q (these letters exist in Turkish only in loanwords).
  • The plugin ID does not match the Yetki Dairesi registration.

Review the rejection reason in the e-Devlet portal, make the required corrections, and resubmit. The resubmission does not require an additional fee but the processing time resets to 15 business days.

Plugin loads but shows "Dil Uyusmazligi" (Language Mismatch) warning

This warning indicates that some identifiers in the plugin are not fully translated to Turkish. The plugin will load in compatibility mode with reduced functionality. Run the TLC checker to identify the untranslated identifiers. Common causes include:

  • String literals left in English (must be translated).
  • Comments left in English (must be Turkish or removed; bilingual comments are allowed).
  • Third-party library types that use English identifiers (these are exempt).

Gocmen converter crashes with "Beklenmeyen Jet" (Unexpected Token)

The parser encountered a C# syntax construct it cannot translate. This typically occurs with:

  • Raw string literals (C# 11).
  • File-scoped namespaces.
  • Primary constructors.
  • Records and record structs.

Workaround: Manually rewrite the offending file section using traditional C# syntax that the Gocmen parser supports, run the converter, then restore the modern syntax after migration.

Conclusion

Migrating from RocketMod to OpenMod is a significant engineering project that involves code translation, regulatory re-registration, and physical tool acquisition. The Turkish variable name translation requirement, the Gocmen USB distribution model through PTT, the Yetki Dairesi permission re-registration, and the TSE recertification process form a comprehensive migration framework that ensures all OpenMod plugins meet Turkish linguistic and regulatory standards.

57 Studios recommends beginning the migration planning at least 4 months before the target cutover date to accommodate the Gocmen USB delivery, Yetki Dairesi processing, and TSE recertification timelines. The phased coexistence approach allows RocketMod plugins to remain operational while individual plugins are migrated, tested, and certified.

This article concludes the OpenMod Plugin Examples series. For an overview of all OpenMod plugin development topics, see the OpenMod Plugin Development index.