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

使用Java插件的dataFolder时遇问题:无法找到文件存储位置

问题:Minecraft插件生成的玩家坐标日志文件找不到存储位置

我需要将Minecraft玩家的坐标输出保存到以玩家用户名命名的.log文件(例如用户名为abce时,文件名为abce.log),但在远程Shockbyte服务器的plugins文件夹中找不到该文件,它并未出现在我预期的路径里。以下是相关信息:

插件代码

package newestfile.here.newestplugin;

import java.util.UUID;
import java.nio.charset.StandardCharsets;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.io.File;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.entity.Player;
import org.bukkit.Location;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import java.nio.file.Files; 

public class Main extends JavaPlugin implements Listener
{
    boolean stopRepeater;
    HashMap<UUID, BukkitTask> tasks = new HashMap<>();
 
    private File dataFolder;
    
    public void onEnable() {
        Bukkit.getServer().getPluginManager().registerEvents(this,this);
        getLogger().info("HELLO! WELCOME TO THE TRACKER PLUGIN");
        dataFolder = new File(getDataFolder(), "data"); 
        dataFolder.mkdirs();
    }
    
    @EventHandler
    public void onLogin(final PlayerJoinEvent event) {
        final Player thePlayer = event.getPlayer();
        this.stopRepeater = true;
        final Location playerSpawnLocation = thePlayer.getLocation();
        getLogger().info("Welcome " + thePlayer.getName() + ". Your current position is: " + playerSpawnLocation);  
        BukkitTask task = getServer().getScheduler().runTaskTimer(this, () -> {
            if(this.stopRepeater) {
                this.logToFile(thePlayer, thePlayer.getLocation());
            }
        }, 0L, 20L);
        tasks.put(thePlayer.getUniqueId(),task);}
    
    @EventHandler
    public void onQuit(final PlayerQuitEvent event) {
        Player thePlayer = event.getPlayer(); 
        if(!thePlayer.isOnline()) {
            this.stopRepeater = false;  
            getLogger().info(String.valueOf(event.getPlayer().getName()) + " has left the game");
            BukkitTask task = tasks.remove(thePlayer.getUniqueId()); 
            if(task != null) { 
               task.cancel();
            }
        }
    }

    public void logToFile(final Player currentPlayer, final Location playerCurrentLocation) {
        try {
            String content = String.valueOf(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date())) + " CurrentLocation(x,y,z): " + playerCurrentLocation.getBlockX() + " " + playerCurrentLocation.getBlockY() + " " + playerCurrentLocation.getBlockZ() + "\n";
            final File file = new File(dataFolder, currentPlayer.getName() + ".log");
            if (!file.exists()) {
                file.createNewFile();
            }
            Files.write(file.toPath(),content.getBytes(StandardCharsets.UTF_8),StandardOpenOption.APPEND);
        } catch (Exception e) {
            e.printStackTrace();
        }
     }
}

预期存储路径说明

预期路径为plugins/NewestPlugin/data文件夹,当前该文件夹为空。

latest.log输出说明

日志显示插件已正常加载(输出HELLO! WELCOME TO THE TRACKER PLUGIN),玩家加入时会记录坐标(例如Welcome Caledonian26. Your current position is: Location{world=CraftWorld{name=world},x=...,y=...,z=...,pitch=...,yaw=...}),玩家退出时也有对应日志记录(例如Caledonian26 has left the game)。


问题排查与解决方案

1. 日志文件实际存储位置

代码中getDataFolder()返回的是插件专属数据文件夹,路径为plugins/你的插件jar包名/(比如插件jar是NewestPlugin.jar,则路径为plugins/NewestPlugin/data/)。你需要进入plugins下对应插件的子文件夹,而非plugins根目录。

2. 代码逻辑修复

  • 全局变量stopRepeater会导致多玩家在线时,一个玩家退出就停止所有玩家的日志记录,需改为按玩家UUID单独维护状态:
// 替换原全局变量stopRepeater
HashMap<UUID, Boolean> playerTrackingStatus = new HashMap<>();

// 修改onLogin方法
@EventHandler
public void onLogin(final PlayerJoinEvent event) {
    final Player thePlayer = event.getPlayer();
    playerTrackingStatus.put(thePlayer.getUniqueId(), true);
    final Location playerSpawnLocation = thePlayer.getLocation();
    getLogger().info("Welcome " + thePlayer.getName() + ". Your current position is: " + playerSpawnLocation);  
    BukkitTask task = getServer().getScheduler().runTaskTimer(this, () -> {
        if(playerTrackingStatus.getOrDefault(thePlayer.getUniqueId(), false)) {
            this.logToFile(thePlayer, thePlayer.getLocation());
        }
    }, 0L, 20L);
    tasks.put(thePlayer.getUniqueId(),task);
}

// 修改onQuit方法
@EventHandler
public void onQuit(final PlayerQuitEvent event) {
    Player thePlayer = event.getPlayer(); 
    playerTrackingStatus.remove(thePlayer.getUniqueId());
    getLogger().info(event.getPlayer().getName() + " has left the game");
    BukkitTask task = tasks.remove(thePlayer.getUniqueId()); 
    if(task != null) { 
       task.cancel();
    }
}
  • onQuit方法中的if(!thePlayer.isOnline())判断多余,PlayerQuitEvent触发时玩家已离线,可直接移除该判断。

3. Shockbyte服务器文件访问

登录Shockbyte控制面板,进入文件管理器,找到plugins文件夹后进入对应插件的子目录,即可在data文件夹中找到玩家日志文件。若仍找不到,可通过服务器控制台查看插件加载日志,确认数据文件夹的实际路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:31:03