Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,40 @@ minecraft {
sourceSets.main.resources { srcDir 'src/generated/resources' }

repositories {
flatDir {
dirs 'libs'
maven {
url "https://cursemaven.com"
content {
includeGroup "curse.maven"
}
}

// flatDir {
// dirs 'libs'
// }
}

dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"

compileOnly fg.deobf("_:rubidium:0.5.6")
// implementation fg.deobf("_:rubidium:0.5.6")
compileOnly "curse.maven:$rubidium_project_id:$rubidium_file_id"
// compileOnly fg.deobf("_:rubidium:0.5.6")
// implementation fg.deobf("_:rubidium:0.5.6")

// implementation fg.deobf("_:Patchouli:1.18.2-71.1")
// implementation fg.deobf("_:TerraFirmaCraft:Forge-1.18.2-2.1.11-beta")
// implementation fg.deobf("_:Cartography:1.18.2-0.4.0-alpha3")

// implementation fg.deobf("_:Patchouli:1.18.2-71.1")
// implementation fg.deobf("_:TerraFirmaCraft:Forge-1.18.2-2.1.11-beta")
// implementation fg.deobf("_:Cartography:1.18.2-0.4.0-alpha3")
implementation fg.deobf("curse.maven:$architectury_project_id:$architectury_file_id")
implementation fg.deobf("curse.maven:$ftbchunks_project_id:$ftbchunks_file_id")
implementation fg.deobf("curse.maven:$ftblib_project_id:$ftblib_file_id")
implementation fg.deobf("curse.maven:$ftbteams_project_id:$ftbteams_file_id")
implementation fg.deobf("curse.maven:$waystones_project_id:$waystones_file_id")
implementation fg.deobf("curse.maven:$balm_project_id:$balm_file_id")
Comment on lines +91 to +92
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong, but I think these should be compileOnly not implementation, same as for Rubidium/Embeddium?

(Same for the FTB dependencies above, but that's existing problems so up to you if you wanna fix for everything or just for your change)


implementation fg.deobf("_:ftb-chunks:${ftbchunks_version}")
implementation fg.deobf("_:ftb-teams:${ftbteams_version}")
implementation fg.deobf("_:ftb-library:$ftblib_version")
implementation fg.deobf("_:architectury:${architectury_version}")
// implementation fg.deobf("_:ftb-chunks:${ftbchunks_version}")
// implementation fg.deobf("_:ftb-teams:${ftbteams_version}")
// implementation fg.deobf("_:ftb-library:$ftblib_version")
// implementation fg.deobf("_:architectury:${architectury_version}")

// implementation fg.deobf("_:journeymap:1.20.1-5.10.0-forge")
// implementation fg.deobf("_:Xaeros_Minimap:24.2.0_Forge_1.20")
Expand Down Expand Up @@ -123,7 +138,7 @@ jar {
// This is the preferred method to reobfuscate your jar file
jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
//publish.dependsOn('reobfJar')
// publish.dependsOn('reobfJar')

publishing {
publications {
Expand Down
21 changes: 17 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@ mappings_version=1.18.2
minecraft_version=1.18.2
forge_version=40.2.17

ftbchunks_version=forge-1802.3.19-build.362
ftbteams_version=forge-1802.2.11-build.107
ftblib_version=forge-1802.3.11-build.177
architectury_version=4.12.94-forge
# Curseforge File IDs
rubidium_file_id=4494903
architectury_file_id=5137931
ftbchunks_file_id=5423717
ftbteams_file_id=4579981
ftblib_file_id=4396792
waystones_file_id=4943242
balm_file_id=4412588

# Curseforge Project IDs
rubidium_project_id=rubidium-574856
architectury_project_id=architectury-api-419699
ftbchunks_project_id=ftb-chunks-forge-314906
ftbteams_project_id=ftb-teams-forge-404468
ftblib_project_id=ftb-library-forge-404465
waystones_project_id=waystones-245755
balm_project_id=balm-531761
9 changes: 5 additions & 4 deletions src/main/java/com/eerussianguy/blazemap/BlazeMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.eerussianguy.blazemap.integration.KnownMods;
import com.eerussianguy.blazemap.integration.ModIntegration;
import com.eerussianguy.blazemap.integration.ftbchunks.FTBChunksPlugin;
import com.eerussianguy.blazemap.integration.waystones.WaystonesPlugin;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;

Expand All @@ -35,7 +36,8 @@ public class BlazeMap {
public static final String MOD_NAME = "Blaze Map";

public static final List<ModIntegration> INTEGRATIONS = List.of(
new FTBChunksPlugin()
new FTBChunksPlugin(),
new WaystonesPlugin()
);

public static ResourceLocation resource(String name) {
Expand All @@ -55,8 +57,7 @@ public BlazeMap() {
// Enabling this will log when certain events happen in the world, allowing you
// to crossreference what's happening on screen with what's happening in the logs.
// DebuggingEventHandler.init();
}
else {
} else {
// Client side objects are forbidden in the dedicated server.
// The others are frozen by the RegistryController when the time comes.
RegistryController.freezeClientRegistries();
Expand All @@ -75,7 +76,7 @@ public void setup(FMLCommonSetupEvent event) {
// This might be helpful later on, on server side, where we want the engine off but other features on.
// So removing the mod to disable the server engine will not be an option.
// For now, though, there are no other server features.
if(BlazeMapConfig.COMMON.enableServerEngine.get()){
if(BlazeMapConfig.COMMON.enableServerEngine.get()) {
ServerEngine.init();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ public class WaypointChannelLocal extends WaypointChannel {
public static final ResourceLocation GROUP_DEFAULT = BlazeMap.resource("waypoint/group/default");
private static final ResourceLocation GROUP_DEFAULT_FIRST = BlazeMap.resource("waypoint/group/default_first");
public static final ResourceLocation GROUP_DEATH = BlazeMap.resource("waypoint/group/death");
public static final ResourceLocation GROUP_WAYSTONE = BlazeMap.resource("waypoint/group/waystone");
public static final Component DEATHS = new TextComponent("Deaths").withStyle(ChatFormatting.YELLOW);
public static final Component WAYSTONES = new TextComponent("Waystones").withStyle(ChatFormatting.DARK_PURPLE);

public WaypointChannelLocal() {
super(REGISTRY.findOrCreate(BlazeMap.resource("local")));
WaypointGroup.define(GROUP_DEFAULT, () -> new WaypointGroup(GROUP_DEFAULT).setUserGivenName("New Group"));
WaypointGroup.define(GROUP_DEFAULT_FIRST, () -> new WaypointGroup(GROUP_DEFAULT).setUserGivenName("My Waypoints"));
WaypointGroup.define(GROUP_DEATH, () -> new WaypointGroup(GROUP_DEATH, ManagementType.INBOX).setSystemName(DEATHS));
WaypointGroup.define(GROUP_WAYSTONE, () -> new WaypointGroup(GROUP_WAYSTONE, ManagementType.INBOX).setSystemName(WAYSTONES));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public void iterate(ResourceKey<Level> dimension, BiConsumer<Waypoint, WaypointG
}
}

public void iterateAll(BiConsumer<Waypoint, WaypointGroup> consumer) {
groups.keySet().forEach(dimension -> iterate(dimension, consumer));
}

public List<WaypointGroup> getGroups(ResourceKey<Level> dimension) {
return groups.computeIfAbsent(dimension, $ -> makeDefaultGroups());
}
Expand All @@ -77,6 +81,7 @@ public List<ResourceLocation> getDefaultGroups() {
}

public abstract void save(StorageAccess.ServerStorage storage);

public abstract void load(StorageAccess.ServerStorage storage);

protected void save(StorageAccess.ServerStorage storage, ResourceLocation file) {
Expand Down Expand Up @@ -116,7 +121,7 @@ protected void load(StorageAccess.ServerStorage storage, ResourceLocation file,
groups.putAll(WaypointSerialization.FORMAT.readLegacy(input));
}
catch(IOException e) {
BlazeMap.LOGGER.error("Error loading legacy waypoints for level \""+key+"\". Not all waypoints could be loaded", e);
BlazeMap.LOGGER.error("Error loading legacy waypoints for level \"" + key + "\". Not all waypoints could be loaded", e);
}
});

Expand Down
36 changes: 19 additions & 17 deletions src/main/java/com/eerussianguy/blazemap/integration/KnownMods.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public static void init() {
add(COMPAT, ModIDs.SODIUM);
add(COMPAT, ModIDs.EMBEDDIUM);
add(COMPAT, ModIDs.RUBIDIUM);
add(COMPAT, ModIDs.WAYSTONES);
add(COMPAT, ModIDs.BALM);

add(PROBLEM, ModIDs.OPTIFINE);
add(PROBLEM, ModIDs.CHUNKPREGEN);
Expand All @@ -48,16 +50,16 @@ public static void init() {
mods.addAll(Arrays.asList(integration.dependencies));
}

for(String mod : mods){
for(String mod : mods) {
add(ANNOUNCED, mod);
}
}

@SafeVarargs
public static boolean isAnyLoaded(Iterable<String> ... lists) {
for(var list : lists){
for(var key : list){
if(ALL_KNOWN.contains(key)){
public static boolean isAnyLoaded(Iterable<String>... lists) {
for(var list : lists) {
for(var key : list) {
if(ALL_KNOWN.contains(key)) {
return true;
}
}
Expand All @@ -78,35 +80,35 @@ public static String getOwnerName(ResourceLocation key) {
}

@SafeVarargs
public static <T> T[] getCore(Class<T> t, Function<ModInfo, ? extends T> function, T ... fallbacks){
public static <T> T[] getCore(Class<T> t, Function<ModInfo, ? extends T> function, T... fallbacks) {
return mapEntries(CORE, t, function, fallbacks);
}

@SafeVarargs
public static <T> T[] getCompat(Class<T> t, Function<ModInfo, ? extends T> function, T ... fallbacks){
public static <T> T[] getCompat(Class<T> t, Function<ModInfo, ? extends T> function, T... fallbacks) {
return mapEntries(COMPAT, t, function, fallbacks);
}

@SafeVarargs
public static <T> T[] getProblem(Class<T> t, Function<ModInfo, ? extends T> function, T ... fallbacks){
public static <T> T[] getProblem(Class<T> t, Function<ModInfo, ? extends T> function, T... fallbacks) {
return mapEntries(PROBLEM, t, function, fallbacks);
}

@SafeVarargs
public static <T> T[] getAPICall(Class<T> t, Function<ModInfo, ? extends T> function, T ... fallbacks){
public static <T> T[] getAPICall(Class<T> t, Function<ModInfo, ? extends T> function, T... fallbacks) {
return mapEntries(API_CALL, t, function, fallbacks);
}

@SafeVarargs
public static <T> T[] getAnnounced(Class<T> t, Function<ModInfo, ? extends T> function, T ... fallbacks){
public static <T> T[] getAnnounced(Class<T> t, Function<ModInfo, ? extends T> function, T... fallbacks) {
return mapEntries(ANNOUNCED, t, function, fallbacks);
}

@SafeVarargs
private static <T> T[] mapEntries(HashMap<String, ModInfo> map, Class<T> t, Function<ModInfo, ? extends T> function, T ... fallbacks){
if(map.size() == 0){
private static <T> T[] mapEntries(HashMap<String, ModInfo> map, Class<T> t, Function<ModInfo, ? extends T> function, T... fallbacks) {
if(map.size() == 0) {
return fallbacks;
}else{
} else {
return map.values().stream().map(function).collect(Collectors.toList()).toArray((T[]) Array.newInstance(t, map.size()));
}
}
Expand All @@ -115,14 +117,14 @@ public static void addIntegration(ModIntegration integration) {
add(COMPAT, integration.modID);
}

public static void addRegistry(BlazeRegistry<?> registry){
for(var key : registry.keys()){
public static void addRegistry(BlazeRegistry<?> registry) {
for(var key : registry.keys()) {
String mod = key.location.getNamespace();
add(API_CALL, mod);
}
}

private static void add(HashMap<String, ModInfo> map, String modId){
private static void add(HashMap<String, ModInfo> map, String modId) {
var container = ModList.get().getModContainerById(modId);
if(container.isEmpty()) return;
map.put(modId, new ModInfo(container.get()));
Expand All @@ -132,7 +134,7 @@ private static void add(HashMap<String, ModInfo> map, String modId){
public static class ModInfo {
public final String id, name, version;

public ModInfo(ModContainer container){
public ModInfo(ModContainer container) {
this.id = container.getModId();
var info = container.getModInfo();
this.name = info.getDisplayName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class ModIDs {
public static final String FTB_TEAMS = "ftbteams";
public static final String FTB_LIBRARY = "ftblibrary";
public static final String ARCHITECTURY = "architectury";
public static final String WAYSTONES = "waystones";
public static final String BALM = "balm";

public static final List<String> SODIUM_FAMILY = List.of(SODIUM, EMBEDDIUM, RUBIDIUM);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.eerussianguy.blazemap.integration.waystones;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.MinecraftForge;

import com.eerussianguy.blazemap.BlazeMap;
import com.eerussianguy.blazemap.api.markers.Waypoint;
import com.eerussianguy.blazemap.feature.waypoints.service.WaypointChannelLocal;
import com.eerussianguy.blazemap.feature.waypoints.service.WaypointGroup;
import com.eerussianguy.blazemap.feature.waypoints.service.WaypointServiceClient;
import com.eerussianguy.blazemap.integration.ModIDs;
import com.eerussianguy.blazemap.integration.ModIntegration;
import net.blay09.mods.waystones.api.IWaystone;
import net.blay09.mods.waystones.api.KnownWaystonesEvent;

public class WaystonesPlugin extends ModIntegration {
public static final ResourceLocation WAYSTONE = BlazeMap.resource("textures/waypoints/special/waystone.png");
private static final int WHITE = 0xFFFFFFFF;

public WaystonesPlugin() {
super(ModIDs.WAYSTONES, ModIDs.BALM);
}

@Override
public void setup() {
MinecraftForge.EVENT_BUS.addListener(this::onKnownWaystonesEvent);
}

/**
* Event handler for adding waypoints for waystones. The event gets fired on the client
* every time a waystone is added/updated and contains a list of all the current waystones.
*/
private void onKnownWaystonesEvent(KnownWaystonesEvent event) {
var waypointClient = WaypointServiceClient.instance();
Copy link
Contributor

@maddie-j maddie-j Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid using var unless there's a good reason to. Java is a typed language and works best when types are declared correctly!

var waystones = event.getWaystones();

removeDeletedWaystoneWaypoints(waystones);

for(var waystone : waystones) {
var dimension = waystone.getDimension();
var waypoint = new Waypoint(
BlazeMap.resource("waypoint/waystone/" + waystone.getWaystoneUid()),
dimension,
waystone.getPos(),
waystone.getName(),
WAYSTONE,
WHITE
);
var waypointGroups = waypointClient.getPool(WaypointChannelLocal.PRIVATE_POOL).getGroups(dimension);
waypointGroups.stream()
.filter(g -> g.type == WaypointChannelLocal.GROUP_WAYSTONE)
.findFirst()
.ifPresentOrElse(g -> updateWaypoint(g, waypoint), () -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: While short to write, this isn't a particularly performant way of doing this as you're having to:

  1. Check every node
  2. Then go back and find the first element
  3. Then do a check to see if that first element exists.

It also unnecessarily creates a new list, which adds to memory usage and so GC events.

While not as fancy looking, it's better speed and memory efficient if you just did a normal for loop to check each element. That way, you can short circuit as soon as you've found a match, meaning fewer elements are checked in the average case, and you're not creating any unnecessary objects that'll need to be GCed later 😊

It's not a big deal here as the numbers we're talking about are very small. But it's a good habit to get into when writing high-performance code, such as code that runs in real time on the main game thread.

// Add the waystone group if it didn't exist before
// This is so it doesn't need to be a default group (if waystones isn't installed) and
// this is the easiest place to add it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good comment!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to do this check for every waystone present in the event, or can you do it just once before the outer loop an avoid duplicated work?

var group = WaypointGroup.make(WaypointChannelLocal.GROUP_WAYSTONE);
waypointGroups.add(group);
updateWaypoint(group, waypoint);
});
}
}

/**
* Helper to add or updates waypoints to a waypoint group.
*
* @param group The waypoint group to add to.
* @param newWaypoint The waypoint to add/update.
*/
private void updateWaypoint(WaypointGroup group, Waypoint newWaypoint) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helper function might make more sense to put on the WaypointGroup class rather than this one, as it seems to not be Waystones-specific. That way we can reuse this method elsewhere 😊

if(!group.has(newWaypoint)) {
group.add(newWaypoint);
return;
}

// If it already exists update the existing waypoint instead
group.getAll().stream()
.filter(waypoint -> waypoint.getID().equals(newWaypoint.getID()))
.findFirst()
.ifPresent(waypoint -> {
waypoint.setName(newWaypoint.getName());
// I don't know if these change can change but updating them in case it's possible to move waystones
waypoint.setDimension(newWaypoint.getDimension());
waypoint.setPosition(newWaypoint.getPosition());
});
}

/**
* Removes waystone waypoints that are not in the list of known waystones.
*
* @param waystones The list of all known waystones.
*/
private void removeDeletedWaystoneWaypoints(List<IWaystone> waystones) {
var waypointClient = WaypointServiceClient.instance();
var waystoneIds = waystones.stream().map(waystone -> waystone.getWaystoneUid().toString()).toList();

Map<Waypoint, WaypointGroup> waypointsToRemove = new HashMap<>();

waypointClient.getPool(WaypointChannelLocal.PRIVATE_POOL).iterateAll((waypoint, group) -> {
if(group.type != WaypointChannelLocal.GROUP_WAYSTONE) return;

var idParts = waypoint.getID().getPath().split("/");
var id = idParts[idParts.length - 1]; // UUID of Waystone associated with waypoint
if(!waystoneIds.contains(id)) {
waypointsToRemove.put(waypoint, group);
}
});

waypointsToRemove.forEach((waypoint, group) -> group.remove(waypoint));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why put them in a map to delete rather than just delete them then and there? It's extra work you don't have to do and an extra data structure that needs to be GCed.

If it's because that'd be changing a data structure in place, I believe there are iteration methods that are more forgiving for that.

}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.