Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for allay platform #474

Merged
merged 61 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
02a7363
feat: init work on allay
smartcmd Jun 15, 2024
b29ba2d
feat: more works
smartcmd Jun 15, 2024
d81f886
feat: more works
smartcmd Jun 15, 2024
59d7632
feat: add mapping files
smartcmd Jun 15, 2024
2b12541
feat: more works
smartcmd Jun 15, 2024
62e5898
feat: more works
smartcmd Jun 16, 2024
3d4aec4
chores: improve imports
smartcmd Jun 16, 2024
d861d3e
feat: more works
smartcmd Jun 16, 2024
1f937a2
feat: fake entity
smartcmd Jun 16, 2024
133df45
feat: make it works!
smartcmd Jun 16, 2024
6ff0903
fix: fix an mistake
smartcmd Jun 16, 2024
4a3678c
feat: update to 1.21
smartcmd Jun 17, 2024
e68f928
feat: use OtherChunkAccessibleContext directly
smartcmd Jun 18, 2024
2d0e4a8
fix: OtherChunkAccessibleContext.get/setBlockState() should use level…
smartcmd Jun 18, 2024
5fa7007
fix: fix a typo
smartcmd Jun 19, 2024
d490324
feat: support waterlogged
smartcmd Jun 19, 2024
cd767a6
feat: fetch allay's changes
smartcmd Jul 16, 2024
2443fff
feat: fetch allay's changes
smartcmd Jul 16, 2024
4acd0de
feat: fetch allay's changes
smartcmd Jul 24, 2024
a34946c
feat: return air if block type not found
smartcmd Aug 18, 2024
28c689d
feat: fetch allay's changes
smartcmd Aug 18, 2024
c97f25c
feat: support 1.21.20 and newer versions
smartcmd Aug 23, 2024
2e709da
feat: sync allay
smartcmd Aug 27, 2024
5f70ecb
feat: use jitpack
smartcmd Sep 4, 2024
bbf0915
build: use org.allaymc.allay as the group id
smartcmd Sep 7, 2024
732a894
ci: trigger github action
smartcmd Sep 17, 2024
1acdad5
ci: run github action when pushing
smartcmd Sep 17, 2024
f73eadd
ci: use jdk 21
smartcmd Sep 17, 2024
b432a4e
build: use jdk21 for allay platform
smartcmd Sep 17, 2024
2c476a2
build: fix build for allay platform
smartcmd Sep 17, 2024
328ebf5
build: disable cli platform
smartcmd Sep 17, 2024
c6df3c3
build: disable fabric platform
smartcmd Sep 17, 2024
ca4461b
build: disable bukkit platform
smartcmd Sep 17, 2024
6c8a7da
build: disable mixin platform
smartcmd Sep 17, 2024
2f2d43e
build: disable mixin platform
smartcmd Sep 17, 2024
18a2456
ci: upload jar
smartcmd Sep 17, 2024
1f01b99
ci: should check allay branch
smartcmd Sep 17, 2024
ce9fb53
build: disable useless modules
smartcmd Sep 17, 2024
76f12e0
build: prepare for merging
smartcmd Sep 18, 2024
4bad8f7
docs: format javadoc
smartcmd Sep 18, 2024
af2ac64
feat: using the new safe getter api
smartcmd Sep 20, 2024
6042f1c
build: update build.gradle.kts
smartcmd Sep 20, 2024
1496f2c
build: update jitpack repo link
smartcmd Oct 13, 2024
61ed302
feat: adapting terra 6.5.1 (WIP)
smartcmd Oct 14, 2024
4fc24f0
Merge branch 'PolyhedralDev:master' into allay
smartcmd Oct 14, 2024
6261f08
feat: remove java version declaration in allay platform as all platfo…
smartcmd Oct 14, 2024
0ca7171
docs: add README.md to allay platform
smartcmd Oct 14, 2024
a01f700
build: rollback github action file changes
smartcmd Oct 14, 2024
ece5213
feat: use macro in plugin.json and update author list
smartcmd Oct 14, 2024
cc14c71
build: move repo declaration to DependencyConfig.kt
smartcmd Oct 14, 2024
8a6ad95
refactor: delombok and move version info to Versions.kt
smartcmd Oct 14, 2024
f5de882
build: use fixed allay api version
smartcmd Oct 14, 2024
f2c5c15
refactor: use com.dfsek as the new package name
smartcmd Oct 14, 2024
b0bc37c
refactor: remove version info in mapping files
smartcmd Oct 14, 2024
8d63c40
refactor: replace 'var' with explicit type
smartcmd Oct 14, 2024
67fc2ba
docs: remove useless TODOs
smartcmd Oct 14, 2024
84fe879
fix: fix entrance in plugin.json
smartcmd Oct 14, 2024
f0d03d4
feat: fallback to FLAT generator if config pack name is missing
smartcmd Oct 14, 2024
df3e623
feat: implement config pack reloading
smartcmd Oct 14, 2024
d2107fd
fix: chunkGenerator should be overwritten after reloading
smartcmd Oct 14, 2024
071f9d3
docs: fix a typo in README.md
smartcmd Oct 15, 2024
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
8 changes: 8 additions & 0 deletions platforms/allay/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Allay platform

## Resource files

- `mapping/biomes_JE_1_21_to_BE_1_21_30.json` obtain from GeyserMC/mappings.
- `mapping/items_JE_1_21_to_BE_1_21_30.json` obtain from GeyserMC/mappings.
- `mapping/blocks_JE_1_21_to_BE_1_21_30.json` generated by using GeyserMC/mappings-generator, and it's origin name is `generator_blocks.json`.
- `je_block_default_states_1_21.json` converted from https://zh.minecraft.wiki/w/Module:Block_state_values.
smartcmd marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 16 additions & 0 deletions platforms/allay/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
repositories {
maven("https://repo.opencollab.dev/maven-releases/")
maven("https://repo.opencollab.dev/maven-snapshots/")
maven("https://storehouse.okaeri.eu/repository/maven-public/")
maven("https://jitpack.io/")
}
smartcmd marked this conversation as resolved.
Show resolved Hide resolved

dependencies {
shadedApi(project(":common:implementation:base"))
implementation("com.google.code.gson", "gson", "2.11.0")

compileOnly("org.projectlombok:lombok:1.18.32")
compileOnly("org.allaymc.allay:api:master-SNAPSHOT")

annotationProcessor("org.projectlombok:lombok:1.18.32")
}
smartcmd marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.allaymc.terra.allay;
smartcmd marked this conversation as resolved.
Show resolved Hide resolved

import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import org.allaymc.api.server.Server;
import org.allaymc.api.world.biome.BiomeId;
import org.allaymc.terra.allay.delegate.AllayBiome;
import org.allaymc.terra.allay.handle.AllayItemHandle;
import org.allaymc.terra.allay.handle.AllayWorldHandle;
import org.jetbrains.annotations.NotNull;

import java.io.File;

import com.dfsek.terra.AbstractPlatform;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.world.biome.PlatformBiome;


/**
* @author daoge_cmd
*/
public class AllayPlatform extends AbstractPlatform {

protected static final AllayWorldHandle ALLAY_WORLD_HANDLE = new AllayWorldHandle();
protected static final AllayItemHandle ALLAY_ITEM_HANDLE = new AllayItemHandle();

public AllayPlatform() {
load();
}

@Override
public boolean reload() {
// TODO: implement reload
return false;
}

@Override
public @NotNull String platformName() {
return "Allay";
}

@Override
public @NotNull WorldHandle getWorldHandle() {
return ALLAY_WORLD_HANDLE;
}

@Override
public @NotNull ItemHandle getItemHandle() {
return ALLAY_ITEM_HANDLE;
}

@Override
public @NotNull File getDataFolder() {
return TerraAllayPlugin.INSTANCE.getPluginContainer().dataFolder().toFile();
}

@Override
public void runPossiblyUnsafeTask(@NotNull Runnable task) {
Server.getInstance().getScheduler().runLater(Server.getInstance(), task);
}

@Override
public void register(TypeRegistry registry) {
super.register(registry);
registry.registerLoader(BlockState.class, (type, o, loader, depthTracker) -> ALLAY_WORLD_HANDLE.createBlockState((String) o))
.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker));
}

protected AllayBiome parseBiome(String id, DepthTracker depthTracker) throws LoadException {
if(!id.startsWith("minecraft:")) throw new LoadException("Invalid biome identifier " + id, depthTracker);
return new AllayBiome(BiomeId.fromId(Mapping.biomeIdJeToBe(id)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.allaymc.terra.allay;

import org.allaymc.api.utils.HashUtils;

import java.util.TreeMap;


/**
* @author daoge_cmd
*/
public class JeBlockState {
protected final String identifier;
protected final TreeMap<String, String> properties;
protected int hash = Integer.MAX_VALUE;

public static JeBlockState fromString(String data) {
return new JeBlockState(data);
}

public static JeBlockState create(String identifier, TreeMap<String, String> properties) {
return new JeBlockState(identifier, properties);
}

private JeBlockState(String data) {
var strings = data.replace("[", ",").replace("]", ",").replace(" ", "").split(",");
this.identifier = strings[0];
this.properties = new TreeMap<>();
if (strings.length > 1) {
for (int i = 1; i < strings.length; i++) {
final var tmp = strings[i];
final var index = tmp.indexOf("=");
properties.put(tmp.substring(0, index), tmp.substring(index + 1));
}
}
completeMissingProperties();
}

public String getPropertyValue(String key) {
return properties.get(key);
}

private void completeMissingProperties() {
var defaultProperties = Mapping.getJeBlockDefaultProperties(identifier);
if(properties.size() == defaultProperties.size()) {
return;
}
for (var entry : defaultProperties.entrySet()) {
if (properties.containsKey(entry.getKey())) continue;
properties.put(entry.getKey(), entry.getValue());
}
}

private JeBlockState(String identifier, TreeMap<String, String> properties) {
this.identifier = identifier;
this.properties = properties;
}

public String toString(boolean includeProperties) {
if(!includeProperties) return identifier;
StringBuilder builder = new StringBuilder(identifier).append(";");
properties.forEach((k, v) -> builder.append(k).append("=").append(v).append(";"));
var str = builder.toString();
if (hash == Integer.MAX_VALUE) {
hash = HashUtils.fnv1a_32(str.getBytes());
}
return str;
}

public int getHash() {
if (hash == Integer.MAX_VALUE) {
hash = HashUtils.fnv1a_32(toString(true).getBytes());
}
return hash;
}

@Override
public String toString() {
return toString(true);
}
}
189 changes: 189 additions & 0 deletions platforms/allay/src/main/java/org/allaymc/terra/allay/Mapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package org.allaymc.terra.allay;

import com.google.gson.reflect.TypeToken;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.extern.slf4j.Slf4j;
import org.allaymc.api.block.type.BlockState;
import org.allaymc.api.block.type.BlockStateSafeGetter;
import org.allaymc.api.block.type.BlockTypes;
import org.allaymc.api.item.type.ItemType;
import org.allaymc.api.item.type.ItemTypeSafeGetter;
import org.allaymc.api.utils.JSONUtils;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;


/**
* @author daoge_cmd
*/
@Slf4j
smartcmd marked this conversation as resolved.
Show resolved Hide resolved
public final class Mapping {

private static final Map<String, Map<String, String>> JE_BLOCK_DEFAULT_PROPERTIES = new Object2ObjectOpenHashMap<>();
private static final Map<BlockState, JeBlockState> BLOCK_STATE_BE_TO_JE = new Object2ObjectOpenHashMap<>();
private static final Map<Integer, BlockState> BLOCK_STATE_JE_HASH_TO_BE = new Int2ObjectOpenHashMap<>();
private static final Map<String, ItemType<?>> ITEM_ID_JE_TO_BE = new Object2ObjectOpenHashMap<>();
private static final Map<String, Integer> BIOME_ID_JE_TO_BE = new Object2IntOpenHashMap<>();
private static final BlockState BE_AIR_STATE = BlockTypes.AIR.getDefaultState();

public static void init() {
if(!initBlockStateMapping()) error();
if(!initJeBlockDefaultProperties()) error();
if(!initItemMapping()) error();
if(!initBiomeMapping()) error();
}

public static JeBlockState blockStateBeToJe(BlockState beBlockState) {
return BLOCK_STATE_BE_TO_JE.get(beBlockState);
}

public static BlockState blockStateJeToBe(JeBlockState jeBlockState) {
var result = BLOCK_STATE_JE_HASH_TO_BE.get(jeBlockState.getHash());
if(result == null) {
log.warn("Failed to find be block state for {}", jeBlockState);
return BE_AIR_STATE;
}
return result;
}

public static ItemType<?> itemIdJeToBe(String jeItemId) {
return ITEM_ID_JE_TO_BE.get(jeItemId);
}

// Enchantment identifiers are same in both versions

public static String enchantmentIdBeToJe(String beEnchantmentId) {
return beEnchantmentId;
}

public static String enchantmentIdJeToBe(String jeEnchantmentId) {
return jeEnchantmentId;
}

public static int biomeIdJeToBe(String jeBiomeId) {
return BIOME_ID_JE_TO_BE.get(jeBiomeId);
}

public static Map<String, String> getJeBlockDefaultProperties(String jeBlockIdentifier) {
var defaultProperties = JE_BLOCK_DEFAULT_PROPERTIES.get(jeBlockIdentifier);
if( defaultProperties == null) {
log.warn("Failed to find default properties for {}", jeBlockIdentifier);
return Map.of();
}
return defaultProperties;
}

private static void error() {
throw new RuntimeException("Mapping not initialized");
}

private static boolean initBiomeMapping() {
try (var stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/biomes_JE_1_21_to_BE_1_21_30.json")) {
if (stream == null) {
log.error("biomes mapping not found");
return false;
}
var mappings = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, Integer>>>(){}).entrySet();
for(var mapping : mappings) {
BIOME_ID_JE_TO_BE.put(mapping.getKey(), mapping.getValue().get("bedrock_id"));
}
} catch(IOException e) {
log.error("Failed to load biomes mapping", e);
return false;
}
return true;
}

private static boolean initItemMapping() {
try (var stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/items_JE_1_21_to_BE_1_21_30.json")) {
if (stream == null) {
log.error("items mapping not found");
return false;
}
var mappings = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, Object>>>(){}).entrySet();
for(var mapping : mappings) {
var item = ItemTypeSafeGetter
.name((String) mapping.getValue().get("bedrock_identifier"))
// NOTICE: should be cast to double
.meta(((Double) mapping.getValue().get("bedrock_data")).intValue())
.itemType();
ITEM_ID_JE_TO_BE.put(mapping.getKey(), item);
}
} catch(IOException e) {
log.error("Failed to load items mapping", e);
}
return true;
}

private static boolean initBlockStateMapping() {
try (var stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/blocks_JE_1_21_to_BE_1_21_30.json")) {
if (stream == null) {
log.error("blocks mapping not found");
return false;
}
// noinspection unchecked
var mappings = (List<Map<String, Map<String, Object>>>) JSONUtils.from(stream, new TypeToken<Map<String, Object>>(){}).get("mappings");
for(var mapping : mappings) {
var jeState = createJeBlockState(mapping.get("java_state"));
var beState = createBeBlockState(mapping.get("bedrock_state"));
BLOCK_STATE_BE_TO_JE.put(beState, jeState);
BLOCK_STATE_JE_HASH_TO_BE.put(jeState.getHash(), beState);
}
} catch(IOException e) {
log.error("Failed to load blocks mapping", e);
}
return true;
}

private static boolean initJeBlockDefaultProperties() {
try (var stream = Mapping.class.getClassLoader().getResourceAsStream("je_block_default_states_1_21.json")) {
if (stream == null) {
log.error("je_block_default_states.json not found");
return false;
}
var states = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, String>>>(){});
for(var entry : states.entrySet()) {
var identifier = entry.getKey();
var properties = entry.getValue();
JE_BLOCK_DEFAULT_PROPERTIES.put(identifier, properties);
}
} catch(IOException e) {
throw new RuntimeException(e);
}
return true;
}

private static BlockState createBeBlockState(Map<String, Object> data) {
var getter = BlockStateSafeGetter
.name("minecraft:" + data.get("bedrock_identifier"));
if (data.containsKey("state")) {
// noinspection unchecked
convertValueType((Map<String, Object>) data.get("state")).forEach(getter::property);
}
return getter.blockState();
}

private static Map<String, Object> convertValueType(Map<String, Object> data) {
var result = new TreeMap<String, Object>();
for (var entry : data.entrySet()) {
if (entry.getValue() instanceof Number number) {
// Convert double to int because the number in json is double
result.put(entry.getKey(), number.intValue());
} else {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
}

private static JeBlockState createJeBlockState(Map<String, Object> data) {
var identifier = (String) data.get("Name");
// noinspection unchecked
return JeBlockState.create(identifier, new TreeMap<>((Map<String, String>) data.getOrDefault("Properties", Map.of())));
}
}
Loading
Loading