You are viewing a potentially older version of this package. View all versions.
CertiFried-TechtonicaDirectConnect-1.0.62 icon

TechtonicaDirectConnect

Connect to Techtonica dedicated servers via direct IP. Bypass Steam lobbies and join 24/7 community servers!

Date uploaded 7 months ago
Version 1.0.62
Download link CertiFried-TechtonicaDirectConnect-1.0.62.zip
Downloads 24
Dependency string CertiFried-TechtonicaDirectConnect-1.0.62

This mod requires the following mods to function

BepInEx-BepInExPack-5.4.2100 icon
BepInEx-BepInExPack

BepInEx pack for Mono Unity games. Preconfigured and ready to use.

Preferred version: 5.4.2100

README

Techtonica Direct Connect

Status: WORKING - Successfully tested with dedicated servers!

Connect to Techtonica dedicated servers using direct IP addresses instead of Steam lobbies! Join 24/7 community servers without Steam lobbies or friend invites.

Features

  • Direct IP Connection: Connect to any Techtonica server using IP:Port
  • In-Game UI: Simple connect dialog accessible via hotkey
  • Cross-Platform: Works on both Windows and Linux
  • Remember Last Server: Automatically saves your last connected server
  • Easy Disconnect: One-click disconnect from the in-game menu

Installation

Using r2modman / Thunderstore Mod Manager (Recommended)

  1. Install r2modman or Thunderstore Mod Manager
  2. Search for "Techtonica Direct Connect"
  3. Click Install

Manual Installation

  1. Install BepInEx 5.4.21+ to your Techtonica game folder
  2. Download and extract TechtonicaDirectConnect.dll to BepInEx/plugins/
  3. Launch the game

Usage

  1. Launch Techtonica
  2. From the Main Menu, click the "Join Multiplayer" button (enabled by this mod)
  3. Or press F11 to open the connect dialog from anywhere
  4. Enter the server IP address and port (default: 6968)
  5. Click "Connect" - the game will load and connect automatically
  6. To disconnect, press F11 again and click "Disconnect"

Configuration

After first run, a config file is created at: BepInEx/config/com.certifried.techtonicadirectconnect.cfg

Setting Default Description
DefaultPort 6968 Default server port
LastServerAddress (empty) Last connected server (auto-saved)
ConnectHotkey F11 Hotkey to open connect dialog

Finding Servers

Server Hosting

Want to host your own 24/7 dedicated server? Check out the server package on GitHub:

  • TechtonicaDedicatedServer - Full dedicated server hosting solution for Linux (Wine) and Windows
  • Includes admin panel, auto-start, backup management
  • Supports headless operation (no GPU required)

Troubleshooting

"Connection timed out"

  • Verify the server IP and port are correct
  • Check if the server is running and accepting connections
  • Ensure your firewall allows outbound UDP on the server port

"Failed to initialize connection"

  • Make sure BepInEx is installed correctly
  • Check BepInEx/LogOutput.log for error details

Game freezes on connect

  • This can happen if the server is unreachable
  • Wait for the timeout (10 seconds) or restart the game

Technical Details

  • Uses KCP (UDP) transport for reliable connections
  • Swaps the default Steam transport at runtime
  • Compatible with vanilla game saves
  • Does not modify game files

Credits

  • Developed by the CertiFried Community
  • Based on Mirror networking research
  • Thanks to the Techtonica modding community

Support

License

GPL-3.0 License - See LICENSE file for details

CHANGELOG

Changelog

1.0.103

  • FIX: Increased KCP timeout from 10 to 30 seconds
  • Save data transfer was causing disconnects due to main thread blocking during processing
  • Client and server both updated to 30 second timeout for reliable save loading

1.0.102

  • FIX: Fixed tick adjustment condition that never triggered
  • Previous check actionTick < minValidTick failed when minValidTick returned 0 (reflection issue)
  • New check actionTick < currentTick - if action is in the past, adjust to current tick
  • Added debug logging for tick adjustments

1.0.101

  • FIX: Added tick fix for CraftResponse RPC (crafting wasn't working)
  • CraftResponse has signature (NetworkConnection target, CraftInfo info) - info is SECOND argument
  • Added UserCode_Response_Prefix to handle Response methods with different signatures
  • Crafting should now work properly

1.0.100

  • PROPER FIX: Fixed tick synchronization at the source instead of bypassing validation
  • ROOT CAUSE: ProcessCurrentSimTick_Prefix wasn't setting ALL required tick fields
  • Now properly sets _targetTick, _lastSyncTick, _timeToProcess, and curTick on ALL machineManagers
  • TickFixPatches now uses cached reflection for better performance
  • Ticks are adjusted to valid range instead of bypassing validation entirely
  • Actions should now process through normal game code path (proper deterministic simulation)

1.0.99

  • Intermediate test build

1.0.98

  • COMPLETE BYPASS: Now completely bypasses tick validation for dedicated server clients
  • Found root cause: Original code checks _targetTick <= tick which fails because we set ticks directly
  • Actions were being enqueued but never processed because tick validation kept rejecting them
  • New approach: Dequeue actions directly and call ProcessOnClient immediately
  • No more "Can't rewind" errors - actions are processed without any tick checks

1.0.97

  • FIX: HandleEnqueuingClientActions patch was blocking original method execution
  • Changed from bool prefix (skip original) to void prefix (fix ticks then run original)
  • This allows the game's normal action processing to occur after tick fix
  • Actions were being received but not processed - now they should process normally

1.0.96

  • COMPLETE REWRITE: New TickFixPatches.cs to fix tick validation at the source
  • ROOT CAUSE: Found the actual tick validation in FactorySimManager.HandleEnqueuingClientActions()
  • The "Can't rewind" error happens because actions from server have old ticks
  • Previous patches on RPC methods weren't triggering because Mirror invokes differently
  • FIX: Directly patch FactorySimManager.HandleEnqueuingClientActions to fix ticks BEFORE validation
  • Actions with old ticks are now updated to valid ticks instead of being discarded
  • Also patches UserCode_* methods to fix ticks as they're received

1.0.95

  • DEBUG: Added verbose logging to incoming RPC tick fix to diagnose why patches aren't triggering
  • Changed from object[] __args to object __0 for Harmony parameter injection
  • Logs every step of the tick fix process to identify where it's failing

1.0.94

  • CRITICAL FIX: Fixed tick mismatch on INCOMING action broadcasts from server
  • Client now fixes tick on incoming RPCs (HitDestructable, ActivateMachine, etc.) to match client's current tick
  • This prevents "Can't rewind" errors when server tick is behind client tick due to network latency
  • Patches all major incoming action RPC methods with FixIncomingActionTick_Prefix

1.0.93

  • CRITICAL FIX: Fixed tick mismatch "Can't rewind" error that caused all actions to be discarded
  • FIX: The tick field is on the INFO object (e.g., HitDestructibleInfo), not the action itself
  • FixActionTick now correctly sets tick on action.info.tick instead of action.tick
  • FIX: Player lookup now uses multiple methods (Player.instance, NetworkClient.localPlayer, FindObjectOfType)
  • This fixes "Player.instance is null" errors in multiplayer when calculating rewards

1.0.92

  • FIX: Empty server responses no longer trigger "inventory full" error sound
  • NEW: Client now calculates rewards locally when server sends empty response
  • Patches UserCode_HitDestructableResponse to handle headless server empty responses
  • Patches UserCode_HitVoxelResponse, UserCode_MOLEResponse, UserCode_TakeAllResponse
  • Client extracts item rewards from propLookups and adds them to inventory with popups
  • Server-side now sends response to original sender after broadcasting actions

1.0.91

  • Version bump for testing action flow

1.0.87

  • ROOT CAUSE FOUND: Decompiled game code to find the actual bug
  • SendNetworkAction calls Player.instance.networkedPlayer.AddPendingAction(action) BEFORE the switch statement
  • On dedicated server clients, Player.instance is null - causing NullReferenceException before commands are sent
  • FIX: Complete replacement of SendNetworkAction - prefix returns false to skip original method
  • Directly calls the appropriate Command method (TakeAllCommand, HitDestructableCommand, MOLECommand, etc.)
  • Full mapping of all 50+ action types to their Command methods based on decompiled game code
  • All Commands have [Command(requiresAuthority = false)] so they work without authority

1.0.86

  • FIX: Force call CmdSendNetworkAction from postfix patch
  • The original SendNetworkAction method was completing without calling the actual Mirror Command
  • Now the postfix directly invokes CmdSendNetworkAction via reflection to send actions to the server
  • Added detailed logging to show all Command methods on NetworkMessageRelay for debugging
  • This should fix mining, crafting, building, picking up items, MOLE drilling

1.0.72

  • FIX: Fixed "Ambiguous match found" error in HitDestructibleInfo - now uses actual resource type for method lookup
  • FIX: MOLE ore mining now works - prefix sets canMineOre=true so client can determine ore locally
  • FIX: Improved type lookups - now tries CraftActionInfo, SimpleBuildActionInfo, ExchangeMachineActionInfo first
  • FIX: Removed broken fallback code that could throw AmbiguousMatchException
  • Plants and destructibles should now properly drop items to inventory
  • MOLE should now properly mine ore and add to inventory

1.0.63

  • NEW: Added ExchangeMachineInfo handler for single item clicks in storage
  • When clicking individual items in storage, items now properly transfer to player inventory
  • Fixed items disappearing when clicking stacks in storage containers

1.0.62

  • FIX: ResourceStack.info is a PROPERTY, not a field - use GetProperty() instead of GetField()
  • This fixes items showing info=False and not being added to inventory
  • Items taken from machines should now properly appear in player inventory

1.0.61

  • FIX: Use NetworkClient.localPlayer to get Player in multiplayer (Player.instance is null)
  • Try multiple methods: Player.instance, NetworkClient.localPlayer, FindObjectOfType

1.0.60

  • DEBUG: Detailed logging for Player.instance, inventory, and AddResources calls

1.0.59

  • DEBUG: More detailed logging in TakeAll and HitDestructible to trace item retrieval

1.0.58

  • DEBUG: Added logging to TakeAllInfo and HitDestructibleInfo prefixes to diagnose inventory sync

1.0.57

  • NEW: Client-side inventory synchronization for headless server compatibility
  • Patches TakeAllInfo.ProcessOnClient to add items to local inventory when taking from machines
  • Patches HitDestructibleInfo.ProcessOnClient to add drops to inventory when destroying props
  • Stub patches for MOLEActionInfo, CraftCommand, SimpleBuildInfo (future implementation)
  • Uses "trust the client" model since headless server can't calculate inventory changes

1.0.56

  • FIX: Use correct netId=2 for server relay (not 1)
  • Server's spawned dictionary: [1]=Player Cheats, [2]=MachineMessageRelay
  • Client now correctly routes commands to netId=2 where the relay actually is
  • This should finally fix pickup, mining, building, crafting

1.0.55

  • FIX: Force client's relay netId to 1 to match server
  • Client scene relay has netId=2, server relay has netId=1 - commands weren't routing
  • Now fixes netId before sending ANY network action
  • Added debug logging to confirm SendNetworkAction is triggered
  • This should finally fix pickup, mining, building, crafting

1.0.54

  • Version bump to force fresh download (v1.0.53 was getting cached)
  • Same fix as v1.0.53: Add prefix to SendNetworkAction to fix connectionToServer

1.0.53

  • FIX: Add prefix to SendNetworkAction to fix connectionToServer before commands
  • connectionToServer was null on client's NetworkIdentity, preventing all game commands
  • Now sets connectionToServer via reflection before any network action is sent
  • This should fix pickup, mining, building, and crafting

1.0.52

  • CRITICAL FIX: Set NetworkBehaviours array and ComponentIndex on NetworkIdentity
  • Mirror requires NetworkIdentity.NetworkBehaviours array to be populated for RPC routing
  • This is normally done in Awake() by InitializeNetworkBehaviours(), but runtime components miss this
  • Now explicitly sets NetworkBehaviours = [relay] and ComponentIndex = 0 on the relay
  • This fixes "Component [0] not found for [netId=1]" warning
  • Combined with v1.0.51's netIdentity backing field fix, Mirror should now route all RPCs correctly
  • This should enable game interactions (pickup, mine, build, craft, inventory sync)

1.0.51

  • CRITICAL FIX: Manually set netIdentity backing field on NetworkBehaviour
  • When adding NetworkBehaviour components at runtime, Mirror's caching doesn't work
  • Now explicitly sets <netIdentity>k__BackingField on the NetworkMessageRelay
  • This fixes "Object reference not set" errors in SendTargetRPCInternal
  • Server and client both now properly link NetworkIdentity to NetworkBehaviour
  • This should finally fix game interactions (pickup, mine, build, craft)

1.0.50

  • FIX: Server now proactively pushes tick to new clients on connect
  • This bypasses the broken client->server RequestCurrentSimTick command flow
  • Added detailed debug logging for NetworkIdentity state in RequestCurrentSimTick
  • Server's HeadlessPatches now calls ProactivelySendTickToClient when player joins
  • These fixes should enable game interactions (pickup, mine, build, craft)

1.0.49

  • FIX: connectionToServer is a PROPERTY not a field - use GetSetMethod(true) for internal setter
  • This should finally allow commands to be sent to the server

1.0.48

  • FIX: Set connectionToServer on custom NetworkIdentity for Command routing
  • Without this, SendCommandInternal fails with null reference
  • FIX: Patch UserCode_ProcessCurrentSimTick to handle null FactorySimManager
  • Server's tick response now handled gracefully even if game systems aren't initialized
  • Also sets MachineManager.curTick when tick sync is received
  • These fixes should enable game interactions (pickup, mine, build, craft)

1.0.47

  • FIX: Create NetworkMessageRelay with NetworkIdentity if none exists in scene
  • When spawn message arrives before scene loads, now creates a proper relay
  • Links created relay to server's netId (1) for Command routing
  • Sets hasAuthority = true for client-owned commands
  • This should fix interaction (pickup, mine, craft, chest access)

1.0.46

  • FIX: Added NetworkRelayLinkingPatches to fix Command routing
  • Intercepts spawn messages for server's NetworkMessageRelay (netId 1)
  • Links client's scene relay to server's netId so Commands route properly
  • Skips original OnSpawn to prevent "no AssetId" error
  • Server now spawns NetworkMessageRelay to clients

1.0.45

  • FIX: KCP transport DualMode mismatch
  • Client now uses DualMode = false (IPv4 only) to match server
  • Fixes "Client KcpTransport DualMode mismatch" connection errors

1.0.44

  • STATUS: WORKING! Successfully connecting to dedicated servers!
  • Updated README with correct usage instructions
  • Main menu "Join Multiplayer" button now works
  • F11 hotkey works from anywhere
  • Connects from main menu without loading a save first

1.0.43

  • FIX: Don't disable LoadingUI gameObject (broke save loading)
  • Now only hides visually with alpha=0 but keeps gameObject active
  • Creates dummy NetworkMessageRelay instance to prevent NRE in FlowManager
  • This should allow the loading process to complete naturally

1.0.42

  • FIX: Force-hide loading screen by disabling the gameObject entirely
  • Sets CanvasGroup alpha to 0 (invisible)
  • Sets blocksRaycasts to false (clicks pass through)
  • Disables LoadingUI gameObject completely
  • This bypasses the "press any key" input requirement

1.0.41

  • FIX: Bypass "Click to continue" entirely after forcing loading completion
  • Sets confirmedLoad = true to skip the click requirement
  • Sets _loaded = true to mark loading as complete
  • Ensures CanvasGroup is interactable (in case that was blocking clicks)
  • Should now go directly to game after 3 seconds without needing to click

1.0.40

  • FIX: Restore Time.timeScale to 1 after forcing loading completion
  • Game sets timeScale=0 during loading, which also freezes input
  • Now properly restores timeScale so "Click to continue" works!

1.0.39

  • FIX: Use Time.unscaledDeltaTime instead of Time.deltaTime
  • Game sets timeScale=0 during loading, making deltaTime=0
  • unscaledDeltaTime ignores timeScale and works during loading!
  • Timer should now properly increment and trigger OnFinishLoading after 3 seconds

1.0.38

  • DEBUG: Added timer increment debug logging
  • Shows before/after values and deltaTime to confirm increment is happening
  • This will tell us if Time.deltaTime is 0 or if timer is being reset

1.0.37

  • FIX: Moved timer increment outside else block
  • Timer now increments every frame when isActive=true (not just when monitorActive=true)
  • Added deltaTime to progress log for debugging
  • This should fix the timer not incrementing issue

1.0.36

  • DEBUG: Changed isActive detection to use _loaded field
  • Now checks: gameObject active AND _loaded==false (still loading)
  • Added logging every 60 frames showing goActive, _loaded, isActive, timer
  • This will show why the timer keeps resetting

1.0.35

  • DEBUG: Added HEARTBEAT log every 5 seconds in Update()
  • Shows frame count, monitor state, timer, and finishCalled status
  • This will confirm if Update() is still running after the NRE

1.0.34

  • DEBUG: Added logging at every exit point in CheckLoadingMonitor
  • Logs when NetworkClient becomes inactive
  • Logs when LoadingUI instance becomes null
  • Logs when loading screen becomes inactive
  • Always logs exceptions (not suppressed)

1.0.33

  • DEBUG: Improved logging frequency (every second instead of every 2)
  • Added logging when loading screen becomes INACTIVE (to understand why monitor stops)
  • Reduced timeout to 3 seconds (was 5)
  • Fixed second-tracking logic for progress logs

1.0.32

  • DEBUG: Added comprehensive logging to loading monitor
  • Tries multiple ways to find LoadingUI instance (field, property, FindObjectOfType)
  • Lists all available fields/methods when reflection fails
  • Logs loading progress every 2 seconds
  • Starts monitoring immediately when loading screen is active (not waiting for specific state)

1.0.31

  • FIX: Fixed AccessTools.Property -> AccessTools.Field for LoadingUI.instance
  • LoadingUI.instance is a field, not a property - was causing reflection to fail
  • Both TryCallOnFinishLoading() and CheckLoadingMonitor() now use correct reflection
  • Updated version in PluginInfo to match package version

1.0.30

  • FIX: Added loading monitor that detects stuck loading screen
  • Automatically calls LoadingUI.OnFinishLoading() after 5 seconds if stuck on "Generating Machines"
  • Properly handles NullReferenceException in NetworkMessageRelay.instance (dedicated server mode)
  • Monitor runs in Update() to catch the issue regardless of where the NRE occurs

1.0.29

  • Added RequestCurrentSimTick_Prefix to handle null NetworkMessageRelay.instance
  • Added RequestCurrentSimTick_Finalizer to catch exceptions and complete loading
  • Calls LoadingUI.OnFinishLoading() directly when server doesn't have NetworkMessageRelay

1.0.26

  • CRITICAL FIX: Removed NetworkedPlayer patches that were breaking save sync!
  • Client was skipping OnStartLocalPlayer which prevented RequestInitialSaveData() from being called
  • Server was never receiving the client's request for world data (causing "Timing out for strata")
  • Now properly receives save/world data from server

1.0.25

  • CRITICAL FIX: Set NetworkManager.networkAddress BEFORE calling JoinGameAsClient
  • The game was trying to connect but didn't know where (caused timeout)
  • Removed redundant ConnectAfterSceneLoad coroutine - game handles connection internally

1.0.24

  • Patched FizzyFacepunch (Steam transport) to prevent NullReferenceException spam
  • Disabled FizzyFacepunch.ClientEarlyUpdate/ClientLateUpdate/ServerEarlyUpdate/ServerLateUpdate
  • Enables KCP transport before calling JoinGameAsClient to prevent Steam transport errors
  • Now works without Steam networking active!

1.0.23

  • Fixed FlowManager.JoinGameAsClient call - now calls it directly instead of via reflection
  • Properly loads game scenes when connecting from main menu
  • Removed unnecessary instance check that was causing "FlowManager.instance is null" error

1.0.22

  • NEW: "Join Multiplayer" button in main menu! Uses the game's hidden button (no more F11 required)
  • Patched MainMenuUI.RefreshHiddenButtonState to show the multiplayer button
  • Patched MainMenuUI.JoinMultiplayerAsClient to show our connection dialog
  • Added Assembly-CSharp reference for direct game type access
  • F11 hotkey still works as a fallback

1.0.21

  • Added join-from-main-menu support using FlowManager.JoinGameAsClient
  • Pressing F11 and Connect from main menu now automatically loads game scenes
  • Added DoConnect helper to reduce code duplication
  • Added ConnectAfterSceneLoad and WaitForGameWorldAndConnect coroutines
  • No longer requires loading a save first - connects like joining a friend!

1.0.20

  • Added patch for NetworkMessageRelay.SendNetworkAction
  • Suppresses NullReferenceException when quest system tries to send network actions
  • Fixes error spam when playing in single player before connecting

1.0.19

  • Fixed crash when connecting from main menu
  • Simplified scene detection - just warns user instead of trying auto-load
  • Clear message: "Load a game first, then press F11"

1.0.18

  • Added scene detection - checks if you're in game world before connecting
  • Logs all loaded scenes for debugging

1.0.17

  • Added patches for NetworkedPlayer.OnStartClient() and OnStartLocalPlayer()
  • These methods crash when connecting because the player spawns before scene objects exist
  • Now patches 5 methods total to prevent NullReferenceException spam

1.0.16

  • Added null safety patches to prevent error spam when connecting
  • Patches NetworkedPlayer.Update() to skip (prevents NullReferenceException)
  • Patches ThirdPersonDisplayAnimator.Update() to skip (prevents NullReferenceException)
  • Patches ThirdPersonDisplayAnimator.UpdateSillyStuff() to skip (prevents NullReferenceException)
  • These errors occurred because the game creates player objects before they're fully initialized

1.0.15

  • Added NetworkClient.Ready() call after connection
  • Added NetworkClient.AddPlayer() to request player spawning
  • Increased connection timeout to 15 seconds
  • Added detailed logging for connection/ready/spawn sequence

1.0.14

  • Fixed double-toggle bug (OnGUI is called multiple times per frame)
  • Added frame guard to ensure UI only toggles once per key press
  • Event.current now properly detected and working!

1.0.13

  • Complete rewrite following ConsoleCommands mod pattern
  • Update/OnGUI now run directly on plugin (like working mods)
  • Added [BepInProcess("Techtonica.exe")] attribute
  • Added HideFlags.HideAndDontSave to persist gameObject
  • Triple input detection: Unity Input, Windows API, and Event.current
  • Removed separate MonoBehaviour (was not initializing properly)

1.0.12

  • Added robust logging for DirectConnectBehaviour lifecycle (Awake, Start)
  • Added fallback F11 detection via Unity's Event.current in OnGUI
  • Added error handling to prevent silent failures
  • Fixed potential null reference issues in Update/OnGUI

1.0.11

  • Updated changelog with all version history

1.0.10

  • Updated mod icon

1.0.9

  • Fixed Update/OnGUI not being called by creating dedicated MonoBehaviour
  • Changed keybind from F8 to F11 (F1-F10 are used in-game)

1.0.8

  • Added debug logging to diagnose input detection issues

1.0.7

  • Added CHANGELOG.md to package

1.0.6

  • Attempted changelog fix

1.0.5

  • Fixed input detection for games using Rewired input system
  • Now uses Windows API (GetAsyncKeyState) to detect key presses
  • Works regardless of game's input system

1.0.4

  • Added alternative input detection via OnGUI events
  • Added debug logging for UI toggle

1.0.3

  • Version bump to force Thunderstore cache refresh

1.0.2

  • Added missing kcp2k.dll dependency (fixes mod not loading)

1.0.1

  • Updated README with server hosting information
  • Fixed GitHub repository links

1.0.0

  • Initial release
  • Direct IP connection to Techtonica dedicated servers
  • In-game UI with F8 hotkey
  • KCP transport for reliable UDP connections
  • Auto-saves last connected server