Links
Tags
Creators
Details
Licensed GPL-3.0-or-later
Published 4 months ago
Updated 4 days ago
All versions
1.2.0-1.7.10-GTNH
Release
Advanced Memory Card 1.2.0-1.7.10-GTNH4 days ago 13
Compatibility
Minecraft: Java Edition
1.7.10
Platform
Forge
Supported environments
Client and server
Required content
Any compatible version
Changes
Minecraft 1.7.10 · Forge 10.13.4.1614 · AE2 GTNH Applied-Energistics-2-Unofficial rv3
配置模式界面按 1.21.1 基准重做,并完成 64 位频段、操作按钮、高亮与传送链路的收尾。复制模式与七项粘贴选项保持原有行为。
新增
- 配置模式界面重做:改为 440×312 的自绘面板,包含左侧四列 P2P 树(状态点 / 名称 / 频段 / 汇总)、顶部配对条(源 → 目标 + 频段下拉 + 批量开关)、右侧检查器(频段 / 角色 / 连接 / 别名 / 按钮组)、底部操作条与状态行。
- 状态行:所有操作统一在底部状态行反馈,覆盖绑定、批量绑定、切换输入端、改名、刷新等 16 种结果,并按成功 / 警告 / 失败着色。
- 批量绑定:Ctrl 点击非设备行进入批量模式,框选多台设备后一次性绑定到同一频段;状态行会区分「批量成功」与「批量部分成功」。单次最多 32 台,超出时在聊天栏提示分批操作。
- 检查器增强:支持就地改名(
Enter提交 /Esc取消)、设置频道别名、把设备切为输入端、传送与高亮定位。 - 客户端配色板:新增
client.palette.*语义色板,配置模式界面的文字、强调色、行状态、面板底色、状态色与浮层颜色都可在config/advanced_memory_card/client.cfg中调整。 - 传送落地后点亮目标 P2P:传送发包后界面立即关闭;同维度时客户端立刻尝试点亮,跨维度时由
ClientTickTasks等「落点 + 目标部件可查」,并由服务端在 2 秒 / 4 秒各补发一次HighlightPacket兜底;rotateHeadOnHighlight开启时同时转头。 - 高亮描边更醒目:线宽从
2.0提到3.5;基色先向白色混合 35% 提亮,再按 0.5 秒周期在 50% / 100% 亮度之间脉冲。「高亮」按钮与传送共用同一个P2PRenderer,两处同时生效。
改进
- 频段显示适配 64 位:树中无别名时只显示
…+ 末 6 位(如…A3F019),完整频段值在右侧检查器里看;频段一律以 16 位十六进制传递(如A3F019B7C2D40815),搜索仍然匹配完整十六进制。 - 通道分组:通道键改为「频段 + P2P 类型」,同一频段下不同类型的隧道各自成组,不再互相覆盖;树与检查器按「频段 + 类型」查找频道,设备行的频道占用数字与频道别名都能取到。
- 绑定结果分类:绑定失败会按原因区分(无目标 / 频段非法 / 无网络),状态行直接给出具体原因,而不是笼统的一句失败。
- 跟随选中不再强制居中:配对源变化时用
revealP2P,只在目标不在可视区时滚动,不再把玩家从当前位置拽回去;显式跳转仍用navigateToP2P。
修复
- 配置模式界面崩溃(
NumberFormatException):1.7.10 的频段是 64 位,服务端下发的是 16 位十六进制(如000001A13FF44AA4)。树在排序频道时用Integer.parseInt(frequency, 16)解析,必然溢出并抛出异常,而这个排序发生在界面 tick 的updateScreen→tryAutoNavigateToPendingBind→navigateToP2P→rebuildTree调用链里,于是直接Ticking screen崩溃。现在统一改用 64 位无符号比较(ChannelInfo.compareFrequency),遇到脏数据退化为长度 + 字典序,不再有异常逃逸到渲染循环。 - 配置模式界面崩溃(
ClassCastException):渲染 P2P 树的类型行时,P2PTypeNames用ResourceLocation去查 1.7.10 的物品注册表,而这张表的键是String,RegistryNamespaced.getObject(Object)会先做强转,于是抛ResourceLocation cannot be cast to String,客户端在Rendering screen阶段崩溃。现在类型名只查本模组自己的语言键,不再碰注册表。 - 类型名显示成类名:
P2PManager.getP2PType只剥掉了PartP2PTunnel前缀,PartP2PRedstone/PartP2PItems这类部件会把PartP2PRedstone原样画到树上。现在两个前缀都剥掉,配合 14 条gui.advanced_memory_card.p2p_type.*语言键(中英各一份),树上显示「红石 P2P 隧道」「物品 P2P 隧道」等名称;第三方模组的 P2P 部件查不到译名时退回原始 token。 - ME 频道的占用数字不显示:
P2PChannelUsage.ME_TYPE沿用基准的me_p2p_tunnel,而 1.7.10 的类型 token 是ME,两者永远不相等,导致 ME 频道的占用统计与检查器里的 ME 判定一直失效。现在统一为ME,输出端设备行与频道行重新显示占用数字。 - 批量搜索结果排序:搜索模式下频道结果的频段排序有同样的
Integer.parseInt溢出问题,一并改掉。 - 配对条频段下拉顺序错乱:下拉列表的排序把解析失败的值全部塞成
Integer.MAX_VALUE,所有 64 位频段排序值相同,顺序实际上是随机的;现在按真实数值从小到大。 - 最高位为 1 的频段被当成「未绑定」:服务端解析频段用的是有符号
Long.parseLong,F000000000000001这类频段会解析失败并被当作 0,导致渲染、高亮与频段改名静默失效;现在改用Long.parseUnsignedLong。 - 树整块点不动:基准里「鼠标命中控件 → 调
onClick」是 AE2AbstractWidget#mouseClicked干的活,旧版Widget基类的mouseClicked只返回false,于是P2PTreeWidget.onClick从头到尾没有调用者 —— 点设备行不选中、点频段行不展开、Ctrl 多选与框选起手也都没了。现在树的mouseClicked自己派发:左键落在树矩形内就调onClick并返回true。 - 滚动条被树吃掉点击:滚动条的矩形压在树右缘的 14px 留白上,而事件的派发顺序是「树 → 滚动条」,树开始消费点击之后滑块就再也拖不动了。现在滚动条先于树判定。
- 界面显示原始翻译键:
TranslateHelper.Keys里的键都是GUI_PREFIX + "advanced_memory_card.<组>.",拼出来是双份命名空间的gui.advanced_memory_card.advanced_memory_card.<组>.*。历史组(复制模式、检查器、按钮、状态、树、聊天、tooltip)的语言文件一直是双份,能对上;但新加的action_bar/pair/status_line/p2p_type写成了单份,tree与tree_col干脆没有写,于是这 39 个键在游戏里按原样显示。现在两语文件统一为双份命名空间,并补齐tree_col.{name,frequency,summary}与tree.{summary_channel,summary_channel_plain,summary_type,role_input,role_output,prefix_input,prefix_output}共 10 条新键。 - P2P 类型名的键前缀:
P2PTypeNames的LANG_PREFIX同步改成双份命名空间,与其余各组保持一致。 - 配置界面所有操作按钮失效(绑定 / 改名 / 传送 / 高亮 / 刷新):
ServerTaskQueue.register()把ServerTaskQueue.class传给了 FML 的EventBus.register(Object)。1.7.10 的EventBus只有register(Object),没有register(Class<?>)重载,它扫描的是target.getClass().getMethods()—— 传Class对象时扫描的是java.lang.Class自己的方法,onServerTick一个都没注册。于是动作包全部入队、队列从未被消费,所有服务端 action 静默失效。现在注册单例实例,并把onServerTick改成实例方法。 - 客户端延迟任务同样不执行:
ClientTickTasks.register()有同样的register(Class)误用。传送后的到达等待、延迟高亮都挂在这个队列上,队列不跑,这些收尾动作也就不会发生。同样改为注册实例。 - 高亮不关界面、不渲染、不刷聊天栏:界面从未在
onHighlightP2P/onHighlightChannel里关闭;现在按基准 1.21.1 的顺序执行「发包 → 关界面 → 转头」,并补上频段高亮时转向第一台输入端的逻辑。 - 高亮发包后立刻关界面会丢动作:动作包被延迟到下一个服务端 tick 执行,而关容器的包先到,执行时
player.openContainer已回到玩家背包,instanceof IActionMenu失败、动作被丢弃。现在动作包处理器在收到包时就抓住菜单实例,菜单关掉后仍持有p2pManager与玩家背包,动作照常执行。 - 高亮始终不渲染(客户端找不到部件):
ClientHighlightHandler.findPart用DimensionManager.getWorld(dimId)。1.7.10 的DimensionManager是服务端注册表,setWorld只在WorldServer/MinecraftServer里调用,客户端loadWorld不会注册WorldClient:专用服务器客户端上getWorld恒为null,单机拿到的是服务端WorldServer及其部件,都不是渲染用的那一份。现在改用Minecraft.theWorld,并且只处理当前维度(跨维度的部件本来就看不见)。 - 远程 / 未加载区块的传送与高亮静默失败:
parsingP2P只走世界侧getTileEntity,区块未加载或朝向索引对不上时返回null。改名早已用findP2PByPositionString兜底,传送 / 高亮 / 切换输入端 / 设配对源现在统一走resolveP2P,失败时同样退回已分析部件表。 - 同维度传送白跑一次维度转移:1.7.10 的
transferPlayerToDimension不判断j == dimension,会把玩家 danger-remove 再传回。现在只在维度不同时调用。 - 传送后界面不关:服务端已经完成位移,客户端还对着 GUI,玩家会以为按钮没反应。现在发包后立即关界面,与基准 1.21.1 的
doTeleport一致。 - 传送后仍不亮:只判坐标会在「坐标先到、区块后到」的窗口里触发高亮,但
findPart仍为 null,高亮被静默丢掉。现在客户端条件同时要求目标部件可查,服务端在 2 秒 / 4 秒各补发一次HighlightPacket,复用「高亮」按钮那条已验证可用的渲染路径。 - 设备行第一次点击后选中态被清掉:
TreeNode.p2pNodeId()用的是dimension()且漏掉:frequency,与getNodeId()的 P2P 分支拼法不一致。点击设备会触发set_pending_bind,服务端回包后自动导航用p2pNodeId恢复选中,匹配失败就把选中态当成节点消失清掉;第二次点击时 pending 已相同、不再导航,所以能选上。现在两者逐字一致(维度 id + 坐标 + 朝向 + 频段)。 - 右侧检查器多出一块白色矩形:
DetailPanelWidget.render()先用paletteSurface铺满整块面板,盖住了基准底图。现在移除这次填充,面板底色交给config_mode_menu.png。 - 批量模式多选只绑定一台:多选集合的键
positionKey用info.dimension()(维度名,如Overworld)拼P2PPosition,而p2pInfoMap的键用的是String.valueOf(dimensionId)(如0);P2PPosition.equals又把 dimension 纳入比较,于是p2pInfoMap.get(key)全部落空,getSourceCandidates()退回单选的selectedP2PInfo,doBind()只发bind_frequency而不是bind_frequency_batch。现在positionKey统一用维度 id 字符串,多选反查能拿全所有设备。 - 按住左键从按钮上滑出、再移动鼠标时会误触发该按钮:现在
mouseMovedOrUp只在button >= 0时派发 Up 事件,滑出即取消。 - P2P 绑定的角色仲裁对 ME 隧道也一视同仁:一个频段只保留一个输入端,其余自动作为输出端,避免整条 ME 通道永久显示未连接。
- 拒绝绑定全零频段(
0000…0000):这类频段在 AE2 里代表「未连接」,不能作为绑定目标。 - 切换输入端时先降级旧输入端、再提升目标设备,避免中间态出现两个输入端。
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:pDQWt1Yf:PBIj39IE"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:pDQWt1Yf:PBIj39IE"
}

