Skip to content

Commit 4067d4b

Browse files
authored
v0.15.3.3-rc1 - Storage Rework
Merge Storage Rework into main
2 parents 003a995 + e76aaea commit 4067d4b

53 files changed

Lines changed: 2826 additions & 721 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ parchment_mappings_version=2024.11.17
1717
mod_id=pmweatherapi
1818
mod_name=PMWeatherAPI
1919
mod_license=GNU GPL 3.0
20-
mod_version=0.15.3.2
20+
mod_version=0.15.3.3-rc1
2121
mod_group_id=net.nullved
22-
mod_authors=NullVed
22+
mod_authors=nullved
2323
mod_description=An API for interfacing with ProtoManly's Weather Mod
2424

2525
# Dependencies

src/main/java/net/nullved/pmweatherapi/PMWeatherAPI.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,28 @@
1212
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
1313
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
1414
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
15+
import net.nullved.pmweatherapi.client.data.PMWClientStorages;
16+
import net.nullved.pmweatherapi.client.metar.MetarClientStorage;
17+
import net.nullved.pmweatherapi.client.radar.RadarClientStorage;
18+
import net.nullved.pmweatherapi.client.radar.WSRClientStorage;
1519
import net.nullved.pmweatherapi.client.render.IDOverlay;
1620
import net.nullved.pmweatherapi.client.render.RadarOverlays;
1721
import net.nullved.pmweatherapi.config.PMWClientConfig;
22+
import net.nullved.pmweatherapi.data.PMWStorages;
23+
import net.nullved.pmweatherapi.example.ExampleOverlay;
24+
import net.nullved.pmweatherapi.metar.MetarServerStorage;
25+
import net.nullved.pmweatherapi.metar.MetarStorage;
26+
import net.nullved.pmweatherapi.metar.MetarStorageData;
1827
import net.nullved.pmweatherapi.network.PMWNetworking;
1928
import net.nullved.pmweatherapi.radar.RadarMode;
29+
import net.nullved.pmweatherapi.radar.storage.*;
30+
import net.nullved.pmweatherapi.storage.data.BlockPosData;
31+
import net.nullved.pmweatherapi.storage.data.StorageDataManager;
32+
import org.checkerframework.checker.units.qual.C;
2033
import org.slf4j.Logger;
2134

35+
import java.awt.*;
36+
2237
@Mod(PMWeatherAPI.MODID)
2338
public class PMWeatherAPI {
2439
public static final String MODID = "pmweatherapi";
@@ -40,20 +55,30 @@ public PMWeatherAPI(IEventBus modEventBus, ModContainer modContainer) {
4055
}
4156

4257
private void commonSetup(FMLCommonSetupEvent event) {
43-
// if (!ModList.get().isLoaded("pmweather")) {
44-
// throw new RuntimeException("ProtoManly's Weather not detected!");
45-
// }
58+
StorageDataManager.register(BlockPosData.ID, BlockPosData::deserializeFromNBT);
59+
StorageDataManager.register(RadarStorageData.ID, RadarStorageData::deserializeFromNBT);
60+
StorageDataManager.register(MetarStorageData.ID, MetarStorageData::deserializeFromNBT);
61+
StorageDataManager.register(WSRStorageData.ID, WSRStorageData::deserializeFromNBT);
62+
63+
PMWStorages.registerStorage(RadarStorage.ID, RadarServerStorage.class, RadarServerStorage::new);
64+
PMWStorages.registerStorage(MetarStorage.ID, MetarServerStorage.class, MetarServerStorage::new);
65+
PMWStorages.registerStorage(WSRStorage.ID, WSRServerStorage.class, WSRServerStorage::new);
4666
}
4767

4868
private void registerPayloads(RegisterPayloadHandlersEvent event) {
4969
PMWNetworking.register(event.registrar("1"));
5070
}
5171

5272
private void clientSetup(FMLClientSetupEvent event) {
73+
//RadarMode.removeBaseRendering(true);
74+
75+
PMWClientStorages.registerStorage(RadarStorage.ID, RadarClientStorage.class, RadarClientStorage::new);
76+
PMWClientStorages.registerStorage(MetarStorage.ID, MetarClientStorage.class, MetarClientStorage::new);
77+
PMWClientStorages.registerStorage(WSRStorage.ID, WSRClientStorage.class, WSRClientStorage::new);
78+
5379
RadarOverlays.registerOverlay(() -> IDOverlay.INSTANCE);
5480
//RadarOverlays.registerOverlay(() -> ExampleOverlay.INSTANCE);
5581
}
56-
5782
public static ResourceLocation rl(String path) {
5883
return ResourceLocation.fromNamespaceAndPath(MODID, path);
5984
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package net.nullved.pmweatherapi.client.data;
2+
3+
import net.minecraft.client.multiplayer.ClientLevel;
4+
import net.minecraft.core.BlockPos;
5+
import net.minecraft.nbt.*;
6+
import net.nullved.pmweatherapi.PMWeatherAPI;
7+
import net.nullved.pmweatherapi.client.radar.RadarClientStorage;
8+
import net.nullved.pmweatherapi.network.S2CStoragePacket;
9+
import net.nullved.pmweatherapi.storage.IStorage;
10+
import net.nullved.pmweatherapi.storage.data.IStorageData;
11+
import net.nullved.pmweatherapi.storage.data.StorageData;
12+
13+
import java.util.Objects;
14+
import java.util.stream.Collectors;
15+
16+
/**
17+
* The interface defining the client-side implementation of a Storage such as {@link RadarClientStorage}
18+
* <br><br>
19+
* Every time the client changes dimension, a new {@link IClientStorage} is created for each storage.
20+
* @since 0.15.3.3
21+
*/
22+
public interface IClientStorage<D extends IStorageData> extends IStorage<D> {
23+
ClientLevel getLevel();
24+
25+
/**
26+
* Syncs all data from a {@link S2CStoragePacket} with operation {@code overwrite} into this storage's memory
27+
* @param tag The {@link CompoundTag} of the data
28+
* @since 0.15.3.3
29+
*/
30+
default void syncAll(CompoundTag tag) {
31+
clean();
32+
syncAdd(tag);
33+
}
34+
35+
/**
36+
* Syncs data from a {@link S2CStoragePacket} with operation {@code add} into this storage's memory
37+
* @param tag The {@link CompoundTag} of the data
38+
* @since 0.15.3.3
39+
*/
40+
default void syncAdd(CompoundTag tag) {
41+
int version = tag.getInt("version");
42+
if (tag.contains("list") && tag.getBoolean("list")) {
43+
// list format
44+
ListTag list = tag.getList("data", ListTag.TAG_COMPOUND);
45+
add(list.stream().map((t -> {
46+
try {
47+
return (D) StorageData.deserializeFromNBT((CompoundTag) t, version);
48+
} catch (ClassCastException e) {
49+
PMWeatherAPI.LOGGER.info("Invalid data entry in NBT: {}", e.getMessage());
50+
return null;
51+
}
52+
})).filter(Objects::nonNull).collect(Collectors.toSet()));
53+
} else {
54+
try {
55+
add((D) StorageData.deserializeFromNBT(tag.getCompound("data"), version));
56+
} catch (ClassCastException e) {
57+
PMWeatherAPI.LOGGER.info("Invalid data entry in NBT: {}", e.getMessage());
58+
}
59+
}
60+
}
61+
62+
/**
63+
* Syncs data from a {@link S2CStoragePacket} with operation {@code remove} into this storage's memory
64+
* @param tag The {@link CompoundTag} of the data
65+
* @since 0.15.3.3
66+
*/
67+
default void syncRemove(CompoundTag tag) {
68+
int version = tag.getInt("version");
69+
if (!tag.contains("format")) {
70+
// data
71+
if (tag.contains("list") && tag.getBoolean("list")) {
72+
// list format
73+
ListTag list = tag.getList("data", ListTag.TAG_COMPOUND);
74+
removeByData(list.stream().map((t -> {
75+
try {
76+
return (D) StorageData.deserializeFromNBT((CompoundTag) t, version);
77+
} catch (ClassCastException e) {
78+
PMWeatherAPI.LOGGER.info("Invalid data entry in NBT: {}", e.getMessage());
79+
return null;
80+
}
81+
})).filter(Objects::nonNull).collect(Collectors.toSet()));
82+
} else {
83+
// not list format
84+
try {
85+
remove((D) StorageData.deserializeFromNBT(tag.getCompound("data"), version));
86+
} catch (ClassCastException e) {
87+
PMWeatherAPI.LOGGER.info("Invalid data entry in NBT: {}", e.getMessage());
88+
}
89+
}
90+
} else if (tag.getString("format").equals("blockpos")) {
91+
if (tag.contains("list") && tag.getBoolean("list")) {
92+
// list format
93+
ListTag list = tag.getList("data", ListTag.TAG_INT_ARRAY);
94+
removeByPos(list.stream().map(t -> {
95+
if (t instanceof IntArrayTag iat) {
96+
return new BlockPos(iat.get(0).getAsInt(), iat.get(1).getAsInt(), iat.get(2).getAsInt());
97+
} else return null;
98+
}).collect(Collectors.toSet()));
99+
} else {
100+
// not list format
101+
remove(NbtUtils.readBlockPos(tag, "data").orElseThrow());
102+
}
103+
} else {
104+
PMWeatherAPI.LOGGER.info("Invalid data format for packet: '{}'!", tag.getString("format"));
105+
}
106+
}
107+
}
Lines changed: 119 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
package net.nullved.pmweatherapi.client.data;
22

33
import net.minecraft.client.Minecraft;
4+
import net.minecraft.client.multiplayer.ClientLevel;
45
import net.minecraft.core.BlockPos;
5-
import net.minecraft.world.level.Level;
6+
import net.minecraft.resources.ResourceLocation;
67
import net.neoforged.api.distmarker.Dist;
78
import net.neoforged.api.distmarker.OnlyIn;
89
import net.nullved.pmweatherapi.PMWeatherAPI;
10+
import net.nullved.pmweatherapi.client.metar.MetarClientStorage;
911
import net.nullved.pmweatherapi.client.radar.RadarClientStorage;
12+
import net.nullved.pmweatherapi.client.radar.WSRClientStorage;
13+
import net.nullved.pmweatherapi.client.storage.ClientStorageInstance;
14+
import net.nullved.pmweatherapi.metar.MetarStorage;
15+
import net.nullved.pmweatherapi.metar.MetarStorageData;
1016
import net.nullved.pmweatherapi.radar.RadarMode;
17+
import net.nullved.pmweatherapi.radar.storage.RadarStorage;
18+
import net.nullved.pmweatherapi.radar.storage.WSRStorage;
19+
import net.nullved.pmweatherapi.radar.storage.WSRStorageData;
20+
import net.nullved.pmweatherapi.storage.data.IStorageData;
21+
import net.nullved.pmweatherapi.storage.data.StorageData;
22+
import net.nullved.pmweatherapi.radar.storage.RadarStorageData;
1123

1224
import java.awt.*;
25+
import java.util.Collection;
1326
import java.util.HashMap;
1427
import java.util.Map;
28+
import java.util.Optional;
29+
import java.util.function.Function;
1530

1631
/**
1732
* A class holding the specific storage instances for the client
@@ -25,44 +40,122 @@ public class PMWClientStorages {
2540
*/
2641
public static Map<BlockPos, Map<RadarMode, Map<Integer, Color>>> RADAR_MODE_COLORS = new HashMap<>();
2742

28-
private static Level lastLevel;
29-
private static RadarClientStorage radar;
43+
public static final Map<ResourceLocation, ClientStorageInstance<?, ?>> STORAGE_INSTANCES = new HashMap<>();
44+
45+
private static ClientLevel lastLevel;
3046

3147
/**
32-
* Resets this client's internal radar storage
48+
* Gets the {@link ClientStorageInstance} of the {@link RadarClientStorage}
49+
* @return The {@link ClientStorageInstance}
3350
* @since 0.14.15.3
3451
*/
35-
public static void resetRadars() {
36-
radar = null;
52+
public static ClientStorageInstance<RadarStorageData, RadarClientStorage> radars() {
53+
return get(RadarStorage.ID, RadarClientStorage.class).orElseThrow();
3754
}
3855

3956
/**
40-
* Gets the radar storage for the dimension this client is currently in
41-
* @return A {@link RadarClientStorage}
42-
* @since 0.14.15.3
57+
* Gets the {@link ClientStorageInstance} of the {@link MetarClientStorage}
58+
* @return The {@link ClientStorageInstance}
59+
* @since 0.15.3.3
4360
*/
44-
public static RadarClientStorage getRadars() {
45-
try {
46-
Level level = Minecraft.getInstance().level;
47-
if (radar == null || level != lastLevel) {
48-
init(level);
49-
}
50-
} catch (Exception e) {
51-
PMWeatherAPI.LOGGER.error(e.getMessage(), e);
52-
}
61+
public static ClientStorageInstance<MetarStorageData, MetarClientStorage> metars() {
62+
return get(MetarStorage.ID, MetarClientStorage.class).orElseThrow();
63+
}
5364

54-
return radar;
65+
/**
66+
* Gets the {@link ClientStorageInstance} of the {@link WSRClientStorage}
67+
* @return The {@link ClientStorageInstance}
68+
* @since 0.15.3.3
69+
*/
70+
public static ClientStorageInstance<WSRStorageData, WSRClientStorage> wsrs() {
71+
return get(WSRStorage.ID, WSRClientStorage.class).orElseThrow();
5572
}
5673

5774
/**
58-
* Initializes this client's storages to be the storages for the given level
59-
* @param level The {@link Level} to initialize storages for
60-
* @since 0.14.15.3
75+
* Get a {@link ClientStorageInstance} for a given {@link ResourceLocation} ID
76+
* @param location The ID of the storage
77+
* @return A {@link ClientStorageInstance}
78+
* @since 0.15.3.3
6179
*/
62-
public static void init(Level level) {
63-
lastLevel = level;
64-
if (level != null) {
65-
radar = new RadarClientStorage(level.dimension());
80+
public static ClientStorageInstance<?, ?> get(ResourceLocation location) {
81+
if (!STORAGE_INSTANCES.containsKey(location)) {
82+
PMWeatherAPI.LOGGER.error("No storage instance found for location {}", location);
83+
}
84+
85+
ClientLevel curLevel = Minecraft.getInstance().level;
86+
if (curLevel != null && curLevel != lastLevel) {
87+
loadDimension(curLevel);
6688
}
89+
90+
ClientStorageInstance<?, ?> csi = STORAGE_INSTANCES.get(location);
91+
if (csi.get() == null) {
92+
csi.load(curLevel);
93+
}
94+
95+
return csi;
96+
}
97+
98+
/**
99+
* Overwrite a {@link ClientStorageInstance}
100+
* @param location The ID {@link ResourceLocation}
101+
* @param instance The new {@link ClientStorageInstance}
102+
* @since 0.15.3.3
103+
*/
104+
public static void set(ResourceLocation location, ClientStorageInstance<?, ?> instance) {
105+
STORAGE_INSTANCES.put(location, instance);
106+
}
107+
108+
/**
109+
* Casts the {@link ClientStorageInstance} to the specified {@link IClientStorage} class after retrieval
110+
* @param location The ID {@link ResourceLocation}
111+
* @param clazz The {@link Class} of an {@link IClientStorage} to cast to
112+
* @return The casted {@link ClientStorageInstance}
113+
* @param <D> The {@link IStorageData} of the {@link IClientStorage}
114+
* @param <T> The {@link IClientStorage}
115+
* @since 0.15.3.3
116+
*/
117+
public static <D extends StorageData, T extends IClientStorage<D>> Optional<ClientStorageInstance<D, T>> get(ResourceLocation location, Class<T> clazz) {
118+
return get(location).cast(clazz);
119+
}
120+
121+
/**
122+
* Gets all {@link ClientStorageInstance}s
123+
* @return A {@link Collection} of all {@link ClientStorageInstance}s
124+
* @since 0.15.3.3
125+
*/
126+
public static Collection<? extends ClientStorageInstance<?, ?>> getAll() {
127+
return STORAGE_INSTANCES.values();
128+
}
129+
130+
/**
131+
* Resets all data for all {@link ClientStorageInstance}s
132+
* @since 0.15.3.3
133+
*/
134+
public static void resetAll() {
135+
getAll().forEach(ClientStorageInstance::clear);
136+
}
137+
138+
/**
139+
* Loads a new {@link ClientLevel} for all {@link ClientStorageInstance}s
140+
* @param clientLevel The new {@link ClientLevel} to load
141+
* @since 0.15.3.3
142+
*/
143+
public static void loadDimension(ClientLevel clientLevel) {
144+
lastLevel = clientLevel;
145+
STORAGE_INSTANCES.forEach((location, instance) -> instance.load(clientLevel));
146+
}
147+
148+
/**
149+
* Register a new {@link IClientStorage}
150+
* @param id The {@link ResourceLocation} to save this {@link IClientStorage} as
151+
* @param clazz The {@link Class} of the {@link IClientStorage}
152+
* @param creator A function creating another {@link IClientStorage} for the given {@link ClientLevel}
153+
* @param <D> The {@link IStorageData} of the {@link IClientStorage}
154+
* @param <C> The {@link IClientStorage}
155+
* @since 0.15.3.3
156+
*/
157+
public static <D extends StorageData, C extends IClientStorage<D>> void registerStorage(ResourceLocation id, Class<C> clazz, Function<ClientLevel, C> creator) {
158+
ClientStorageInstance<D, C> instance = new ClientStorageInstance<>(id, clazz, creator);
159+
STORAGE_INSTANCES.put(id, instance);
67160
}
68161
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package net.nullved.pmweatherapi.client.event;
2+
3+
import net.minecraft.client.multiplayer.ClientLevel;
4+
import net.minecraft.world.level.LevelAccessor;
5+
import net.neoforged.api.distmarker.Dist;
6+
import net.neoforged.bus.api.SubscribeEvent;
7+
import net.neoforged.fml.common.EventBusSubscriber;
8+
import net.neoforged.neoforge.event.level.LevelEvent;
9+
import net.nullved.pmweatherapi.PMWeatherAPI;
10+
import net.nullved.pmweatherapi.client.data.PMWClientStorages;
11+
12+
@EventBusSubscriber(modid = PMWeatherAPI.MODID, value = Dist.CLIENT)
13+
public class PMWClientEvents {
14+
@SubscribeEvent
15+
public static void onLevelLoadEvent(LevelEvent.Load event) {
16+
LevelAccessor level = event.getLevel();
17+
if (level.isClientSide() && level instanceof ClientLevel clevel) {
18+
PMWeatherAPI.LOGGER.info("Loaded client storages for dimension {}", clevel.dimension().location());
19+
PMWClientStorages.loadDimension(clevel);
20+
}
21+
}
22+
23+
@SubscribeEvent
24+
public static void onLevelUnloadEvent(LevelEvent.Unload event) {
25+
LevelAccessor level = event.getLevel();
26+
if (level.isClientSide() && level instanceof ClientLevel clevel) {
27+
PMWeatherAPI.LOGGER.info("Unloaded client storages for dimension {}", clevel.dimension().location());
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)