You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Lua向jQuery传递的武器HUD逻辑迁移至React?

React重构Lua服务器HUD武器显示逻辑

原功能说明

基于Lua服务器的HUD,实现玩家空手时显示拳头图片、持械时显示对应武器图片及弹药信息,原使用jQuery操作DOM,现切换到React需重构逻辑。


原Lua代码

SetInterval("run",150, function()
    local ped = PlayerPedId()
    local oldWeaponHash = nil
    local currentWeaponHash = nil
    local oldWeaponAmmo = nil
    local oldClipAmmo = nil
    currentWeaponHash = GetSelectedPedWeapon(ped)
    oldWeaponHash = currentWeaponHash

    local weaponName = nil
    local _, maxAmmo = GetMaxAmmo(ped, currentWeaponHash)

    for _k, value in pairs(weapons) do
        if currentWeaponHash == GetHashKey(value) then
            weaponName = value
        end
    end

    -- 判断是否空手(哈希值-1569615261对应空手状态)
    if currentWeaponHash == -1569615261 or currentWeaponHash == nil  then
        SendNUIMessage({
            show2 = true, -- 标记显示拳头图片
            show3 = false -- 隐藏武器图片
        })
    else
        if weaponName ~= nil then
            local maxClipAmmo = GetMaxAmmoInClip(ped, currentWeaponHash, 1)
            local _, clipAmmo = GetAmmoInClip(ped, currentWeaponHash)
            local weaponAmmo = GetAmmoInPedWeapon(ped, currentWeaponHash)
    
            oldWeaponAmmo = weaponAmmo
            oldClipAmmo = clipAmmo
            SendNUIMessage({
                updateWeapon = true,
                show2 = false, -- 隐藏拳头图片
                show3 = true, -- 显示当前武器图片
                weaponName = weaponName,
                maxAmmo = maxAmmo,
                maxClipAmmo = maxClipAmmo,
                clipAmmo = clipAmmo,
                weaponAmmo = weaponAmmo
            })
            SetNuiFocus(false, false)
        end
    end
end)

原jQuery代码

if (data.show2 == true) {
    var Url = `<img class="stoljpi mt-1" id="weapon_image" src="./assets/imgs/weapons/unarmed.png" alt="">`
    $("#slike").html(Url)
    $("#slike").fadeIn("100")
} 
if (data.show2 == false) {
    var Url = `<img class="stoljpi mt-1" id="weapon_image" src="./assets/imgs/weapons/${data.weaponName}.png" alt="">`
    $("#slike").html(Url)
}

React重构方案

核心思路

用React状态驱动视图替代jQuery的DOM操作,通过监听NUI消息同步Lua传来的武器状态,由React自动渲染对应UI。

1. 实现武器状态上下文(共享状态)

创建Context统一管理武器状态,方便组件间共享数据:

import { useState, useEffect, createContext, useContext } from 'react';

// 创建武器状态上下文
const WeaponContext = createContext();

// 状态提供者组件
export const WeaponProvider = ({ children }) => {
  const [weaponState, setWeaponState] = useState({
    isUnarmed: true, // 是否空手
    weaponName: '', // 武器名称
    maxAmmo: 0, // 总弹药上限
    maxClipAmmo: 0, // 弹夹上限
    clipAmmo: 0, // 当前弹夹弹药
    weaponAmmo: 0 // 总剩余弹药
  });

  useEffect(() => {
    // 监听Lua发送的NUI消息
    const handleNuiMessage = (event) => {
      const data = event.data;
      if (data.show2 !== undefined) {
        // 构建新状态
        const newState = {
          ...weaponState,
          isUnarmed: data.show2,
          weaponName: data.weaponName || ''
        };
        // 持械时同步弹药数据
        if (!data.show2) {
          newState.maxAmmo = data.maxAmmo;
          newState.maxClipAmmo = data.maxClipAmmo;
          newState.clipAmmo = data.clipAmmo;
          newState.weaponAmmo = data.weaponAmmo;
        }
        setWeaponState(newState);
      }
    };

    window.addEventListener('message', handleNuiMessage);
    // 组件卸载时移除监听
    return () => window.removeEventListener('message', handleNuiMessage);
  }, [weaponState]);

  return (
    <WeaponContext.Provider value={weaponState}>
      {children}
    </WeaponContext.Provider>
  );
};

2. 实现武器HUD组件

基于状态渲染UI,替代jQuery的DOM拼接:

// 武器HUD展示组件
export const WeaponHUD = () => {
  const weaponState = useContext(WeaponContext);

  return (
    <div id="slike" className="weapon-hud-container">
      {/* 根据状态渲染对应图片 */}
      {weaponState.isUnarmed ? (
        <img 
          className="stoljpi mt-1" 
          id="weapon_image" 
          src="./assets/imgs/weapons/unarmed.png" 
          alt="空手"
          style={{ display: 'block', animation: 'fadeIn 0.1s ease-in-out' }}
        />
      ) : (
        <img 
          className="stoljpi mt-1" 
          id="weapon_image" 
          src={`./assets/imgs/weapons/${weaponState.weaponName}.png`} 
          alt={weaponState.weaponName}
        />
      )}
      {/* 可选:添加弹药信息显示 */}
      {!weaponState.isUnarmed && (
        <div className="ammo-display">
          <span className="clip-ammo">{weaponState.clipAmmo}/{weaponState.maxClipAmmo}</span>
          <span className="total-ammo">/{weaponState.weaponAmmo}</span>
        </div>
      )}
    </div>
  );
};

3. 入口组件集成

在React入口文件中包裹状态提供者:

import { WeaponProvider } from './WeaponContext';
import { WeaponHUD } from './WeaponHUD';

function App() {
  return (
    <WeaponProvider>
      <div className="hud-container">
        <WeaponHUD />
        {/* 其他HUD组件 */}
      </div>
    </WeaponProvider>
  );
}

export default App;

Lua代码微调

原Lua代码无需大幅修改,仅需移除SendReactMessage('pesnica')(该消息已被show2字段替代),保持SendNUIMessage的字段结构即可。


内容的提问来源于stack exchange,提问作者whereiam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:21:25