Skip to content

Commit 5bf3af2

Browse files
committed
Entity type id mapping
1 parent 26104a5 commit 5bf3af2

File tree

6 files changed

+130
-59
lines changed

6 files changed

+130
-59
lines changed

client/src/main/java/com/fox2code/foxloader/registry/GameRegistryClient.java

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public class GameRegistryClient extends GameRegistry {
3434
public static final short[] blockIdMappingIn = new short[MAXIMUM_BLOCK_ID];
3535
public static final short[] blockIdMappingOut = new short[MAXIMUM_BLOCK_ID];
3636
public static final String[] itemIdMappingInNames = new String[MAXIMUM_ITEM_ID];
37+
38+
public static final int[] entityTypeIdMappingIn = new int[MAXIMUM_ENTITY_TYPE_ID];
39+
public static final int[] entityTypeIdMappingOut = new int[MAXIMUM_ENTITY_TYPE_ID];
40+
public static final String[] entityTypeIdMappingNames = new String[MAXIMUM_ENTITY_TYPE_ID];
41+
3742
private static MappingState idMappingState = MappingState.CLIENT;
3843
private enum MappingState {
3944
CLIENT, SERVER, CUSTOM
@@ -129,13 +134,17 @@ public int generateNewItemId(String name, int fallbackId) {
129134
if (registryEntries.containsKey(name)) {
130135
throw new RuntimeException("Duplicate item/block string id: " + name);
131136
}
137+
132138
if (fallbackId < 0 || fallbackId > 255) {
133139
throw new IllegalArgumentException("Invalid fallback id: " + fallbackId);
134140
}
141+
135142
int itemId = nextItemId++;
143+
136144
if (itemId > MAXIMUM_ITEM_ID) {
137145
throw new RuntimeException("Maximum block count registered! (Too many mods?)");
138146
}
147+
139148
registryEntries.put(name, new RegistryEntry((short) itemId, (short) fallbackId, name,
140149
StringTranslate.getInstance().translateKey("item." + name.replace(':', '.'))));
141150
return itemId;
@@ -147,10 +156,15 @@ public int generateNewEntityTypeId(String name, int fallbackId) {
147156
throw new RuntimeException("Duplicate entity string id: " + name);
148157
}
149158

159+
if (fallbackId < 0 || fallbackId > 202) {
160+
throw new IllegalArgumentException("Invalid fallback id: " + fallbackId);
161+
}
162+
150163
int entityTypeId = nextEntityTypeId++;
151164

152-
if (entityTypeId > MAXIMUM_ITEM_ID) {
153-
throw new RuntimeException("Maximum block count registered! (Too many mods?)");
165+
if (entityTypeId > MAXIMUM_ENTITY_TYPE_ID) {
166+
// This is extremely unlikely
167+
throw new RuntimeException("Maximum entity type count registered! (Too many mods?)");
154168
}
155169

156170
entityTypeEntries.put(name, new EntityTypeRegistryEntry(entityTypeId, fallbackId, name));
@@ -399,11 +413,11 @@ public static void resetMappings(boolean singlePlayer) {
399413
itemIdMappingIn[i] = DEFAULT_FALLBACK_BLOCK_ID;
400414
itemIdMappingOut[i] = DEFAULT_FALLBACK_BLOCK_ID;
401415
}
402-
for (int i = INITIAL_BLOCK_ID; i < MAXIMUM_BLOCK_ID; i++) {
416+
for (short i = INITIAL_BLOCK_ID; i < MAXIMUM_BLOCK_ID; i++) {
403417
blockIdMappingIn[i] = DEFAULT_FALLBACK_BLOCK_ID;
404418
blockIdMappingOut[i] = DEFAULT_FALLBACK_BLOCK_ID;
405419
}
406-
for (int i = INITIAL_ITEM_ID; i < MAXIMUM_ITEM_ID; i++) {
420+
for (short i = INITIAL_ITEM_ID; i < MAXIMUM_ITEM_ID; i++) {
407421
itemIdMappingIn[i] = DEFAULT_FALLBACK_ITEM_ID;
408422
itemIdMappingOut[i] = DEFAULT_FALLBACK_ITEM_ID;
409423
}
@@ -423,35 +437,46 @@ public static void initializeMappings(ServerHello serverHello) {
423437
return;
424438
}
425439
idMappingState = MappingState.CUSTOM;
426-
for (RegistryEntry registryEntry : serverHello.registryEntries.values()) {
427-
final short remoteId = registryEntry.realId;
440+
for (RegistryEntry entry : serverHello.registryEntries.values()) {
441+
final short remoteId = entry.realId;
428442
if (isLoaderReservedItemId(remoteId)) {
429-
RegistryEntry local = registryEntries.get(
430-
itemIdMappingInNames[remoteId] = registryEntry.name);
443+
RegistryEntry local = registryEntries.get(itemIdMappingInNames[remoteId] = entry.name);
431444
if (local == null) {
432-
itemIdMappingIn[remoteId] = registryEntry.fallbackId;
445+
itemIdMappingIn[remoteId] = entry.fallbackId;
433446
if (remoteId >= INITIAL_TRANSLATED_BLOCK_ID &&
434447
remoteId < MAXIMUM_TRANSLATED_BLOCK_ID) {
435-
blockIdMappingIn[convertItemIdToBlockId(remoteId)] = registryEntry.fallbackId;
448+
blockIdMappingIn[convertItemIdToBlockId(remoteId)] = entry.fallbackId;
436449
}
437450
} else {
438451
itemIdMappingIn[remoteId] = local.realId;
439452
itemIdMappingOut[local.realId] = remoteId;
440-
if (remoteId >= INITIAL_TRANSLATED_BLOCK_ID &&
441-
remoteId < MAXIMUM_TRANSLATED_BLOCK_ID) {
442-
if (local.realId >= INITIAL_TRANSLATED_BLOCK_ID &&
443-
local.realId < MAXIMUM_TRANSLATED_BLOCK_ID) {
453+
if (remoteId >= INITIAL_TRANSLATED_BLOCK_ID && remoteId < MAXIMUM_TRANSLATED_BLOCK_ID) {
454+
if (local.realId >= INITIAL_TRANSLATED_BLOCK_ID && local.realId < MAXIMUM_TRANSLATED_BLOCK_ID) {
444455
final short remoteBlockId = (short) convertItemIdToBlockId(remoteId);
445456
final short localBlockId = (short) convertItemIdToBlockId(local.realId);
446457
blockIdMappingIn[remoteBlockId] = localBlockId;
447458
blockIdMappingOut[localBlockId] = remoteBlockId;
448459
} else {
449460
// We should never reach here, but let still "support" this extreme case.
450-
blockIdMappingIn[convertItemIdToBlockId(remoteId)] = registryEntry.fallbackId;
461+
blockIdMappingIn[convertItemIdToBlockId(remoteId)] = entry.fallbackId;
451462
}
452463
}
453464
}
454465
}
455466
}
467+
468+
for (EntityTypeRegistryEntry entry : serverHello.entityTypeRegistryEntries.values()) {
469+
final int remoteId = entry.realId;
470+
if (isLoaderReservedEntityTypeId(remoteId)) {
471+
EntityTypeRegistryEntry local = entityTypeEntries.get(entityTypeIdMappingNames[remoteId] = entry.name);
472+
if (local == null) {
473+
entityTypeIdMappingIn[remoteId] = entry.fallbackId;
474+
continue;
475+
}
476+
477+
entityTypeIdMappingIn[remoteId] = local.realId;
478+
entityTypeIdMappingOut[local.realId] = remoteId;
479+
}
480+
}
456481
}
457482
}
Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.fox2code.foxloader.loader.packet;
22

3+
import com.fox2code.foxloader.registry.EntityTypeRegistryEntry;
34
import com.fox2code.foxloader.registry.RegistryEntry;
45

56
import java.io.DataInputStream;
@@ -9,64 +10,92 @@
910
import java.util.Map;
1011

1112
public final class ServerHello extends FoxPacket {
12-
public static final int SERVER_HELLO_VERSION = 0;
13+
public static final int SERVER_HELLO_VERSION = 1;
1314
private static final int SERVER_HELLO_VERSION_NEXT = 1;
1415

1516
public HashMap<String, RegistryEntry> registryEntries;
1617
public HashMap<String, String> metadata;
18+
public HashMap<String, EntityTypeRegistryEntry> entityTypeRegistryEntries;
1719

1820
public ServerHello() {
1921
super(0, false);
2022
}
2123

2224
public ServerHello(HashMap<String, RegistryEntry> registryEntries,
23-
HashMap<String, String> metadata) {
25+
HashMap<String, String> metadata,
26+
HashMap<String, EntityTypeRegistryEntry> entityTypeRegistryEntries) {
2427
super(0, false);
2528
this.registryEntries = registryEntries;
2629
this.metadata = metadata;
30+
this.entityTypeRegistryEntries = entityTypeRegistryEntries;
2731
}
2832

2933
@Override
30-
public void readData(DataInputStream dataInputStream) throws IOException {
31-
int serverHelloVersion = dataInputStream.readUnsignedShort();
34+
public void readData(DataInputStream inStream) throws IOException {
35+
int serverHelloVersion = inStream.readUnsignedShort();
3236
if (serverHelloVersion >= SERVER_HELLO_VERSION_NEXT &&
3337
// Next field is how much backward compatible is the packet
34-
dataInputStream.readUnsignedShort() > SERVER_HELLO_VERSION_NEXT) {
38+
inStream.readUnsignedShort() > SERVER_HELLO_VERSION_NEXT) {
3539
throw new RuntimeException("Client is critically out of date, please update FoxLoader");
3640
}
37-
int entries = dataInputStream.readUnsignedShort();
38-
registryEntries = new HashMap<>(entries);
39-
while (entries-->0) {
40-
RegistryEntry registryEntry = new RegistryEntry(
41-
dataInputStream.readShort(), dataInputStream.readShort(),
42-
dataInputStream.readUTF(), dataInputStream.readUTF());
43-
registryEntries.put(registryEntry.name, registryEntry);
41+
42+
int entries = inStream.readUnsignedShort();
43+
this.registryEntries = new HashMap<>(entries);
44+
while (entries-- > 0) {
45+
RegistryEntry entry = new RegistryEntry(
46+
inStream.readShort(), inStream.readShort(),
47+
inStream.readUTF(), inStream.readUTF());
48+
this.registryEntries.put(entry.name, entry);
4449
}
45-
if (dataInputStream.available() == 0) {
50+
51+
if (inStream.available() < 2) {
52+
// Too few bytes to read the next short.
53+
this.metadata = new HashMap<>();
54+
} else {
55+
entries = inStream.readUnsignedShort();
4656
metadata = new HashMap<>();
47-
return;
57+
while (entries-- > 0) {
58+
metadata.put(inStream.readUTF(), inStream.readUTF());
59+
}
4860
}
49-
entries = dataInputStream.readUnsignedShort();
50-
metadata = new HashMap<>();
51-
while (entries-->0) {
52-
metadata.put(dataInputStream.readUTF(), dataInputStream.readUTF());
61+
62+
if (inStream.available() < 4) {
63+
// Too few bytes to read the next integer.
64+
this.entityTypeRegistryEntries = new HashMap<>();
65+
} else {
66+
int entityEntries = inStream.readInt();
67+
entityTypeRegistryEntries = new HashMap<>(entityEntries);
68+
while (entityEntries-- > 0) {
69+
EntityTypeRegistryEntry entry = new EntityTypeRegistryEntry(
70+
inStream.readInt(), inStream.readInt(), inStream.readUTF());
71+
this.entityTypeRegistryEntries.put(entry.name, entry);
72+
}
5373
}
5474
}
5575

5676
@Override
57-
public void writeData(DataOutputStream dataOutputStream) throws IOException {
58-
dataOutputStream.writeShort(SERVER_HELLO_VERSION);
59-
dataOutputStream.writeShort(this.registryEntries.size());
77+
public void writeData(DataOutputStream outStream) throws IOException {
78+
outStream.writeShort(SERVER_HELLO_VERSION);
79+
80+
outStream.writeShort(this.registryEntries.size());
6081
for (RegistryEntry registryEntry : registryEntries.values()) {
61-
dataOutputStream.writeShort(registryEntry.realId);
62-
dataOutputStream.writeByte(registryEntry.fallbackId);
63-
dataOutputStream.writeUTF(registryEntry.name);
64-
dataOutputStream.writeUTF(registryEntry.fallbackDisplayName);
82+
outStream.writeShort(registryEntry.realId);
83+
outStream.writeByte(registryEntry.fallbackId);
84+
outStream.writeUTF(registryEntry.name);
85+
outStream.writeUTF(registryEntry.fallbackDisplayName);
6586
}
66-
dataOutputStream.writeShort(this.metadata.size());
87+
88+
outStream.writeShort(this.metadata.size());
6789
for (Map.Entry<String, String> metadata : this.metadata.entrySet()) {
68-
dataOutputStream.writeUTF(metadata.getKey());
69-
dataOutputStream.writeUTF(metadata.getValue());
90+
outStream.writeUTF(metadata.getKey());
91+
outStream.writeUTF(metadata.getValue());
92+
}
93+
94+
outStream.writeInt(this.entityTypeRegistryEntries.size());
95+
for (EntityTypeRegistryEntry entry : entityTypeRegistryEntries.values()) {
96+
outStream.writeInt(entry.realId);
97+
outStream.writeInt(entry.fallbackId);
98+
outStream.writeUTF(entry.name);
7099
}
71100
}
72101
}

common/src/main/java/com/fox2code/foxloader/registry/EntityTypeRegistryEntry.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.fox2code.foxloader.registry;
22

3+
import org.jetbrains.annotations.ApiStatus;
4+
35
public class EntityTypeRegistryEntry {
46
public final int realId, fallbackId;
57
public final String name;
68

7-
EntityTypeRegistryEntry(int realId, int fallbackId, String name) {
9+
@ApiStatus.Internal
10+
public EntityTypeRegistryEntry(int realId, int fallbackId, String name) {
811
this.realId = realId;
912
this.fallbackId = fallbackId;
1013
this.name = name;

common/src/main/java/com/fox2code/foxloader/registry/GameRegistry.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ public abstract class GameRegistry {
1616
public static final int INITIAL_BLOCK_ID = 360;
1717
public static final int MAXIMUM_BLOCK_ID = 1024; // Hard max: 1258
1818
public static final int INITIAL_ITEM_ID = 4096;
19-
public static final int INITIAL_ENTITY_TYPE_ID = 210;
2019
public static final int MAXIMUM_ITEM_ID = 8192; // Hard max: 31999
20+
public static final int INITIAL_ENTITY_TYPE_ID = 210;
21+
// Array size limit is fuzzy so lets avoid it.
22+
public static final int MAXIMUM_ENTITY_TYPE_ID = Integer.MAX_VALUE - Short.MAX_VALUE;
2123
// Block ids but translated to item ids
2224
public static final int INITIAL_TRANSLATED_BLOCK_ID = convertBlockIdToItemId(INITIAL_BLOCK_ID);
2325
public static final int MAXIMUM_TRANSLATED_BLOCK_ID = convertBlockIdToItemId(MAXIMUM_BLOCK_ID);
@@ -240,21 +242,27 @@ public static void validateRegistryName(String name) {
240242

241243
/**
242244
* @param itemId the item id
243-
* @return if the id is reserved for mod loader use
245+
* @return if the id is an item id reserved for mod loader use
244246
*/
245247
public static boolean isLoaderReservedItemId(int itemId) {
246-
return (itemId >= INITIAL_TRANSLATED_BLOCK_ID &&
247-
itemId < MAXIMUM_TRANSLATED_BLOCK_ID) ||
248-
(itemId >= INITIAL_ITEM_ID && itemId < MAXIMUM_ITEM_ID);
248+
return (itemId >= INITIAL_TRANSLATED_BLOCK_ID && itemId < MAXIMUM_TRANSLATED_BLOCK_ID)
249+
|| (itemId >= INITIAL_ITEM_ID && itemId < MAXIMUM_ITEM_ID);
249250
}
250251

251252
/**
252253
* @param itemId the item id
253-
* @return if the id is reserved for mod loader and a block
254+
* @return if the id is a block id reserved for mod loader use
254255
*/
255256
public static boolean isLoaderReservedBlockItemId(int itemId) {
256-
return (itemId >= INITIAL_TRANSLATED_BLOCK_ID &&
257-
itemId < MAXIMUM_TRANSLATED_BLOCK_ID);
257+
return itemId >= INITIAL_TRANSLATED_BLOCK_ID && itemId < MAXIMUM_TRANSLATED_BLOCK_ID;
258+
}
259+
260+
/**
261+
* @param entityTypeId the entity type id
262+
* @return if the id is an entity id reserved for mod loader use
263+
*/
264+
public static boolean isLoaderReservedEntityTypeId(int entityTypeId) {
265+
return entityTypeId >= INITIAL_ENTITY_TYPE_ID && entityTypeId < MAXIMUM_ENTITY_TYPE_ID;
258266
}
259267

260268
public interface Ingredient {}

common/src/main/java/com/fox2code/foxloader/registry/RegistryEntry.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.fox2code.foxloader.registry;
22

3+
import org.jetbrains.annotations.ApiStatus;
4+
35
public final class RegistryEntry {
46
public final short realId, fallbackId;
57
public final String name, fallbackDisplayName;
68

9+
@ApiStatus.Internal
710
public RegistryEntry(short realId, short fallbackId, String name, String fallbackDisplayName) {
811
this.realId = realId;
912
this.fallbackId = fallbackId;

server/src/main/java/com/fox2code/foxloader/registry/GameRegistryServer.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,24 @@ public static void initialize() {
4242

4343
public static void freeze() {
4444
if (!ModLoader.areAllModsLoaded())
45-
throw new IllegalArgumentException("Mods didn't finished to load!");
45+
throw new IllegalArgumentException("Mods haven't finished loading!");
4646
// Compile server hello into a byte array for memory and performance efficiency.
4747
serverHello = ModLoader.Internal.compileServerHello(
48-
new ServerHello(GameRegistry.registryEntries,
49-
new HashMap<>(SidedMetadataAPI.getSelfMetadata())));
50-
final Block stoneBlock = Block.blocksList[0];
48+
new ServerHello(
49+
GameRegistry.registryEntries,
50+
new HashMap<>(SidedMetadataAPI.getSelfMetadata()),
51+
GameRegistry.entityTypeEntries
52+
));
53+
final Block airBlock = Block.blocksList[0]; // was named "stoneBlock" but that is incorrect
5154
for (int i = 0; i < Block.blocksList.length; i++) {
5255
if (Block.blocksList[i] == null) {
53-
Block.blocksList[i] = stoneBlock;
56+
Block.blocksList[i] = airBlock;
5457
}
5558
}
56-
final Item stoneItem = Item.itemsList[0];
59+
final Item airItem = Item.itemsList[0]; // was named "stoneItem" but that is incorrect
5760
for (int i = 0; i < Item.itemsList.length; i++) {
5861
if (Item.itemsList[i] == null) {
59-
Item.itemsList[i] = stoneItem;
62+
Item.itemsList[i] = airItem;
6063
}
6164
}
6265
}

0 commit comments

Comments
 (0)