需要反作弊方案?试试 Kauri Anticheat!
Atlas 是一个一体化且高度集成的 API,专为希望提升其 Bukkit 插件或反作弊系统性能的开发者设计。它提供了一套强大的工具集,旨在简化开发流程并增强插件功能。
Atlas 包含以下核心组件,帮助开发者构建高效、稳定的插件:
将以下配置添加到您的 pom.xml 文件中以使用 Atlas:
<repositories>
<repository>
<id>funkemunky-releases</id>
<url>http://nexus.funkemunky.cc/content/repositories/releases/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>cc.funkemunky.plugins</groupId>
<artifactId>Atlas</artifactId>
<version>1.5.4</version>
<scope>provided</scope>
</dependency>
</dependencies>您可以创建继承自 AtlasEvent 的自定义事件。以下是一个示例:
package cc.funkemunky.anticheat.api.event;
import cc.funkemunky.api.events.AtlasEvent;
import cc.funkemunky.api.events.Cancellable;
import lombok.AllArgsConstructor;
import lombok.Getter;
public class TickEvent extends AtlasEvent implements Cancellable {
private int currentTick;
public TickEvent(int currentTick) {
this.currentTick = currentTick;
}
public int getCurrentTick() {
return currentTick;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public void setCancelled(boolean b) {
}
}new BukkitRunnable() {
public void run() {
TickEvent tickEvent = new TickEvent(currentTicks++);
Atlas.getInstance().getEventManager().callEvent(tickEvent);
}
}.runTaskTimerAsynchronously(this, 1L, 1L);创建一个类并实现 AtlasListener 接口,使用 @Listen 注解来监听事件:
package cc.funkemunky.anticheat.impl.listeners;
import cc.funkemunky.anticheat.Rock;
import cc.funkemunky.anticheat.api.data.PlayerData;
import cc.funkemunky.anticheat.api.event.TickEvent;
import cc.funkemunky.api.Atlas;
import cc.funkemunky.api.events.AtlasListener;
import cc.funkemunky.api.events.Listen;
import cc.funkemunky.api.utils.Init;
@Init
public class FunkeListeners implements AtlasListener {
@Listen
public void onTickEvent(TickEvent event) {
Atlas.getInstance().executeTask(() -> Rock.getInstance().getDataManager().getDataObjects().keySet().forEach(key -> {
PlayerData data = Rock.getInstance().getDataManager().getDataObjects().get(key);
data.getActionProcessor().update(data);
}));
}
}public void onEnable() {
Atlas.getInstance().getEventManager().registerListeners(new FunkeListeners(), this);
}使用 TinyProtocolHandler 发送自定义数据包:
TinyProtocolHandler.sendPacket(e.getPlayer(), new WrappedOutKeepAlivePacket(233 + e.getPlayer().getEntityId() + 935));通过监听 PacketRecieveEvent 来处理客户端发送的数据包:
@Listen
public void onEvent(PacketRecieveEvent e) {
if (e.getType().equals(Packet.Client.ENTITY_ACTION)) {
WrappedInEntityActionPacket packet = new WrappedInEntityActionPacket(e.getPacket(), e.getPlayer());
switch (packet.getAction()) {
case START_SNEAKING:
data.skiderino.sneak = true;
break;
case STOP_SNEAKING:
data.skiderino.sneak = false;
break;
case START_SPRINTING:
data.skiderino.sprint = true;
break;
case STOP_SPRINTING:
data.skiderino.sprint = false;
break;
}
}
}通过监听 PacketSendEvent 来处理服务器发送给客户端的数据包:
@Listen
public void onPacketSend(PacketSendEvent e) {
PlayerData data = Fiona.getInstance().getDataManager().getPlayerData(e.getPlayer());
if (data != null) {
switch (e.getType()) {
case Packet.Server.KEEP_ALIVE:
data.lastServerKeepAlive = System.currentTimeMillis();
break;
case Packet.Server.ENTITY_METADATA:
WrappedOutEntityMetadata wrapper = new WrappedOutEntityMetadata(e.getPacket(), e.getPlayer());
if(wrapper.getObjects().size() > 0) {
if(wrapper.getObjects().get(0).getObject() instanceof Byte && (data.isUsingItem = ((Byte) wrapper.getObjects().get(0).getObject()) % 0x5 == 1)) {
data.lastUseItem.reset();
}
}
break;
}
}
}此示例展示了如何获取被点击方块的碰撞箱并可视化其边界:
@EventHandler(priority = EventPriority.HIGHEST)
public void onEvent(PlayerInteractEvent event) {
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
if (event.getItem() != null && event.getItem().getType().equals(Material.BLAZE_ROD) && event.getItem().getItemMeta().getDisplayName().equalsIgnoreCase(Color.Red + "Magic Box Wand")) {
Block block = event.getClickedBlock();
event.getPlayer().sendMessage(block.getType().name() + "'s Data: " + block.getData());
for (BoundingBox box : Atlas.getInstance().getBlockBoxManager().getBlockBox().getSpecificBox(block.getLocation())) {
for (float x = box.minX; x < box.maxX; x += 0.2f) {
for (float y = box.minY; y < box.maxY; y += 0.2f) {
for (float z = box.minZ; z < box.maxZ; z += 0.2f) {
WrappedPacketPlayOutWorldParticle packet = new WrappedPacketPlayOutWorldParticle(WrappedEnumParticle.FLAME, true, x, y, z, 0f, 0f, 0f, 0f, 1, null);
packet.sendPacket(event.getPlayer());
}
}
}
event.getPlayer().sendMessage(ReflectionsUtil.getVanillaBlock(event.getClickedBlock()).getClass().getSimpleName() + ": " + box.toString());
}
}
}
}List<BoundingBox> box = Atlas.getInstance().getBlockBoxManager().getBlockBox().getCollidingBoxes(to.getWorld(), data.boundingBox.grow(0.5f, 0.1f, 0.5f).subtract(0, 0.5f, 0, 0, 0, 0));
CollisionAssessment assessment = new CollisionAssessment(data.boundingBox, data);
box.forEach(bb -> assessment.assessBox(bb, to.getWorld()));MiscUtils.getEntityBoundingBox(e.getPlayer());如果您有任何疑问,请查阅 [官方 Wiki](这里)。该 Wiki 仍在持续更新和完善中。
友情链接: 网易我的世界 | 泰拉瑞亚 | ocent云计算 | 米饭Minecraft插件文档 | 友链合作
历史访问人数:2,586,120 | 历史访问人次:3,137,426
今日访问人数:6,592 | 今日访问人次:7,047
昨日访问人数:24,332 | 昨日访问人次:29,698
Copyright © 2019-2026 我的世界服务器列表站. All rights reserved.
❤ Powered by GermMC 京ICP备17023959号-6