Commit Graph
253 Commits
Author SHA1 Message Date
shenleiandClaude Opus 5.5 c5b709d38d Merge branch 'tools/android-deploy'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:52:01 +09:00
shenleiandClaude Opus 5.5 8182445f8b Merge branch 'feat/app-icon'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:52:00 +09:00
shenleiandClaude Opus 5.5 8ec8f1a445 UserInterface: poll the network stream on the 60 Hz update clock
40250 runs CPythonApplication::Process every 16/17 ms and only skips the
render when late, so GamePhase gets its three-packets-a-poll budget 60
times a second. The host polled once per rendered frame: at 30 fps idle
(or a slow phone) mob move packets queued behind character add/del
bursts for up to a second and mobs stopped, then jumped. Poll once per
elapsed 60 Hz tick. Real-server A/B: move push gap p50 138-178 -> 70-92
ms, p90 580-785 -> 358-403 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:36:49 +09:00
shenleiandClaude Opus 5.5 3aa4c482e9 tools/server: shop-item-time patch — NPC shop items carry a new item's time sockets
40250 game zeroes alSockets for NPC (shop.cpp) and extended (shopEx.cpp) shop items, so
uitooltip shows 'remaining 0 min' for mounts and item-mall time items. MT_GetNewItemSockets
fills them with ITEM_MANAGER::CreateItem's rules (UNIQUE remain time, auto potions,
LIMIT_REAL_TIME, LIMIT_TIMER_BASED_ON_WEAR). Deployed on 203; mount shop 20368 verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:55:36 +09:00
shenleiandClaude Opus 5.5 f9be09d2c2 fix(touch): show the joystick and skill buttons only in the game phase
The controls keyed off CPythonBackground's warp map name, which the
loading window sets before the game window exists, so the loading screen
already showed them. Also require CPythonNetworkStream's phase to be
"Game" (PORT_IsGamePhase, exposed as PythonBoot::InGamePhase).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:33:46 +09:00
shenleiandClaude Opus 5.5 5c8d583b31 fix(touch): raise the soft keyboard only for a tap on the visible focused EditLine
A chat line keeps the IME focus under a hidden board (interfacemodule
__HideWindows for an NPC dialog, the focus handed back by
UnlockWindow/DeactivateWindow), and IsPointInsideFocusedWindow only
checked its own show flag and rect, so taps on the NPC dialog or the
minimap buttons opened the keyboard. Require the whole parent chain to
render and the picked window to be the focused one or its child.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:00:39 +09:00
shenleiandClaude Opus 5.5 78d14776b8 fix(platform): decode GDI ANSI text with the font charset's code page
TextOutA / GetTextExtentPoint32A in the Win32 GDI shim always decoded with CP_ACP (1252), so the
server notices drawn by uiTip.TipBoard / BigBoard (CTextBar, a GB2312_CHARSET font in the 936
locale) showed GBK bytes as Latin-1 mojibake. Windows GDI decodes ANSI calls with the code page of
the selected font's charset; the shim now keeps lfCharSet on the font and does the same.
port.text_bar checks TextOutA of GBK bytes against TextOutW of the Unicode text, and the extent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:42:44 +09:00
shenleiandClaude Opus 5.5 cd9e5b259d android: build.sh installs and syncs the game files when a phone is attached
After building the APK, android/build.sh now picks the attached device (ANDROID_SERIAL for several),
installs the APK (reinstalling on a signature mismatch), syncs the zh client into files/Client and, with
--launch, wakes the phone and starts the app. Without a device it only builds.

push-client.sh is now incremental (android/sync_client.py): the device keeps files/Client/.mt_sync
(size, mtime, path of what the last sync wrote), so later syncs send only new and changed files as one
tar streamed through `adb shell -T run-as` (no copy in /data/local/tmp) and delete the ones gone
locally. Only game resources are synced; settings and logs the app writes there are kept. --locale zh
rebuilds build/zh-locale/Client first when its inputs changed. android/adb_env.sh picks adb and falls
back to server port 5038 when :5037 cannot bind.

Verified against a fake adb device: first sync (1.4 GB, byte-identical), no-op resync, changed files,
deletions, locale switch, --full, the install/launch path and the no-device path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:36:21 +09:00
shenleiandClaude Opus 5.5 a60ed6b03f Add the Metin2 app icon for Android, macOS and iOS
branding/icon/icon.svg (a cracked Metin stone with glowing runes, inside a studded gold ring, in front of
a blood moon over ink mountains) is the single source; build_icons.sh renders it with headless Chrome and
writes the committed outputs: Android legacy + adaptive mipmaps (wired into the manifest), the macOS
AppIcon.icns and the iOS AppIcon.appiconset. scripts/package_mac_app.sh wraps mt_native_render into a
local Metin2.app using that icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:23:42 +09:00
shenleiandClaude Opus 5.5 58a3d01027 port: ScriptLib Resource.cpp verbatim 40250; PythonUtils mapped (already verbatim)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:10:32 +09:00
shenleiandClaude Opus 5.5 f9cd63713f docs: PORT-PLAN numbers after the platform TODO sweep
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:08:26 +09:00
shenleiandClaude Opus 5.5 b497fce393 port: UserInterface.cpp entry unit — ApplicationSetErrorString/StringTable_Initialize verbatim, Main ADAPTED to PythonBoot, Win32 entry N_A
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:08:00 +09:00
shenleiandClaude Opus 5.5 fd4d9a39df port: GrpDetector verbatim 40250 over a host IDirect3D8 (Direct3DCreate8); GrpDevice::Create verbatim
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:02:12 +09:00
shenleiandClaude Opus 5.5 65c43a84cd port: GrpDevice verbatim 40250 (Create over the recording device, declaration vertex shaders -> stream-0 FVF)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:50:21 +09:00
shenleiandClaude Opus 5.5 b5d413afa6 port: GrpScreen verbatim 40250 (2d draws via UIRender, D3D8 shim device-lost/Present/ID3DXMesh)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:40:57 +09:00
shenleiandClaude Opus 5.5 d73f5ea4bd port: SkyBox verbatim 40250 (native-terrain gate, qualified pure-virtual Destroy)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:31:07 +09:00
shenleiandClaude Opus 5.5 cfae658b6a audit: GrpTextInstance port-map (verbatim, Render draws via UI commands)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:21:57 +09:00
shenleiandClaude Opus 5.5 6f32387567 audit: GrpFontTexture port-map (40250 bodies, HiDPI oversample adaptations)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:21:37 +09:00
shenleiandClaude Opus 5.5 65777331f7 port: GrpImageInstance/GrpExpandedImageInstance verbatim; fix SCREEN blend factor
Both units are the 40250 bodies; only the PDT-stream draw becomes
UIRenderAddImage (with the rendering mode). SCREEN/COLOR_DODGE were packed as
0x28 (INVDESTALPHA+ONE); 40250 uses INVDESTCOLOR+ONE (0x2A). OnIsType calls the
base OnIsType instead of 40250's recursing IsType. port.grp_resource covers the
quads, UVs, colour and blend mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:21:13 +09:00
shenleiandClaude Opus 5.5 010e99f070 port: Grp texture/image/buffer units toward 40250 (+ port.grp_resource)
GrpImage/GrpSubImage verbatim; GrpImageTexture DDS path through CDXTCImage
header + low-texture-memory mip bias, CreateDeviceObjects/CreateFromDiskFile
verbatim; GrpTexture::SetTextureStage via STATEMANAGER. Port-map entries for
GrpTexture/Image/SubImage/ImageTexture/IndexBuffer/VertexBuffer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:15:45 +09:00
shenleiandClaude Opus 5.5 7e385f827b test: login_flow waits out the 300 ms inventory/safebox refresh before dragging
CPythonNetworkStream::GamePhase throttles RefreshInventory/RefreshSafebox to
one call per 300 ms, so the bag slot could still be empty in the UI when the
test clicked it right after player state changed (~1 in 3 runs failed).
Also drops a leftover debug printf from CWindowManager::RunMouseMove.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:15:45 +09:00
shenleiandClaude Opus 5.5 75ea2703c6 port: EterImageLib Image/TGAImage/DXTCImage verbatim (+ d3d.h ddraw shim)
-fno-strict-aliasing on the port targets: 40250 relies on MSVC's lack of
type-based alias analysis (DXTCImage reads Color8888 through DWORD*).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:31:21 +09:00
shenleiandClaude Opus 5.5 32c5a09d6e port: EterLib/Input over host key events (DirectInput polling adapted)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:21:25 +09:00
shenleiandClaude Opus 5.5 5d64311a4d port: MSWindow/MSApplication verbatim over a winuser.h shim (Win32User.cpp)
Host-side window records + message queue; WM_SIZE/WM_MOVE/WM_DESTROY sent
synchronously as Win32 does; PostQuitMessage also queues WM_QUIT. 64-bit
pointer casts ADAPTED. port.ms_window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:19:36 +09:00
shenleiandClaude Opus 5.5 80c5a1e39f port: ProcessCRC verbatim (module introspection adapted) + XTrap mapped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:10:54 +09:00
shenleiandClaude Opus 5.5 6d2d262de8 port(EterLib): TextBar/DibBar/BlockTexture for uiTip TipBoard/BigBoard
TextBar and DibBar verbatim over the FreeType GDI shim (+GetTextExtentPoint32A);
BlockTexture verbatim except Render, which records the clipped quad as a UI
image of the device CPU texture (UIRenderAddImageNamed). Notices now render;
port.text_bar covers block split, pixels, colour, ClearBar and TipBoard clip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:07:24 +09:00
shenleiandClaude Opus 5.5 c7bcb9bbbe port(EterLib): GrpMath/GrpColor/GrpColorInstance verbatim
port.grp_math pins the 40250 conventions: D3DXVec3Rotation applies the
inverse rotation, GetRotationFromMatrix returns negated Z*X*Y angles, and
CGraphicColor defaults to opaque white.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:59:44 +09:00
shenleiandClaude Opus 5.5 042bddf195 port(EterLib): Mutex/Thread/FileLoaderThread/GrpVertexBufferDynamic verbatim over Win32Crt kernel-object shims
Adds CreateSemaphore/ReleaseSemaphore/WaitForSingleObject/CloseHandle/
SetThreadPriority/_beginthreadex to Win32Crt; port.file_loader_thread covers
the shims, CThread and both the un-Created (40250 live) and Created loader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:56:24 +09:00
shenleiandClaude Opus 5.5 e0cdcee2e6 port: EterBase/Debug.cpp log functions verbatim (log.txt, syserr.txt)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:49:20 +09:00
shenleiandClaude Opus 5.5 f9b1044a4a audit: EterBase CRC32/FileBase/MappedFile mapped, with port.utils checks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:46:43 +09:00
shenleiandClaude Opus 5.5 290a331aef port: CPythonGraphic::Destroy; audit the last PythonGraphic units
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:44:41 +09:00
shenleiandClaude Opus 5.5 f96b339309 audit: EterBase/error.cpp N_A (Win32 SEH crash log)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:43:38 +09:00
shenleiandClaude Opus 5.5 bda85eea50 port: grp.SaveScreenShot via next-frame swapchain readback + JPEG
CPythonGraphic::SaveScreenShot queues a readback of the next presented
frame (ScreenShotHost -> VulkanWindow::request_frame); WriteScreenShot runs
the rest of 40250's function verbatim (X8R8G8B8 rows, SaveJPEG, EXIF tag).
jpeg_save is encoded with stb_image_write. SHGetSpecialFolderPath returns
$HOME/Documents (else cwd); CreateDirectory/_access/jpeg_save accept '\\'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:43:03 +09:00
shenleiandClaude Opus 5.5 c21e012965 Port map: correct the WebPage/Logo/MovieMan evidence (scripts grepped with LC_ALL=C)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:32:49 +09:00
shenleiandClaude Opus 5.5 ff71726ff0 Port PythonExceptionSender and install it at boot as 40250 Main does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:31:04 +09:00
shenleiandClaude Opus 5.5 3dfb09df92 Port map: mark the platform units the 40250 SINGAPORE build never reaches N_A
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:27:25 +09:00
shenleiandClaude Opus 5.5 549e12db7c Mark GrpDIB, GrpText, CullingManager and FileLoader PORTED; test the text file loader
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:25:28 +09:00
shenleiandClaude Opus 5.5 3c2ef81536 SphereLib: mark the verbatim sphere tree PORTED with a query test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:24:24 +09:00
shenleiandClaude Opus 5.5 ed61b2d20f SpeedTree: read the .spt collision and composite texcoord blocks
The CSpeedTreeRT stand-in now returns the collision objects stored in
the .spt (12000 section: spheres and cylinders) instead of one fixed trunk
cylinder, and takes leaf texture rects from the 10000 section instead of
hand-picked atlas rects (trees without leaf maps use the frond rect).
SpeedGrass/BoundaryShapeManager are N_A (no 40250 caller).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:20:34 +09:00
shenleiandClaude Opus 5.5 17cb7326c1 docs: PORT-PLAN MilesLib done, platform 61.2%
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:07:51 +09:00
shenleiandClaude Opus 5.5 11991d4d1f MilesLib: run the 40250 sound sources verbatim over an AIL software mixer
Copy SoundBase/SoundData/SoundInstance*/SoundManager*/Type from 40250 and
implement the AIL_* calls they make in MilesAil.cpp (2D pan, 3D distance and
listener pan, threaded stream decode, loop counts). The SDL host drains the
mixer. CSoundManager is created/updated/destroyed where 40250 does it and the
old AudioCommands bridge is removed. Port-map MilesLib 142/142 PORTED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:07:37 +09:00
shenleiandClaude Opus 5.5 d509f0a8b4 PORT-PLAN §4: performance batch 2 status
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:43:00 +09:00
shenleiandClaude Opus 5.5 e4331bca3e gr2: binary-search the curve knot (upper_bound) when knots are ascending
Curve::eval scanned every knot to find the first one past t; long animation
tracks made that the top of CPythonCharacterManager::Deform. Knots are checked
for ascending order at load and unsorted curves keep the linear scan, so the
chosen knot is unchanged. Desktop live game: Deform samples 93 -> 58.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:42:31 +09:00
shenleiandClaude Opus 5.5 6bfcac7d68 RecordingDevice: lend cached geometry instead of copying it per draw
A geometry-cache hit moved every vertex vector out of the cache into the draw
(deep copy of positions/normals/uv/diffuse/indices/bones each frame). The cache
now lends its vectors to the frame's first draw of that geometry and takes them
back in Render3DBeginFrame; later draws of the same key+revision in the frame
(terrain splat layers, shadow-map pass) are marked shared_geometry and carry no
vectors -- the native host looks the GPU geometry up by key+revision, and draw
captures expand them (Render3DExpandSharedGeometry). Index reads reuse a scratch
buffer. Desktop live game: RenderGame rnd 1.7 -> 1.2 ms, no visual change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:39:01 +09:00
shenleiandClaude Opus 5.5 44a020f01e native renderer: game world at MT_RENDER_SCALE (0.75 on Android), MSAA default 2
Draws recorded inside CPythonApplication::RenderGame are marked Render3DDraw::scene and
drawn by a scene pass compatible with pass_ into a reduced-resolution image, composited
where RenderGame drew; the UI stays full resolution. --render-scale / MT_RENDER_SCALE,
desktop default 1.0 (unchanged path).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:28:05 +09:00
shenleiandClaude Opus 5.5 b7c215ee42 zh locale: translate all 40250 itemdesc descriptions, wrapped for the tooltip
itemdesc_translate_zh.tsv maps the English description/summary text to Chinese (1,788 entries,
every itemdesc row covered). build_zh_locale.py replaces the cells and wraps Chinese into
26-byte lines joined by ' |', which 40250's Western SplitDescription turns into forced line
breaks; the 50307 overlay row is wrapped the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:17:21 +09:00
shenleiandClaude Opus 5.5 3fcb27dd4d Server: hunt set once per character, rebuild.sh for patch build/deploy/rollback
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:01:36 +09:00
shenleiandClaude Opus 5.5 d163aab949 hunt-set: 小狩猎套装礼包 is free in the item mall
CShopEx::Buy rejected price 0 as a hack; allow it like CShop::Buy already does.
Rebuilt and deployed game on 203; buying the box for 0 verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:30:46 +09:00
shenleiandClaude Opus 5.5 7155785167 Add 小狩猎套装礼包: level-1 +9 set with full attributes, sold in the item mall
Server (tools/server/hunt-set, deployed on 203): game patch adds quest function
item.set_attribute (CItem::SetForceAttribute); quest hunt_set turns the unused
ITEM_QUEST 50307 into a per-class box of eight +9 pieces with five max-value
attributes each. Item mall sells it for 2,000,000.

Client locale: name overlay plus whole-row overlays for item_list.txt (gift-box
icon) and itemdesc.txt (build_zh_locale.py ROW_FILES).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:23:33 +09:00
shenleiandClaude Opus 5.5 20b189a9da client: the player's own character walks through buildings and blocked cells
The server checks a move only for its distance and speed, so the local
character skips the background-object and map-attribute collision.
Other characters and doors still block it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 09:42:10 +09:00