+1
-1
@@ -13,7 +13,7 @@ loader_version=0.19.2
|
|||||||
loom_version=1.15-SNAPSHOT
|
loom_version=1.15-SNAPSHOT
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.0.0
|
mod_version=1.0.1
|
||||||
maven_group=skybakery
|
maven_group=skybakery
|
||||||
archives_base_name=skybakery
|
archives_base_name=skybakery
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,65 @@
|
|||||||
package skybakery;
|
package skybakery;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
|
||||||
|
import net.minecraft.client.network.ServerInfo;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import skybakery.assets.NewYearCakeAsset;
|
||||||
|
import skybakery.repository.NewYearCakeRepository;
|
||||||
|
import skybakery.utilities.ChatMenu;
|
||||||
|
|
||||||
public class SkyBakeryClient implements ClientModInitializer {
|
public class SkyBakeryClient implements ClientModInitializer {
|
||||||
|
public static final String HYPIXEL_URL = "hypixel.net";
|
||||||
|
public static final NewYearCakeRepository CAKE_REPOSITORY = new NewYearCakeRepository();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
||||||
|
client.execute(() -> {
|
||||||
|
if (client.player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ServerInfo server = client.getCurrentServerEntry();
|
||||||
|
if (server == null || !server.address.contains(HYPIXEL_URL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (CAKE_REPOSITORY.isEmpty()) {
|
||||||
|
CAKE_REPOSITORY.load();
|
||||||
|
ChatMenu.send("Cake collection loaded.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> {
|
||||||
|
ServerInfo server = client.getCurrentServerEntry();
|
||||||
|
if (server == null || !server.address.contains(HYPIXEL_URL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CAKE_REPOSITORY.save();
|
||||||
|
});
|
||||||
|
|
||||||
|
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
|
||||||
|
if (client.player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < client.player.getInventory().size(); i++) {
|
||||||
|
ItemStack stack = client.player.getInventory().getStack(i);
|
||||||
|
if (stack.isEmpty())
|
||||||
|
continue;
|
||||||
|
if (!stack.getName().getString().contains("New Year Cake"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Optional<NewYearCakeAsset> newYearCakeAsset = NewYearCakeAsset.from(stack);
|
||||||
|
|
||||||
|
if (newYearCakeAsset.isEmpty()) {
|
||||||
|
ChatMenu.send("ERROR: Could not parse as NewYearCakeAsset");
|
||||||
|
} else if (CAKE_REPOSITORY.add(newYearCakeAsset.get())) {
|
||||||
|
ChatMenu.send("Detected new New Year Cake! Adding to collection " + stack.getName().getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package skybakery.assets;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public record BaseAsset(
|
||||||
|
String version,
|
||||||
|
String id,
|
||||||
|
String profileId,
|
||||||
|
long pricePaid,
|
||||||
|
Instant dateObtained,
|
||||||
|
ObtainedFrom obtainedFrom) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package skybakery.assets;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import net.minecraft.component.DataComponentTypes;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
|
||||||
|
public record NewYearCakeAsset(BaseAsset base, String uuid, int year) {
|
||||||
|
|
||||||
|
private static final String ITEM_ID = "NEW_YEAR_CAKE";
|
||||||
|
private static final Pattern YEAR_PATTERN = Pattern.compile("Year (\\d+)");
|
||||||
|
|
||||||
|
public static Optional<NewYearCakeAsset> from(ItemStack stack) {
|
||||||
|
if (stack.isEmpty())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
String name = stack.getName().getString();
|
||||||
|
Matcher matcher = YEAR_PATTERN.matcher(name);
|
||||||
|
if (!matcher.find())
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
int year = Integer.parseInt(matcher.group(1));
|
||||||
|
|
||||||
|
var customData = stack.get(DataComponentTypes.CUSTOM_DATA);
|
||||||
|
String uuid = "";
|
||||||
|
String itemId = ITEM_ID;
|
||||||
|
|
||||||
|
if (customData != null) {
|
||||||
|
NbtCompound root = customData.copyNbt();
|
||||||
|
uuid = root.getString("uuid").orElse("");
|
||||||
|
itemId = root.getString("id").orElse(ITEM_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseAsset base = new BaseAsset("1", itemId, "", 0, Instant.now(), ObtainedFrom.UNKNOWN);
|
||||||
|
return Optional.of(new NewYearCakeAsset(base, uuid, year));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package skybakery.assets;
|
||||||
|
|
||||||
|
public enum ObtainedFrom {
|
||||||
|
AUCTION,
|
||||||
|
TRADE,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package skybakery.repository;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import skybakery.assets.NewYearCakeAsset;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class NewYearCakeRepository {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(NewYearCakeRepository.class);
|
||||||
|
|
||||||
|
private static final Gson GSON = new GsonBuilder()
|
||||||
|
.setPrettyPrinting()
|
||||||
|
.registerTypeAdapter(Instant.class,
|
||||||
|
(JsonSerializer<Instant>) (src, type, ctx) -> new JsonPrimitive(src.toEpochMilli()))
|
||||||
|
.registerTypeAdapter(Instant.class,
|
||||||
|
(JsonDeserializer<Instant>) (json, type, ctx) -> Instant.ofEpochMilli(json.getAsLong()))
|
||||||
|
.create();
|
||||||
|
|
||||||
|
private static final Type MAP_TYPE = new TypeToken<Map<Integer, List<NewYearCakeAsset>>>() {
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
private final Path file;
|
||||||
|
private Map<Integer, List<NewYearCakeAsset>> cakes = new HashMap<>();
|
||||||
|
|
||||||
|
public NewYearCakeRepository() {
|
||||||
|
this.file = FabricLoader.getInstance().getConfigDir().resolve("skybakery/cakes.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(NewYearCakeAsset cake) {
|
||||||
|
List<NewYearCakeAsset> forYear = cakes.computeIfAbsent(cake.year(), k -> new ArrayList<>());
|
||||||
|
boolean alreadyExists = forYear.stream().anyMatch(c -> c.uuid().equals(cake.uuid()));
|
||||||
|
if (alreadyExists) return false;
|
||||||
|
forYear.add(cake);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<NewYearCakeAsset> getByYear(int year) {
|
||||||
|
return Collections.unmodifiableList(cakes.getOrDefault(year, Collections.emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer, List<NewYearCakeAsset>> getAll() {
|
||||||
|
return Collections.unmodifiableMap(cakes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Integer> getYears() {
|
||||||
|
return Collections.unmodifiableSet(cakes.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return cakes.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load() {
|
||||||
|
if (!Files.exists(file))
|
||||||
|
return;
|
||||||
|
try (Reader reader = Files.newBufferedReader(file)) {
|
||||||
|
Map<Integer, List<NewYearCakeAsset>> loaded = GSON.fromJson(reader, MAP_TYPE);
|
||||||
|
if (loaded != null)
|
||||||
|
cakes = loaded;
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error("Failed to load cake collection from {}", file, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
Files.createDirectories(file.getParent());
|
||||||
|
try (Writer writer = Files.newBufferedWriter(file)) {
|
||||||
|
GSON.toJson(cakes, MAP_TYPE, writer);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error("Failed to save cake collection to {}", file, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package skybakery.utilities;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class ChatMenu {
|
||||||
|
private static final String PREFIX = "§d[SkyBakery]§r ";
|
||||||
|
|
||||||
|
public static void send(String message) {
|
||||||
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
if (client.player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
client.player.sendMessage(Text.literal(PREFIX + message), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user