generated from KessokuTeaTime/Example-Mod
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
130 changes: 130 additions & 0 deletions
130
src/main/java/net/krlite/knowledges/config/modmenu/cache/Cache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package net.krlite.knowledges.config.modmenu.cache; | ||
|
||
import com.google.common.base.Charsets; | ||
import com.google.common.collect.ImmutableMap; | ||
import com.google.common.reflect.TypeToken; | ||
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; | ||
import net.fabricmc.loader.api.FabricLoader; | ||
import net.krlite.knowledges.KnowledgesClient; | ||
import net.krlite.knowledges.KnowledgesCommon; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.lang.reflect.Type; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.*; | ||
import java.util.function.Consumer; | ||
|
||
public abstract class Cache<K, V> { | ||
public static final Path PATH = FabricLoader.getInstance().getConfigDir().resolve(KnowledgesCommon.ID).resolve("cache"); | ||
|
||
private final Map<K, V> map = new HashMap<>(); | ||
private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); | ||
private final File file; | ||
private boolean loading = false; | ||
|
||
protected Cache(String fileName) { | ||
this.file = PATH.resolve(fileName + ".json").toFile(); | ||
} | ||
|
||
protected abstract boolean validate(V value); | ||
|
||
public Map<K, V> asMap() { | ||
return ImmutableMap.copyOf(map); | ||
} | ||
|
||
public boolean containsKey(K key) { | ||
return asMap().containsKey(key); | ||
} | ||
|
||
public void put(K key, V value) { | ||
if (validate(value)) { | ||
V prev = map.put(key, value); | ||
if (!loading && !Objects.equals(prev, value)) { | ||
save(); | ||
} | ||
} | ||
} | ||
|
||
public void putIfAbsent(K key, V value) { | ||
if (containsKey(key)) return; | ||
put(key, value); | ||
} | ||
|
||
public Optional<V> get(K key) { | ||
return Optional.ofNullable(containsKey(key) ? asMap().get(key) : null); | ||
} | ||
|
||
public V getOrDefault(K key, V defaultValue) { | ||
return get(key).orElse(defaultValue); | ||
} | ||
|
||
public Optional<V> remove(K key) { | ||
V prev = map.remove(key); | ||
if (prev != null) { | ||
save(); | ||
} | ||
|
||
return Optional.ofNullable(prev); | ||
} | ||
|
||
public void operate(Consumer<Map<K, V>> mapConsumer) { | ||
mapConsumer.accept(map); | ||
} | ||
|
||
protected void save() { | ||
if (!file.exists()) { | ||
file.mkdirs(); | ||
} | ||
|
||
new SaveThread(file, gson.toJson(asMap())).start(); | ||
} | ||
|
||
protected void load() { | ||
if (!file.exists()) { | ||
save(); | ||
return; | ||
} | ||
|
||
loading = true; | ||
try (final BufferedReader reader = Files.newBufferedReader(file.toPath(), Charsets.UTF_8)) { | ||
Type type = new TypeToken<Map<UUID, String>>() {}.getType(); | ||
Map<K, V> tempMap = gson.fromJson(reader, type); | ||
|
||
if (tempMap != null) { | ||
map.clear(); | ||
tempMap.forEach(this::put); | ||
} | ||
} catch (Exception e) { | ||
KnowledgesClient.LOGGER.error("Error caching! Deleting file {}", file.getPath()); | ||
file.delete(); | ||
} finally { | ||
loading = false; | ||
} | ||
} | ||
|
||
private static class SaveThread extends Thread { | ||
private final File file; | ||
private final String data; | ||
|
||
public SaveThread(File file, String data) { | ||
this.file = file; | ||
this.data = data; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
try { | ||
// Make sure we don't save when another thread is still saving | ||
synchronized (file) { | ||
Files.writeString(file.toPath(), data); | ||
} | ||
} catch (IOException e) { | ||
KnowledgesClient.LOGGER.error("Failed saving cache!"); | ||
} | ||
} | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
src/main/java/net/krlite/knowledges/config/modmenu/cache/UsernameCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package net.krlite.knowledges.config.modmenu.cache; | ||
|
||
import com.mojang.authlib.GameProfile; | ||
import com.mojang.authlib.yggdrasil.ProfileResult; | ||
import net.krlite.knowledges.KnowledgesClient; | ||
import net.minecraft.client.MinecraftClient; | ||
|
||
import java.util.*; | ||
|
||
public class UsernameCache extends Cache<UUID, String> { | ||
private final Set<UUID> downloading = Collections.synchronizedSet(new HashSet<>()); | ||
|
||
public UsernameCache() { | ||
super("username"); | ||
} | ||
|
||
@Override | ||
protected boolean validate(String value) { | ||
return !value.isEmpty() && !value.contains("§"); | ||
} | ||
|
||
@Override | ||
public Optional<String> get(UUID key) { | ||
if (!containsKey(key)) { | ||
download(key); | ||
} | ||
|
||
return super.get(key); | ||
} | ||
|
||
private void download(UUID uuid) { | ||
if (downloading.contains(uuid)) return; | ||
new DownloadThread(this, uuid).start(); | ||
} | ||
|
||
private static class DownloadThread extends Thread { | ||
private final UsernameCache callback; | ||
private final UUID uuid; | ||
|
||
public DownloadThread(UsernameCache callback, UUID uuid) { | ||
this.callback = callback; | ||
this.uuid = uuid; | ||
|
||
callback.downloading.add(uuid); | ||
} | ||
|
||
@Override | ||
public void run() { | ||
try { | ||
ProfileResult profileResult = MinecraftClient.getInstance().getSessionService().fetchProfile(uuid, true); | ||
if (profileResult == null) { | ||
return; | ||
} | ||
|
||
GameProfile profile = profileResult.profile(); | ||
if (profile.getName() == null || profile.getName().equals("???")) { | ||
return; | ||
} | ||
|
||
callback.put(profile.getId(), profile.getName()); | ||
callback.downloading.remove(uuid); | ||
} catch (Exception e) { | ||
KnowledgesClient.LOGGER.error("Error downloading player profile!", e); | ||
} | ||
} | ||
} | ||
} |