Switchboard

Software, photography, music, and more.

ItemOfTheDay

Posted 06/23/2026 by Tim Northrop

I made a small minigame for Minecraft Paper servers. Each day, a new item is selected as the "Item of the Day" and players can collect it and exchange it for a reward. Server operators have the ability to set or shuffle the Item of the Day (IOTD), set the reward for the current Item of the Day, and set the default reward, which is reverted back to on date change or when the IOTD is shuffled.

You can download the .jar from the plugin's CurseForge page or Modrinth Page to add it to your server. Find the source code on the GitHub repository. See the plugin in action below:

On first startup, the plugin creates a config.yml file to keep track of a list of blacklisted-items, among other things. By default, this list contains all items which are unobtainable in survival mode. To change the list of blacklisted items, edit this list in plugins/ItemOfTheDay/config.yml and restart the server for changes to take effect.

public class ItemOfTheDayPlugin extends JavaPlugin {
    ...
    private final Registry<ItemType> itemReg = RegistryAccess.registryAccess().getRegistry(RegistryKey.ITEM);

    @Override
    public void onEnable() {
        saveDefaultConfig();

        DateWatcher dw = new DateWatcher(this);
        dw.start();

        if (!getConfig().contains("blacklisted-items")) {
            List<String> items = itemReg.stream()
                    .filter(Utils::isUnobtainable)
                    .map(m -> m.getKey().asString())
                    .sorted()
                    .toList();

            getConfig().set("blacklisted-items", items);
            saveConfig();
        }
        blacklistedItems = new HashSet<>(getConfig().getStringList("blacklisted-items"));
        ...
    }
    ...
}

Also instantiated above is the DateWatcher class, which checks the date every 1200 server ticks (1min) against a saved LocalDate and shuffles the Item of the Day upon detecting a new date.

The config file also keeps track of the current IOTD and reward, the default reward, the date of last refresh, and the list of players (UUIDs) that have already claimed the current IOTD. In the remaining part of the onEnable() method, the plugin checks for a current IOTD:

    @Override
    public void onEnable() {
        ...
        long lastRefreshEpochDay = getConfig().getLong("last-refresh-epoch-date");
        if (lastRefreshEpochDay == 0) {
            shuffleIotd();
        } else {
            LocalDate lastRefresh = LocalDate.ofEpochDay(lastRefreshEpochDay);
            if (lastRefresh.isEqual(LocalDate.now())) {
                try {
                    setIotd(itemReg.getOrThrow(Key.key(Objects.requireNonNull(getConfig().getString("iotd")))));
                } catch (RuntimeException e) {
                    shuffleIotd();
                }

                ItemStack currentReward = getConfig().getItemStack("current-reward");
                setRewardOrDefault(currentReward);
            } else {
                shuffleIotd();
            }
        }

        registerCommands();

        getLogger().info("ItemOfTheDay enabled!");
    }

This allows the server to restart without losing track of the current IOTD, reward, and list of players who've claimed.

Also called above is registerCommands(), which uses a LiteralArgumentBuilder to construct the commands introduced by the plugin.

Available Commands:

- /iotd info: available to all players - displays info on the current Item of the Day and corresponding reward.

- /iotd exchange: available to all players - if the player has a single instance of the IOTD in their main hand and has not already exchanged today, the IOTD in their hand will be replaced with the current reward.

- /iotd shuffle: operator required - randomizes the IOTD and resets the reward back to the specified default reward.

- /iotd set <item>: operator required - sets the current IOTD to the specified item WITHOUT changing the reward.

- /iotd set-reward <item> <amount>: operator required - sets the current reward to the specified item and amount.

- /iotd set-default-reward <item> <amount>: operator required - sets the default reward (reverted to when IOTD is shuffled) to the specified item and amount.

- /iotd reset-claimed: operator required - clears the config's list of players (UUIDs) who have already exchanged for the IOTD.

Contributions and Issue Reporting

Report issues and contribute at the plugin's GitHub repository.

- Tim