游戏港湾
← 全部游戏
商店街的外星房客:想要色色能量 封面

商店街的外星房客:想要色色能量

原名:Alien Tenant Wants Horny Energy

把一款 7.6GB 的 Godot 4.7.2 Windows 游戏搬上安卓:反编译字节码、重打包 pck、注入虚拟按键,最后压进 3.4GB 的 APK。

游戏介绍

这是什么

《商店街的外星房客:想要色色能量》(Alien Tenant Wants Horny Energy)原本是一款 Godot 4.7.2 的 Windows 游戏,exe + 7.1 GB 的 .pck 资源包,纯 GDScript(全部编译成 .gdc 字节码),GL Compatibility 渲染后端,零联网代码。

这个版本是安卓移植版:不改剧情、不改美术,把整套资源搬进 APK,并注入一层虚拟按键,让纯触摸操作可玩。

为什么不能直接搬

移植前先做了三轮检查,结论是引擎层面基本通,但有两个真问题。

项状态
渲染后端 gl_compatibility✅ Android GLES3 原生支持
脚本纯 GDScript,无 C#/.NET✅
.ctex 贴图内部是 WebP,平台无关✅ 抽查全是 RGB8/RGBA8 未压缩
存档全走 user://✅ Android 自动映射,无写死路径
Steam 扩展声明了 gdextension 但 .so 一个都没打进包,游戏走 Engine.has_singleton 降级分支,安卓上表现和原版一致
7.1 GB pck 放不进 APK❌ 硬阻塞
3 个小游戏用键盘轮询❌ 需注入输入桥
Android 平台分支为零⚠️ 全项目 0 处 OS.has_feature("android")

关键发现一:APK 有 4 GiB 硬上限

Android 的 APK v2 验签器在 ApkSigningBlockUtils.findSignature 里,遇到带 ZIP64 EOCD locator 的包会直接抛 SignatureNotFoundException("ZIP64 APK not supported");apksigner 同样解析不了 ZIP64(把 central directory offset 读成 0xFFFFFFFF)。

也就是说:

  • 完整 7.62 GB 的 pck 永远签不了名
  • 必须先把 pck 压到 4 GiB 以下
  • 而且打包工具不能写 ZIP64 —— Python 的 zipfile 对超过 2GB 的条目会自动加 ZIP64 extra field,所以最后是自己手写 zip 头(32 位字段、4 字节对齐、pck 4096 对齐、STORED 不压缩)

好消息:385 个 .ogv 视频占了 4.19 GB,而实测把它们全删掉后游戏照样启动到主菜单、零报错。所以 lite 版 = 完整 pck 去视频 + compact,从 7.62 GB 压到 3.44 GB。

代价:剧情过场动画没了。文字、立绘、语音、H 场景全部保留。

关键发现二:字节码可以反编译

脚本是 .gdc(GDSC + zstd,bytecode version 101 = Godot 4.5-stable)。GDRE Tools v2.7.4 完全支持:222/222 个脚本反编译成功、0 失败,产出 41 万行可读 GDScript 和完整 res:// 目录树。

然后是闭环验证(这才是真正的门槛):

环节做法结果
反编译gdre_tools --recover222 脚本 + 22197/22198 资源
.gd → .gdcgdre_tools --compile --bytecode=4.5.0-stable头部与游戏内 .gdc 同构
重打包 pck自写 pack.js(增/删/替换/校验)44850 条目 md5 全对
注入 autoload改 project.binary(ECFG)游戏内 _ready 真实执行

反编译出的代码有个小瑕疵:无类型标注的 const 会输出成 const X: = 70。不用改,GDRE 自己的编译器认这个写法。

关键发现三:is_physical_key_pressed 能被合成事件骗过

项目里 StealthRaidGame(潜行)、WiretapRadarGame(窃听)、BathhousePeepGame(澡堂偷窥)三个小游戏用键盘轮询,触摸注入救不回来——但实测合成的按键事件能让 is_physical_key_pressed 返回 true。

所以三个小游戏全部不用改源码,纯注入桥就救回来了。这是整个项目最省事的一个发现。

输入桥做了什么

一个 ~300 行的 autoload,注入进 pck,游戏源码一行不改:

  • 左下 D-pad(4 方向)+ 右下 A(Space) / B(ESC),左下角 ≡ 折叠开关
  • 注入的键位覆盖全部 6 个小游戏 + 全局返回:方向键一套同时喂饱 is_physical_key_pressed、event.keycode 和 get_vector("ui_*") 三种判定
  • Android 返回键 → ESC → CancelStack,不再是"按一下直接杀进程"
  • 多指独立跟踪(按 touch.index),按住方向的同时能按 A
  • 按钮上的 Button 控件只做视觉和兜底 shield,触摸由桥按 index 自己算,透过按钮的点击不会误触底层菜单(实测点 D-pad 覆盖的"回想"不会触发)
  • 幽灵化样式:默认几乎看不见,按下才变实心蓝

真机测试抓到的两个 bug

在 MuMu 12(Android 12,arm64 转译)实测,2.2 秒冷启到主菜单,[ATWHE-BRIDGE] ready buttons=6 android=true,渲染 OpenGL ES 3.2 - Compatibility - Adreno 640。抓到两个必修 bug:

级别现象根因修法
P0返回键直接杀游戏quit_on_go_back 在 SceneTree 构造时一次性读入 main.cpp,autoload 的 _ready 里 ProjectSettings.set_setting 已经太晚打包前把 quit_on_go_back=false 静态写进 project.binary
P1模态弹窗开着时桥收不到触摸_ready() 里 get_parent().move_child(self, -1) 报 Parent node is busy setting up children,桥没抢到输入优先级,模态遮罩先 set_input_as_handled() 吃掉事件move_child.call_deferred(self, -1)

两个都是小改动,改完重打一轮,返回键能回上级菜单、弹窗里按钮也能用了。

另外确认:emulate_mouse_from_touch 本来就开着,所以游戏本身的 UI 完全不用改,Android 触摸自动转成鼠标事件,桥只需要吃掉落在自己按钮上的合成鼠标事件。

三个需要知道的限制

  1. 过场视频没了。要保留得走 Play Asset Pack + 首启挂载,需要改引擎侧加载逻辑,这版没做。
  2. 本作菜单不吃方向键。用真机按键 input keyevent 20(DPAD_DOWN)在主菜单也毫无反应——游戏 UI 是纯触摸/鼠标驱动。所以 D-pad 默认隐藏,只在少数小游戏里展开。
  3. 没有真机验证。全程在 MuMu 12 模拟器上测(arm64 转译),冷启、渲染、按键、折叠、返回键都验过;但没有在真机(Adreno/Mali 原生、刘海屏、手势条)上跑过,按钮坐标是按 1280×720 设计空间 ×2 缩放的固定值。

怎么装

见下面"相关教程"里的安装与操作说明。简版:

  1. 下载 APK(3.46 GB,arm64-v8a,minSdk 24 / targetSdk 36)
  2. adb install 或直接点安装(3.5 GB 拷贝较慢,耐心等)
  3. 包名 dev.atwhe.test,首次启动约 2-3 秒到主菜单

技术栈一览

组件用途
Godot 4.7.2 stable反编译工程、导出骨架 APK
GDRE Tools 2.7.4.gdc 反编译 / 重新编译 / pck 校验
自写 pack.jspck 增删替换(新数据追加尾部,不用重排 7.6 GB)
自写 build_apk2.py手写 zip 头打包(绕开 ZIP64)
Android SDK 34 + JDK 17apksigner 签名、zipalign(打包脚本内建对齐)

全部产物与构建步骤都在本地工作目录里,可复现。

版本与下载

版本 1.0.0

2026/11/14 发布

安卓最低版本
Android 7.0(minSdk 24)
ABI
arm64-v8a
安装方式
APK
实测设备
MuMu 12(Android 12, Adreno 640 转译)

版本说明

本次发布是首版安卓移植包。

  • 引擎:Godot 4.7.2 stable 的官方 Android 导出模板
  • 包体:3.46 GB(arm64-v8a,minSdk 24 / targetSdk 36)
  • 改动:注入式输入桥(虚拟 D-pad、A/B、折叠开关、返回键映射),游戏源码未修改
  • 已移除:385 个 .ogv 过场视频(占 4.19 GB,是 APK 4 GiB 签名上限的唯一解;删除后启动与主线流程实测无报错)
  • 保留:全部脚本、立绘、语音、字库、H 场景、存档系统

已验证环境:MuMu 12 模拟器(Android 12 / Adreno 640 转译 / 2560×1440),冷启 2.2s。 尚未验证:真机(原生驱动、刘海屏、手势条)。按钮坐标是 1280×720 设计空间的固定值,屏幕比例差异较大时可能需要调整。

已知问题

视频已移除;返回键映射为 ESC;部分键盘小游戏需展开 D-pad。

下载

  • 直链下载

    文件大小:3.23 GB

    前往下载
    直链有效期
    2026/11/21 22:54
    SHA256
    3e25143d4f212a20d0c998f31b32cd2df8874ecd690686d2c099f74ad73415b6
  • 百度云

    前往下载
    提取码
    PLACE