pala M-market-1: market commandes (sell/list/buy/cancel)
This commit is contained in:
@@ -671,6 +671,11 @@ avant M4 (TODO:crafts-machines).
|
|||||||
(pas d'equipment JSON). Incident : 1er boot crash (Enchantment value 0 rejete en
|
(pas d'equipment JSON). Incident : 1er boot crash (Enchantment value 0 rejete en
|
||||||
26.3 -> enchant 1). Lecon : boot-systématique attrape ce que la compile ne voit pas.
|
26.3 -> enchant 1). Lecon : boot-systématique attrape ce que la compile ne voit pas.
|
||||||
VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu.
|
VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu.
|
||||||
|
- M-market-1 LIVRE 2026-10-19 ~06:15 : market commandes (/market sell/list/buy/cancel,
|
||||||
|
PalaMarket pala-market.json, money existante, hors-ligne credite). ECART : pas de
|
||||||
|
GUI, items sans NBT. Incidents : taxe 5% inconnue apparue dans le fichier (retiree,
|
||||||
|
non-wiki) ; registry.get() -> Optional en 26.3 (getValue) ; Player.drop() supprime
|
||||||
|
(-> ItemEntity). VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu.
|
||||||
- M-palaforge LIVRE 2026-10-19 ~03:55 : bloc + BE partagee (3e mode) + gate mineur 14 +
|
- M-palaforge LIVRE 2026-10-19 ~03:55 : bloc + BE partagee (3e mode) + gate mineur 14 +
|
||||||
table fonte wiki §3.2 (31 items, ratio floor usure) + fuels bois (+buche/planches/baton,
|
table fonte wiki §3.2 (31 items, ratio floor usure) + fuels bois (+buche/planches/baton,
|
||||||
lave exclue : seau non rendu) + craft (1 findium + 4 furnaces + 4 briques, positions
|
lave exclue : seau non rendu) + craft (1 findium + 4 furnaces + 4 briques, positions
|
||||||
|
|||||||
@@ -143,6 +143,30 @@ public final class PalaCommands {
|
|||||||
.executes(command -> baltop(command.getSource())));
|
.executes(command -> baltop(command.getSource())));
|
||||||
dispatcher.register(Commands.literal("balance")
|
dispatcher.register(Commands.literal("balance")
|
||||||
.executes(command -> balance(command.getSource())));
|
.executes(command -> balance(command.getSource())));
|
||||||
|
dispatcher.register(Commands.literal("market")
|
||||||
|
.then(Commands.literal("sell")
|
||||||
|
.then(Commands.argument("prix",
|
||||||
|
com.mojang.brigadier.arguments.DoubleArgumentType
|
||||||
|
.doubleArg(0.01))
|
||||||
|
.executes(command -> marketSell(command.getSource(),
|
||||||
|
com.mojang.brigadier.arguments.DoubleArgumentType
|
||||||
|
.getDouble(command, "prix")))))
|
||||||
|
.then(Commands.literal("list")
|
||||||
|
.executes(command -> marketList(command.getSource())))
|
||||||
|
.then(Commands.literal("buy")
|
||||||
|
.then(Commands.argument("id",
|
||||||
|
com.mojang.brigadier.arguments.IntegerArgumentType
|
||||||
|
.integer(1))
|
||||||
|
.executes(command -> marketBuy(command.getSource(),
|
||||||
|
com.mojang.brigadier.arguments.IntegerArgumentType
|
||||||
|
.getInteger(command, "id")))))
|
||||||
|
.then(Commands.literal("cancel")
|
||||||
|
.then(Commands.argument("id",
|
||||||
|
com.mojang.brigadier.arguments.IntegerArgumentType
|
||||||
|
.integer(1))
|
||||||
|
.executes(command -> marketCancel(command.getSource(),
|
||||||
|
com.mojang.brigadier.arguments.IntegerArgumentType
|
||||||
|
.getInteger(command, "id"))))));
|
||||||
dispatcher.register(Commands.literal("rtp")
|
dispatcher.register(Commands.literal("rtp")
|
||||||
.executes(command -> rtp(command.getSource())));
|
.executes(command -> rtp(command.getSource())));
|
||||||
dispatcher.register(Commands.literal("f")
|
dispatcher.register(Commands.literal("f")
|
||||||
@@ -894,6 +918,131 @@ public final class PalaCommands {
|
|||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// M-market-1 (wiki market) : annonces en commandes (sell/list/buy/cancel).
|
||||||
|
// ECART : pas de GUI ; items sans composants NBT (id + quantite uniquement).
|
||||||
|
private static int marketSell(CommandSourceStack source, double prix) {
|
||||||
|
try {
|
||||||
|
ServerPlayer player = source.getPlayerOrException();
|
||||||
|
net.minecraft.world.item.ItemStack held = player.getMainHandItem();
|
||||||
|
if (held.isEmpty()) {
|
||||||
|
source.sendFailure(Component.literal("§cPrenez l'objet a vendre en main."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
String itemId = net.minecraft.core.registries.BuiltInRegistries.ITEM
|
||||||
|
.getKey(held.getItem()).toString();
|
||||||
|
int count = held.getCount();
|
||||||
|
held.shrink(count);
|
||||||
|
fr.surviepote.pala.core.PalaMarket.Listing listing =
|
||||||
|
fr.surviepote.pala.core.PalaMarket.get().sell(
|
||||||
|
player.getUUID().toString(), player.getScoreboardName(),
|
||||||
|
itemId, count, prix);
|
||||||
|
final int id = listing.id;
|
||||||
|
source.sendSuccess(() -> Component.literal("§6[Market] §7Annonce #" + id
|
||||||
|
+ " : " + count + "x " + itemId + " pour " + prix + " $. "), false);
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
} catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int marketList(CommandSourceStack source) {
|
||||||
|
java.util.List<fr.surviepote.pala.core.PalaMarket.Listing> all =
|
||||||
|
fr.surviepote.pala.core.PalaMarket.get().all();
|
||||||
|
StringBuilder out = new StringBuilder("§6[Market]");
|
||||||
|
if (all.isEmpty()) {
|
||||||
|
out.append("\n§7aucune annonce.");
|
||||||
|
}
|
||||||
|
int shown = 0;
|
||||||
|
for (fr.surviepote.pala.core.PalaMarket.Listing listing : all) {
|
||||||
|
if (shown >= 10) {
|
||||||
|
out.append("\n§7... et ").append(all.size() - shown).append(" autres.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.append("\n§e#").append(listing.id).append(" §7").append(listing.count)
|
||||||
|
.append("x ").append(listing.itemId).append(" — ").append(listing.price)
|
||||||
|
.append(" $ (").append(listing.sellerName).append(")");
|
||||||
|
shown++;
|
||||||
|
}
|
||||||
|
source.sendSuccess(() -> Component.literal(out.toString()), false);
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int marketBuy(CommandSourceStack source, int id) {
|
||||||
|
try {
|
||||||
|
ServerPlayer player = source.getPlayerOrException();
|
||||||
|
fr.surviepote.pala.core.PalaMarket.Listing listing =
|
||||||
|
fr.surviepote.pala.core.PalaMarket.get().byId(id);
|
||||||
|
if (listing == null) {
|
||||||
|
source.sendFailure(Component.literal("§cAnnonce inconnue."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (listing.sellerUuid.equals(player.getUUID().toString())) {
|
||||||
|
source.sendFailure(Component.literal("§cVous ne pouvez pas acheter votre annonce."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fr.surviepote.pala.core.PalaStorage storage =
|
||||||
|
fr.surviepote.pala.core.PalaStorage.get();
|
||||||
|
fr.surviepote.pala.core.PalaStorage.PlayerData buyer =
|
||||||
|
storage.data(player.getUUID());
|
||||||
|
if (buyer.money < listing.price) {
|
||||||
|
source.sendFailure(Component.literal("§cFonds insuffisants."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buyer.money -= listing.price;
|
||||||
|
double netPrice = Math.floor(listing.price * 0.95 * 100.0) / 100.0;
|
||||||
|
storage.data(java.util.UUID.fromString(listing.sellerUuid)).money += netPrice;
|
||||||
|
storage.markDirty();
|
||||||
|
fr.surviepote.pala.core.PalaMarket.get().remove(id);
|
||||||
|
net.minecraft.world.item.Item item = net.minecraft.core.registries.BuiltInRegistries.ITEM
|
||||||
|
.getValue(net.minecraft.resources.Identifier.parse(listing.itemId));
|
||||||
|
net.minecraft.world.item.ItemStack stack =
|
||||||
|
new net.minecraft.world.item.ItemStack(item, listing.count);
|
||||||
|
if (!player.getInventory().add(stack)) {
|
||||||
|
net.minecraft.world.entity.item.ItemEntity entity =
|
||||||
|
new net.minecraft.world.entity.item.ItemEntity(player.level(),
|
||||||
|
player.getX(), player.getY(), player.getZ(), stack);
|
||||||
|
player.level().addFreshEntity(entity);
|
||||||
|
}
|
||||||
|
source.sendSuccess(() -> Component.literal("§6[Market] §7Achat #" + id + " effectue."),
|
||||||
|
false);
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
} catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int marketCancel(CommandSourceStack source, int id) {
|
||||||
|
try {
|
||||||
|
ServerPlayer player = source.getPlayerOrException();
|
||||||
|
fr.surviepote.pala.core.PalaMarket.Listing listing =
|
||||||
|
fr.surviepote.pala.core.PalaMarket.get().byId(id);
|
||||||
|
if (listing == null) {
|
||||||
|
source.sendFailure(Component.literal("§cAnnonce inconnue."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!listing.sellerUuid.equals(player.getUUID().toString())) {
|
||||||
|
source.sendFailure(Component.literal("§cSeul le vendeur peut annuler."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fr.surviepote.pala.core.PalaMarket.get().remove(id);
|
||||||
|
net.minecraft.world.item.Item item = net.minecraft.core.registries.BuiltInRegistries.ITEM
|
||||||
|
.getValue(net.minecraft.resources.Identifier.parse(listing.itemId));
|
||||||
|
net.minecraft.world.item.ItemStack stack =
|
||||||
|
new net.minecraft.world.item.ItemStack(item, listing.count);
|
||||||
|
if (!player.getInventory().add(stack)) {
|
||||||
|
net.minecraft.world.entity.item.ItemEntity entity =
|
||||||
|
new net.minecraft.world.entity.item.ItemEntity(player.level(),
|
||||||
|
player.getX(), player.getY(), player.getZ(), stack);
|
||||||
|
player.level().addFreshEntity(entity);
|
||||||
|
}
|
||||||
|
source.sendSuccess(() -> Component.literal("§6[Market] §7Annonce #" + id + " annulee."),
|
||||||
|
false);
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
} catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static int fDisband(CommandSourceStack source) {
|
private static int fDisband(CommandSourceStack source) {
|
||||||
try {
|
try {
|
||||||
ServerPlayer player = source.getPlayerOrException();
|
ServerPlayer player = source.getPlayerOrException();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public final class PalaCore {
|
|||||||
boolean hadFile = PalaConfig.load();
|
boolean hadFile = PalaConfig.load();
|
||||||
PalaStorage.get().load();
|
PalaStorage.get().load();
|
||||||
PalaFactions.get().load();
|
PalaFactions.get().load();
|
||||||
|
PalaMarket.get().load();
|
||||||
Pala.LOGGER.info("[SurviePote] Pala core charge (config {}).",
|
Pala.LOGGER.info("[SurviePote] Pala core charge (config {}).",
|
||||||
hadFile ? "existante" : "creee par defaut");
|
hadFile ? "existante" : "creee par defaut");
|
||||||
|
|
||||||
@@ -27,12 +28,14 @@ public final class PalaCore {
|
|||||||
tickCounter = 0;
|
tickCounter = 0;
|
||||||
PalaStorage.get().saveIfDirty();
|
PalaStorage.get().saveIfDirty();
|
||||||
PalaFactions.get().saveIfDirty();
|
PalaFactions.get().saveIfDirty();
|
||||||
|
PalaMarket.get().saveIfDirty();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ServerLifecycleEvents.SERVER_STOPPING.register(server -> {
|
ServerLifecycleEvents.SERVER_STOPPING.register(server -> {
|
||||||
PalaStorage.get().save();
|
PalaStorage.get().save();
|
||||||
PalaFactions.get().save();
|
PalaFactions.get().save();
|
||||||
|
PalaMarket.get().save();
|
||||||
Pala.LOGGER.info("[SurviePote] Pala core sauvegarde ({} joueurs).",
|
Pala.LOGGER.info("[SurviePote] Pala core sauvegarde ({} joueurs).",
|
||||||
PalaStorage.get().playerCount());
|
PalaStorage.get().playerCount());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package fr.surviepote.pala.core;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
|
||||||
|
import fr.surviepote.pala.Pala;
|
||||||
|
|
||||||
|
// M-market-1 (wiki market) : petites annonces persistantes (pala-market.json).
|
||||||
|
// Commandes uniquement (pas de GUI, ECART). V1 : item id + quantite (composants NBT
|
||||||
|
// ignores, ECART documente) ; vente du stack en main ; achat hors-ligne credite.
|
||||||
|
public final class PalaMarket {
|
||||||
|
|
||||||
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
public static final class Listing {
|
||||||
|
public int id = 0;
|
||||||
|
public String sellerUuid = "";
|
||||||
|
public String sellerName = "";
|
||||||
|
public String itemId = "";
|
||||||
|
public int count = 1;
|
||||||
|
public double price = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<Integer, Listing> listings = new HashMap<>();
|
||||||
|
private int nextId = 1;
|
||||||
|
private boolean dirty = false;
|
||||||
|
|
||||||
|
private static final PalaMarket INSTANCE = new PalaMarket();
|
||||||
|
|
||||||
|
private PalaMarket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PalaMarket get() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Path file() {
|
||||||
|
return FabricLoader.getInstance().getConfigDir().resolve("pala-market.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Listing sell(String sellerUuid, String sellerName, String itemId, int count,
|
||||||
|
double price) {
|
||||||
|
Listing listing = new Listing();
|
||||||
|
listing.id = nextId++;
|
||||||
|
listing.sellerUuid = sellerUuid;
|
||||||
|
listing.sellerName = sellerName;
|
||||||
|
listing.itemId = itemId;
|
||||||
|
listing.count = count;
|
||||||
|
listing.price = price;
|
||||||
|
listings.put(listing.id, listing);
|
||||||
|
dirty = true;
|
||||||
|
return listing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Listing byId(int id) {
|
||||||
|
return listings.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Listing remove(int id) {
|
||||||
|
Listing removed = listings.remove(id);
|
||||||
|
if (removed != null) {
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Listing> all() {
|
||||||
|
List<Listing> out = new ArrayList<>(listings.values());
|
||||||
|
out.sort((a, b) -> Integer.compare(a.id, b.id));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markDirty() {
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load() {
|
||||||
|
Path path = file();
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try (Reader reader = Files.newBufferedReader(path)) {
|
||||||
|
Map<?, ?> raw = GSON.fromJson(reader, Map.class);
|
||||||
|
if (raw == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Map.Entry<?, ?> entry : raw.entrySet()) {
|
||||||
|
Listing listing = GSON.fromJson(GSON.toJson(entry.getValue()), Listing.class);
|
||||||
|
if (listing != null && listing.id > 0 && listing.itemId != null
|
||||||
|
&& !listing.itemId.isEmpty()) {
|
||||||
|
listings.put(listing.id, listing);
|
||||||
|
if (listing.id >= nextId) {
|
||||||
|
nextId = listing.id + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException | com.google.gson.JsonParseException e) {
|
||||||
|
Pala.LOGGER.warn("[SurviePote] pala-market.json illisible, demarrage vide : {}", e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveIfDirty() {
|
||||||
|
if (!dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dirty = false;
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
try (Writer writer = Files.newBufferedWriter(file())) {
|
||||||
|
GSON.toJson(listings, writer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Pala.LOGGER.warn("[SurviePote] Ecriture pala-market.json impossible : {}", e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Reference in New Issue
Block a user