GuiBetterAchievements

基本信息

属性 值
类名 betterachievements.gui.GuiBetterAchievements
父类 net.minecraft.client.gui.GuiScreen
SideOnly Side.CLIENT
源文件 src/main/java/betterachievements/gui/GuiBetterAchievements.java

功能

完整重写后的成就界面。支持多 AchievementPage 切换、鼠标滚轮缩放、鼠标拖拽、自定义箭头颜色、Tooltip、彩虹模式颜色、游戏内中键改页签图标、创造模式右键直接解锁(含父链解锁)。

由 GuiOpenHandler 在 GuiOpenEvent 中拦截 GuiAchievements 替换而来,prevScreen 与 currentPage 通过反射从原版 GuiAchievements.field_146562_a 和 currentPage 字段读出,再将 currentPage + 1 作为参数传入构造函数(避免与 AchievementRegistry.mcPage 冲突)。

构造

public GuiBetterAchievements(GuiScreen currentScreen, int page)
参数 说明
currentScreen 原版父界面(用于 “Done” 按钮返回)
page 1-based 页索引;0 表示恢复上次记忆的 lastPage(静态字段)

关键常量

常量 值 说明
blockSize 16 背景方块尺寸
maxTabs 9 单页可见标签数
guiWidth / guiHeight 252 / 202 GUI 总尺寸
tabWidth / tabHeight 28 / 32 标签尺寸
achievementSize / achievementInnerSize 24 / 22 成就方框外/内尺寸
minDisplayColumn AchievementList.minDisplayColumn * 24 - 240 视图左边界
maxDisplayColumn AchievementList.maxDisplayColumn * 24 视图右边界
minDisplayRow AchievementList.minDisplayRow * 24 - 240 视图上边界
maxDisplayRow AchievementList.maxDisplayRow * 24 视图下边界
scaleJump 0.25F 缩放步进
minZoom 1.0F 默认最小缩放
maxZoom 2.0F 默认最大缩放

静态可配置字段(由 ConfigHandler 写入)

字段 默认 说明
colourUnlocked #A0A0A0 已解锁成就箭头颜色(int)
colourCanUnlock #00FF00 可解锁成就箭头颜色(int)
colourCantUnlock #000000 不可解锁成就箭头颜色(int)
colourUnlockedRainbow 等 false 是否启用彩虹模式(替代固定颜色)
colourUnlockedRainbowSettings 等 null 彩虹参数数组
scrollButtons true 是否显示左右翻页按钮(“<” / “>”)
iconReset false 是否启用游戏中键改页签图标
userColourOverride false 是否强制使用用户箭头颜色,覆盖 mod 提供方

交互

触发 行为
ESC / 物品栏键 关闭 GUI(mc.displayGuiScreen(null))
← / → 切换 AchievementPage(环绕跳转)
Done 按钮 返回 prevScreen
Old Screen 按钮 打开 GuiAchievementsOld(绕过拦截器)
鼠标左键拖拽 平移视图(仅在内部区 inInnerScreen 内有效)
鼠标滚轮(标签上方) 滚动页签窗口(tabsOffset 增减)
鼠标滚轮(成就区) 缩放视图
鼠标左键点击标签 切换当前 AchievementPage
鼠标悬停成就 + 左键 鼠标按住可解锁(仅 GuiOpenHandler 进入的新状态)
鼠标悬停成就 + 右键 创造模式发送 AchievementUnlockMessage 解锁(含父链递归)
鼠标悬停成就 + 中键 + iconReset 把当前页签图标改为该成就图标

行为:成就渲染

drawAchievement(Achievement):

  1. 计算该成就到最近已解锁父节点的 depth = statFileWriter.func_150874_c(achievement)(0…5)。
  2. 若 depth >= 5 跳过绘制(说明太远)。
  3. 计算亮度:unlocked → 0.75F、canUnlock → 1.0F、depth<3 → 0.3F、depth<4 → 0.2F、depth<5 → 0.1F。
  4. 若成就实现 ICustomBackgroundColour,按其返回值上色;否则按亮度灰度上色。
  5. 绑定 sprites.png 绘制 26×26 背景方块(special 时换 sprite)。
  6. 若实现 ICustomIconRenderer,调用 renderIcon;否则使用 RenderItem 绘制 achievement.theItemStack,未解锁时降低亮度并禁用 color。

行为:箭头渲染

drawArrow(achievement, colourCantUnlock, colourCanUnlock, colourUnlocked):

  • 仅当 depth < 5 时绘制。
  • 根据 unlocked / canUnlock 选择颜色(顺序:unlocked → unlocked, canUnlock → canUnlock, 否则 → cantUnlock)。
  • 画水平线 + 垂直线 + 箭头头部 sprite(4 个方向 sprite:arrowRightX/Y/arrowLeftX/Y/arrowUpX/Y/arrowDownX/Y)。
  • 优先顺序:ICustomArrows.getColourFor*() 覆盖(除非 userColourOverride=true),否则使用配置/彩虹颜色。

行为:背景渲染

drawAchievementsBackground(page):

  1. GL11.glTranslatef(left, top + borderWidthY, -200.0F) 移动到内容区。
  2. 若页实现 ICustomBackground,调用其 drawBackground(drawBackground 自己处理缩放)。
  3. 否则用方块纹理(TextureMap.locationBlocksTexture)绘制伪地形背景:
    • 随机种子 session.getPlayerID().hashCode() + (dragY+y) + (dragX+x)*16
    • r = random.nextInt(1 + dragY + y) + (dragY + y) / 2
    • r == 40 → diamond_ore / redstone_ore(1/3 概率);r == 20 → iron_ore;r == 12 → coal_ore;r > 60 → bedrock;r > 4 → stone;r > 0 → dirt;其余 → grass。
    • 颜色按 (dragY+y)/80.0F 调暗:0.7F - dragY/80.0F。
    • 缩放应用 1/scale。

行为:Tooltip

drawMouseOverAchievement(mouseX, mouseY):

  • 仅在鼠标在内部区时调用。
  • 若实现 ICustomTooltip,调用 renderTooltip(mouseX, mouseY, statFileWriter)。
  • 否则按 defaultTooltipWidth=120 绘制文本框:
    • 不可解锁且 depth>3 → 直接 return(不显示 tooltip)。
    • 不可解锁时 desc = achievement.requires(parentTitle);depth==3 时 title = achievement.unknown。
    • 已解锁时 tooltipHeight += lineSize 以容纳 “Taken” 提示。
    • 颜色:canUnlock → (special ? -128 : -1);否则 (special ? -8355776 : -8355712)。
    • 描述用 -6250336 灰色,已解锁 achievement.taken 用 -7302913。
  • 释放 hoveredAchievement 为 null。

缩放与拖拽

doDrag(mouseX, mouseY):

  • 鼠标按住左键时若在 inInnerScreen:
    • 首次按下 newDrag=true,不移动,只记录 prevMouseX/Y。
    • 后续帧 xPos -= (mouseX - prevMouseX) * scale、yPos 同理。
  • 鼠标松开时 newDrag=true。
  • 视图被 minDisplayColumn/max/minDisplayRow/max 夹紧。

doZoom(page):

  • 滚轮:scale += 0.25F 或 -= 0.25F。
  • 范围:ICustomScale.getMinScale()/getMaxScale() 或默认 1.0F / 2.0F。
  • 缩放后维持视觉中心:xPos -= (newW - prevW)/2,yPos 同理。

doTabScroll():

  • 在标签上方滚轮:tabsOffset++ 或 --。
  • 范围:[0, pages.size() - maxTabs/3*2]。

相关条目