Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问clear审计提醒

hytale-networkinghytale 网络

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

466

周安装

20

GitHub Stars

3

下载量

163
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:hytale-networking(hytale 网络)
来源仓库:https://github.com/mnkyarts/hytale-skills
仓库路径:skills/hytale-networking
安装命令:
npx skills add https://github.com/mnkyarts/hytale-skills --skill hytale-networking
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/mnkyarts/hytale-skills --skill hytale-networking

简介

用于辅助前端页面、组件、样式和交互逻辑的开发与维护,适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码。

  • 适用于前端开发、网络交互和组件管理等场景,帮助 Agent 处理前端网络相关功能。
  • 使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装,需结合原始 README 核验具体用法和功能细节。
  • 可结合来源仓库和 SKILL.md 继续核验具体用法,确保与当前宿主环境兼容。

SKILL.md

Hytale Networking API

Complete guide for handling network packets and client-server communication.

When to use this skill

Use this skill when:

  • Sending data to clients
  • Receiving data from clients
  • Creating custom packet types
  • Implementing custom UI synchronization
  • Handling real-time player input
  • Syncing custom game state

Network Architecture Overview

Hytale uses a packet-based networking system:

Client <---> Server
   |           |
   Packet      Packet
   Encoder     Decoder
   |           |
   ByteBuf <-> ByteBuf

Protocol Components

ComponentDescription
PacketData structure with serialization
PacketRegistryMaps packet IDs to classes
PacketHandlerProcesses incoming packets
PacketEncoderSerializes packets to bytes
PacketDecoderDeserializes bytes to packets

Packet Structure

Packet Interface

All packets implement the Packet interface:

public interface Packet {
    int getId();
    void serialize(ByteBuf buffer);
    int computeSize();
}

Built-in Packet Categories

CategoryDirectionExamples
authBidirectionalAuthToken, ConnectAccept
connectionBidirectionalConnect, Disconnect, Ping
setupS→CWorldSettings, AssetInitialize
playerC→SClientMovement, MouseInteraction
entitiesS→CEntityUpdates, PlayAnimation
worldS→CSetChunk, ServerSetBlock
inventoryBidirectionalMoveItemStack, SetActiveSlot
windowBidirectionalOpenWindow, CloseWindow
interfaceS→CChatMessage, Notification
interactionBidirectionalSyncInteractionChains
cameraS→CCameraShakeEffect

Registering Packet Handlers

SubPacketHandler Pattern

Create modular packet handlers:

public class MyPacketHandler implements SubPacketHandler {
    private final MyPlugin plugin;

    public MyPacketHandler(MyPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public void registerHandlers(IPacketHandler handler) {
        // Register by packet ID
        handler.registerHandler(108, this::handleClientMovement);
        handler.registerHandler(111, this::handleMouseInteraction);

        // Or by packet class
        handler.registerHandler(CustomPacket.ID, this::handleCustomPacket);
    }

    private void handleClientMovement(Packet packet) {
        ClientMovement movement = (ClientMovement) packet;
        Vector3d position = movement.getPosition();
        // Process movement
    }

    private void handleMouseInteraction(Packet packet) {
        MouseInteraction interaction = (MouseInteraction) packet;
        // Process mouse input
    }
}

Registering in Plugin

@Override
protected void setup() {
    // Register packet handler with server manager
    ServerManager serverManager = HytaleServer.get().getServerManager();
    serverManager.registerSubPacketHandler(new MyPacketHandler(this));
}

Sending Packets

Send to Single Player

public void sendToPlayer(Player player, Packet packet) {
    player.getConnection().send(packet);
}

Send to Multiple Players

public void sendToAll(Packet packet) {
    for (Player player : HytaleServer.get().getOnlinePlayers()) {
        player.getConnection().send(packet);
    }
}

public void sendToWorld(World world, Packet packet) {
    for (Player player : world.getPlayers()) {
        player.getConnection().send(packet);
    }
}

public void sendToNearby(Vector3d position, double radius, Packet packet) {
    for (Player player : HytaleServer.get().getOnlinePlayers()) {
        if (player.getPosition().distanceTo(position) <= radius) {
            player.getConnection().send(packet);
        }
    }
}

Send with Callback

player.getConnection().send(packet).thenAccept(result -> {
    if (result.isSuccess()) {
        getLogger().atInfo().log("Packet sent successfully");
    } else {
        getLogger().atWarning().log("Packet failed to send: %s", result.getError());
    }
});

Built-in Packets Reference

Chat Message

// Send chat message to player
ChatMessage chatPacket = new ChatMessage(
    "Hello, World!",
    ChatMessage.Type.SYSTEM
);
player.getConnection().send(chatPacket);

Notification

// Send notification popup
Notification notification = new Notification(
    "Achievement Unlocked!",
    "You found the secret area",
    Notification.Type.SUCCESS,
    5000  // Duration in ms
);
player.getConnection().send(notification);

Play Sound

// Play sound at position
PlaySoundPacket sound = new PlaySoundPacket(
    "MyPlugin/Sounds/alert",
    position,
    1.0f,  // Volume
    1.0f   // Pitch
);
player.getConnection().send(sound);

Entity Updates

// Send entity state update
EntityUpdates updates = new EntityUpdates(
    entityId,
    new HashMap<>() {{
        put("health", health);
        put("position", position);
    }}
);
sendToNearby(position, 64, updates);

Set Block

// Update block on client
ServerSetBlock setBlock = new ServerSetBlock(
    position,
    blockTypeId,
    blockState
);
sendToWorld(world, setBlock);

Creating Custom Packets

Define Packet Class

public class MyCustomPacket implements Packet {
    public static final int ID = 5000; // Custom ID (use high numbers)

    private final String message;
    private final int value;
    private final Vector3d position;

    // Deserialize constructor
    public MyCustomPacket(ByteBuf buffer) {
        this.message = PacketIO.readString(buffer);
        this.value = buffer.readInt();
        this.position = new Vector3d(
            buffer.readDouble(),
            buffer.readDouble(),
            buffer.readDouble()
        );
    }

    // Create constructor
    public MyCustomPacket(String message, int value, Vector3d position) {
        this.message = message;
        this.value = value;
        this.position = position;
    }

    @Override
    public int getId() {
        return ID;
    }

    @Override
    public void serialize(ByteBuf buffer) {
        PacketIO.writeString(buffer, message);
        buffer.writeInt(value);
        buffer.writeDouble(position.x());
        buffer.writeDouble(position.y());
        buffer.writeDouble(position.z());
    }

    @Override
    public int computeSize() {
        return PacketIO.stringSize(message) + 4 + 24; // int + 3 doubles
    }

    // Getters
    public String getMessage() { return message; }
    public int getValue() { return value; }
    public Vector3d getPosition() { return position; }
}

Register Custom Packet

@Override
protected void setup() {
    PacketRegistry.register(
        MyCustomPacket.ID,
        MyCustomPacket.class,
        MyCustomPacket::new,  // Deserializer
        MyCustomPacket::validate  // Optional validator
    );
}

// Optional validation
public static boolean validate(ByteBuf buffer) {
    // Quick validation without full parse
    return buffer.readableBytes() >= 28; // Minimum size
}

PacketIO Utilities

Writing Data

// Primitives
buffer.writeByte(value);
buffer.writeShort(value);
buffer.writeInt(value);
buffer.writeLong(value);
buffer.writeFloat(value);
buffer.writeDouble(value);
buffer.writeBoolean(value);

// Strings
PacketIO.writeString(buffer, string);

// Variable-length integers
VarInt.write(buffer, value);

// Collections
PacketIO.writeArray(buffer, items, PacketIO::writeString);

// UUIDs
PacketIO.writeUUID(buffer, uuid);

// Vectors
PacketIO.writeVector3d(buffer, vector);
PacketIO.writeVector3i(buffer, blockPos);

// Optional values (nullable)
PacketIO.writeOptional(buffer, value, PacketIO::writeString);

Reading Data

// Primitives
byte b = buffer.readByte();
short s = buffer.readShort();
int i = buffer.readInt();
long l = buffer.readLong();
float f = buffer.readFloat();
double d = buffer.readDouble();
boolean bool = buffer.readBoolean();

// Strings
String str = PacketIO.readString(buffer);

// Variable-length integers
int var = VarInt.read(buffer);

// Collections
List<String> items = PacketIO.readArray(buffer, PacketIO::readString);

// UUIDs
UUID uuid = PacketIO.readUUID(buffer);

// Vectors
Vector3d pos = PacketIO.readVector3d(buffer);
Vector3i blockPos = PacketIO.readVector3i(buffer);

// Optional values
String optional = PacketIO.readOptional(buffer, PacketIO::readString);

Compression

Large packets are automatically compressed using Zstd:

public class LargeDataPacket implements Packet {
    public static final boolean IS_COMPRESSED = true;

    private final byte[] data;

    @Override
    public void serialize(ByteBuf buffer) {
        // Data will be automatically compressed if IS_COMPRESSED = true
        buffer.writeBytes(data);
    }
}

Manual compression:

// Compress
byte[] compressed = PacketIO.compress(data);

// Decompress
byte[] decompressed = PacketIO.decompress(compressed);

Client-Bound Custom UI

Custom Page Packet

Send custom UI pages to clients:

public void showCustomUI(Player player, String pageId, Map<String, Object> data) {
    CustomPage page = new CustomPage(
        pageId,
        serializeData(data)
    );
    player.getConnection().send(page);
}

Window System

// Open custom window
OpenWindow openWindow = new OpenWindow(
    windowId,
    "MyPlugin:CustomWindow",
    windowData
);
player.getConnection().send(openWindow);

// Handle window actions
handler.registerHandler(SendWindowAction.ID, packet -> {
    SendWindowAction action = (SendWindowAction) packet;
    int windowId = action.getWindowId();
    String actionType = action.getActionType();

    processWindowAction(player, windowId, actionType, action.getData());
});

// Close window
CloseWindow closeWindow = new CloseWindow(windowId);
player.getConnection().send(closeWindow);

Handling Client Input

Mouse Interaction

handler.registerHandler(MouseInteraction.ID, packet -> {
    MouseInteraction interaction = (MouseInteraction) packet;

    MouseButton button = interaction.getButton();
    Vector3d hitPos = interaction.getHitPosition();
    Vector3i blockPos = interaction.getBlockPosition();
    int entityId = interaction.getEntityId();

    if (button == MouseButton.RIGHT) {
        handleRightClick(player, hitPos, blockPos, entityId);
    } else if (button == MouseButton.LEFT) {
        handleLeftClick(player, hitPos, blockPos, entityId);
    }
});

Movement

handler.registerHandler(ClientMovement.ID, packet -> {
    ClientMovement movement = (ClientMovement) packet;

    Vector3d position = movement.getPosition();
    Vector3f rotation = movement.getRotation();
    Vector3d velocity = movement.getVelocity();
    boolean onGround = movement.isOnGround();

    validateMovement(player, position, velocity);
});

Key Input

handler.registerHandler(KeyInputPacket.ID, packet -> {
    KeyInputPacket input = (KeyInputPacket) packet;

    int keyCode = input.getKeyCode();
    boolean pressed = input.isPressed();

    handleKeyInput(player, keyCode, pressed);
});

Rate Limiting

Protect against packet spam:

public class RateLimitedHandler implements SubPacketHandler {
    private final Map<UUID, RateLimiter> limiters = new ConcurrentHashMap<>();

    @Override
    public void registerHandlers(IPacketHandler handler) {
        handler.registerHandler(MyPacket.ID, this::handleWithRateLimit);
    }

    private void handleWithRateLimit(Packet packet) {
        Player player = getPacketSender();
        RateLimiter limiter = limiters.computeIfAbsent(
            player.getUUID(),
            k -> new RateLimiter(10, 1000) // 10 per second
        );

        if (!limiter.tryAcquire()) {
            getLogger().atWarning().log("Rate limit exceeded for %s", player.getName());
            return;
        }

        processPacket(packet);
    }
}

Error Handling

handler.registerHandler(MyPacket.ID, packet -> {
    try {
        processPacket(packet);
    } catch (Exception e) {
        getLogger().atSevere().withCause(e).log("Error processing packet");

        // Optionally disconnect on critical errors
        if (e instanceof CriticalPacketError) {
            player.disconnect("Protocol error");
        }
    }
});

Packet Validation

public class ValidatedPacket implements Packet {
    @Override
    public void serialize(ByteBuf buffer) {
        // Add checksum
        int checksum = computeChecksum();
        buffer.writeInt(checksum);
        // Write data
    }

    public static ValidatedPacket deserialize(ByteBuf buffer) {
        int checksum = buffer.readInt();
        // Read data
        ValidatedPacket packet = new ValidatedPacket(...);

        if (packet.computeChecksum() != checksum) {
            throw new PacketValidationException("Checksum mismatch");
        }

        return packet;
    }
}

Performance Tips

Packet Batching

public class PacketBatcher {
    private final List<Packet> pending = new ArrayList<>();
    private final Player player;

    public void queue(Packet packet) {
        pending.add(packet);
    }

    public void flush() {
        if (pending.isEmpty()) return;

        // Send as batch if supported
        BatchPacket batch = new BatchPacket(pending);
        player.getConnection().send(batch);
        pending.clear();
    }
}

Delta Compression

Only send changes:

public class EntityStateSync {
    private final Map<Integer, EntityState> lastSent = new HashMap<>();

    public void sync(Player player, List<Entity> entities) {
        List<EntityDelta> deltas = new ArrayList<>();

        for (Entity entity : entities) {
            EntityState current = captureState(entity);
            EntityState last = lastSent.get(entity.getId());

            if (last == null || !current.equals(last)) {
                deltas.add(computeDelta(last, current));
                lastSent.put(entity.getId(), current);
            }
        }

        if (!deltas.isEmpty()) {
            player.getConnection().send(new EntityDeltaPacket(deltas));
        }
    }
}

Lazy Serialization

public class LazyPacket implements Packet {
    private ByteBuf cached;

    @Override
    public void serialize(ByteBuf buffer) {
        if (cached == null) {
            cached = Unpooled.buffer();
            doSerialize(cached);
        }
        buffer.writeBytes(cached.duplicate());
    }
}

Troubleshooting

Packet Not Received

  1. Verify packet ID is registered
  2. Check handler is registered
  3. Ensure packet is properly serialized
  4. Check for exceptions in handler

Deserialization Errors

  1. Verify read order matches write order
  2. Check data type sizes
  3. Validate buffer has enough bytes
  4. Add bounds checking

Connection Drops

  1. Check for unhandled exceptions
  2. Verify packet size limits
  3. Monitor bandwidth usage
  4. Check ping/timeout settings

See references/packet-list.md for complete packet catalog. See references/serialization.md for serialization patterns.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Cursor

27.2%
按下载量换算44

Claude Code

25.41%
按下载量换算41

github-copilot

20.27%
按下载量换算33

mcpjam

12.88%
按下载量换算21

zencoder

8.74%
按下载量换算14

crush

3.81%
按下载量换算6

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills