Skip to content

Commit

Permalink
Merge pull request #388 from mircokroon/minecraft-1.19
Browse files Browse the repository at this point in the history
Minecraft 1.19
  • Loading branch information
mircokroon authored Jun 15, 2022
2 parents 072c07f + 749e186 commit 1b40f80
Show file tree
Hide file tree
Showing 36 changed files with 664 additions and 114 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Cross-platform jar (GUI & commandline): [world-downloader.jar](https://github.co

### Requirements
- Java 17 or higher
- Minecraft version 1.12.2+ // 1.13.2+ // 1.14.1+ // 1.15.2+ // 1.16.2+ // 1.17+ // 1.18+
- Minecraft version 1.12.2+ // 1.13.2+ // 1.14.1+ // 1.15.2+ // 1.16.2+ // 1.17+ // 1.18+ // 1.19+

### Basic usage
[Download](https://github.com/mircokroon/minecraft-world-downloader/releases/latest/download/world-downloader.exe) the latest release and run it. Enter the server address in the address field and press start. Instead of connecting to the server itself, connect to `localhost` in Minecraft to start downloading the world.
Expand Down
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@


<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>


<dependency>
<groupId>org.nanohttpd</groupId>
<artifactId>nanohttpd</artifactId>
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/config/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public enum Version {
V1_16(701, 2578),
V1_17(755, 2724),
V1_18(757, 2860),
V1_19(759, 3105),
ANY(0, 0);

public final int dataVersion;
Expand All @@ -28,6 +29,7 @@ boolean isVersion(VersionReporter versionReporter) {
case V1_16 -> versionReporter.isAtLeast1_16();
case V1_17 -> versionReporter.isAtLeast1_17();
case V1_18 -> versionReporter.isAtLeast1_18();
case V1_19 -> versionReporter.isAtLeast1_19();
case ANY -> true;
default -> false;
};
Expand All @@ -42,6 +44,7 @@ public boolean isDataVersion(int dataVersion) {
case V1_16: return VersionReporter.isAtLeast1_16(dataVersion);
case V1_17: return VersionReporter.isAtLeast1_17(dataVersion);
case V1_18: return VersionReporter.isAtLeast1_18(dataVersion);
case V1_19: return VersionReporter.isAtLeast1_19(dataVersion);
case ANY: return true;
default: return false;
}
Expand Down
24 changes: 3 additions & 21 deletions src/main/java/config/VersionReporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public boolean isAtLeast1_17() {
return protocolVersion >= Version.V1_17.protocolVersion;
}
public boolean isAtLeast1_18() { return protocolVersion >= Version.V1_18.protocolVersion; }
public boolean isAtLeast1_19() { return protocolVersion >= Version.V1_19.protocolVersion; }

public static boolean isAtLeast1_12(int dataVersion) {
return dataVersion >= Version.V1_12.dataVersion;
Expand All @@ -80,26 +81,7 @@ public static boolean isAtLeast1_17(int dataVersion) {
public static boolean isAtLeast1_18(int dataVersion) {
return dataVersion >= Version.V1_18.dataVersion;
}

public boolean is1_12() {
return protocolVersion >= Version.V1_12.protocolVersion && protocolVersion < Version.V1_13.protocolVersion;
}
public boolean is1_13() {
return protocolVersion >= Version.V1_13.protocolVersion && protocolVersion < Version.V1_14.protocolVersion;
}
public boolean is1_14() {
return protocolVersion >= Version.V1_14.protocolVersion && protocolVersion < Version.V1_15.protocolVersion;
}
public boolean is1_15() {
return protocolVersion >= Version.V1_15.protocolVersion && protocolVersion < Version.V1_16.protocolVersion;
}
public boolean is1_16() {
return protocolVersion >= Version.V1_16.protocolVersion && protocolVersion < Version.V1_17.protocolVersion;
}
public boolean is1_17() {
return protocolVersion >= Version.V1_17.protocolVersion && protocolVersion < Version.V1_18.protocolVersion;
}
public boolean is1_18() {
return protocolVersion >= Version.V1_18.protocolVersion;
public static boolean isAtLeast1_19(int dataVersion) {
return dataVersion >= Version.V1_19.dataVersion;
}
}
11 changes: 8 additions & 3 deletions src/main/java/game/data/chunk/ChunkEntities.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ public ChunkEntities() {
/**
* Add inventory items to a block entity (e.g. a chest)
*/
public void addInventory(InventoryWindow window) {
public void addInventory(InventoryWindow window, boolean sendMessages) {
CompoundTag blockEntity = (CompoundTag) blockEntities.get(window.getContainerLocation());

// if a block entity is missing, try to generate it first. If there's no block there we don't save anything.
if (blockEntity == null) {
BlockState bs = getBlockStateAt(window.getContainerLocation().withinChunk());
if (bs == null) {
sendInventoryFailureMessage(window);
if (sendMessages) {
sendInventoryFailureMessage(window);
}
return;
}
blockEntity = generateBlockEntity(bs.getName(), window.getContainerLocation());
Expand All @@ -68,7 +70,10 @@ public void addInventory(InventoryWindow window) {
}

WorldManager.getInstance().touchChunk(this);
sendInventoryMessage(window);

if (sendMessages) {
sendInventoryMessage(window);
}
}

private void sendInventoryFailureMessage(InventoryWindow window) {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/game/data/chunk/ChunkFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ private boolean readChunkDataPacket(UnparsedChunk parser) {
*/
private static Chunk getVersionedChunk(CoordinateDim2D chunkPos) {
return Config.versionReporter().select(Chunk.class,
Option.of(Version.V1_19, () -> new Chunk_1_19(chunkPos)),
Option.of(Version.V1_18, () -> new Chunk_1_18(chunkPos)),
Option.of(Version.V1_17, () -> new Chunk_1_17(chunkPos)),
Option.of(Version.V1_16, () -> new Chunk_1_16(chunkPos)),
Expand All @@ -158,6 +159,7 @@ private static Chunk getVersionedChunk(CoordinateDim2D chunkPos) {
*/
private static Chunk getVersionedChunk(int dataVersion, CoordinateDim2D chunkPos) {
return VersionReporter.select(dataVersion, Chunk.class,
Option.of(Version.V1_19, () -> new Chunk_1_19(chunkPos)),
Option.of(Version.V1_18, () -> new Chunk_1_18(chunkPos)),
Option.of(Version.V1_17, () -> new Chunk_1_17(chunkPos)),
Option.of(Version.V1_16, () -> new Chunk_1_16(chunkPos)),
Expand All @@ -166,7 +168,6 @@ private static Chunk getVersionedChunk(int dataVersion, CoordinateDim2D chunkPos
Option.of(Version.V1_13, () -> new Chunk_1_13(chunkPos)),
Option.of(Version.V1_12, () -> new Chunk_1_12(chunkPos))
);

}

public Chunk fromNbt(NamedTag tag, CoordinateDim2D location) {
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/game/data/chunk/version/ChunkSection_1_19.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package game.data.chunk.version;

import config.Version;
import game.data.chunk.Chunk;
import game.data.chunk.palette.Palette;
import se.llbit.nbt.Tag;

public class ChunkSection_1_19 extends ChunkSection_1_18 {
public static final Version VERSION = Version.V1_19;

@Override
public int getDataVersion() {
return VERSION.dataVersion;
}

public ChunkSection_1_19(byte y, Palette palette, Chunk chunk) {
super(y, palette, chunk);
}

public ChunkSection_1_19(int sectionY, Tag nbt) {
super(sectionY, nbt);
}
}
28 changes: 28 additions & 0 deletions src/main/java/game/data/chunk/version/Chunk_1_19.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package game.data.chunk.version;

import config.Version;
import game.data.chunk.ChunkSection;
import game.data.chunk.palette.Palette;
import game.data.coordinates.CoordinateDim2D;
import se.llbit.nbt.SpecificTag;

public class Chunk_1_19 extends Chunk_1_18 {
public static final Version VERSION = Version.V1_19;

@Override
public int getDataVersion() { return VERSION.dataVersion; }

public Chunk_1_19(CoordinateDim2D location) {
super(location);
}

@Override
public ChunkSection createNewChunkSection(byte y, Palette palette) {
return new ChunkSection_1_19(y, palette, this);
}

@Override
protected ChunkSection parseSection(int sectionY, SpecificTag section) {
return new ChunkSection_1_19(sectionY, section);
}
}
4 changes: 2 additions & 2 deletions src/main/java/game/data/container/ContainerManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private void closeWindow(InventoryWindow window) {
} else if (window.getSlotList().size() == 54 && !block.hasProperty("type") && block.isChest()) {
handleChest1_12(block, window);
} else {
c.addInventory(window);
c.addInventory(window, true);
storedWindows.put(window.containerLocation.addDimension3D(WorldManager.getInstance().getDimension()), window);
}
}
Expand Down Expand Up @@ -176,7 +176,7 @@ public void items(int windowId, int count, DataTypeProvider provider) {

public void loadPreviousInventoriesAt(ChunkEntities c, CoordinateDim3D location) {
if (storedWindows.containsKey(location)) {
c.addInventory(storedWindows.get(location));
c.addInventory(storedWindows.get(location), false);
}

}
Expand Down
29 changes: 24 additions & 5 deletions src/main/java/game/data/dimension/Dimension.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package game.data.dimension;

import static util.ExceptionHandling.attempt;

import com.google.gson.Gson;
import config.Config;
import game.data.WorldManager;
Expand Down Expand Up @@ -129,11 +131,7 @@ public void registerType(SpecificTag dimensionNbt) {
this.type = type.getName();

// re-write since we write the dimension information on join otherwise
try {
write(PathUtils.toPath(Config.getWorldOutputDir(), "datapacks", "downloaded", "data"));
} catch (IOException e) {
e.printStackTrace();
}
attempt(() -> write(PathUtils.toPath(Config.getWorldOutputDir(), "datapacks", "downloaded", "data")));
}
}

Expand Down Expand Up @@ -163,6 +161,27 @@ public String toString() {
public String getName() {
return this.toString();
}

/**
* 1.19+ gets the dimension type as a string (this actually makes sense unlike the previous
* implementation).
*/
public void setType(String dimensionType) {
DimensionType type =
WorldManager.getInstance().getDimensionCodec().getDimensionType(dimensionType);

if (type == null) {
return;
}
this.type = type.getName();

int minY = type.getProperties().get("min_y").intValue();
int height = type.getProperties().get("height").intValue();
Chunk_1_17.setWorldHeight(minY, height);

// re-write since we write the dimension information on join otherwise
attempt(() -> write(PathUtils.toPath(Config.getWorldOutputDir(), "datapacks", "downloaded", "data")));
}
}

/**
Expand Down
27 changes: 14 additions & 13 deletions src/main/java/game/data/dimension/DimensionCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
Expand Down Expand Up @@ -52,11 +51,13 @@ public class DimensionCodec {


private final Map<String, Dimension> dimensions;
private final Map<Integer, DimensionType> dimensionTypes;
private final Map<Integer, DimensionType> dimensionTypesByHash;
private final Map<String, DimensionType> dimensionTypesByName;
private final Map<String, Biome> biomes;
private DimensionCodec() {
this.dimensions = new HashMap<>();
this.dimensionTypes = new HashMap<>();
this.dimensionTypesByHash = new HashMap<>();
this.dimensionTypesByName = new HashMap<>();
this.biomes = new HashMap<>();
}

Expand Down Expand Up @@ -96,14 +97,10 @@ private void readDimensionTypes(ListTag dimensionList) {
String[] parts = identifier.split(":");
String namespace = parts[0];
String name = parts[1];

// skip Minecraft ones as the client can make these itself
if (namespace.equals("minecraft")) {
continue;
}


DimensionType type = new DimensionType(namespace, name, d);
this.dimensionTypes.put(type.getSignature(), type);
this.dimensionTypesByHash.put(type.getSignature(), type);
this.dimensionTypesByName.put(type.getName(), type);
}
}

Expand Down Expand Up @@ -135,14 +132,18 @@ public Dimension getDimension(String name) {
* Get a dimension by it's signature. The signature is just the hash of the properties.
*/
public DimensionType getDimensionType(int signature) {
return dimensionTypes.get(signature);
return dimensionTypesByHash.get(signature);
}

public DimensionType getDimensionType(String name) {
return dimensionTypesByName.get(name);
}

/**
* Write all the custom dimension data, if there is any.
*/
public boolean write(Path destination) throws IOException {
if (biomes.isEmpty() && dimensionTypes.isEmpty()) {
if (biomes.isEmpty() && dimensionTypesByHash.isEmpty()) {
// nothing to write
return false;
}
Expand All @@ -151,7 +152,7 @@ public boolean write(Path destination) throws IOException {
d.write(destination);
}

for (DimensionType d : dimensionTypes.values()) {
for (DimensionType d : dimensionTypesByHash.values()) {
d.write(destination);
}

Expand Down
4 changes: 3 additions & 1 deletion src/main/java/game/data/dimension/DimensionType.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public class DimensionType {
private final String name;
private final int index;
private final int signature;

private CompoundTag properties;

DimensionType(String namespace, String name, CompoundTag tag) {
Expand All @@ -29,7 +28,10 @@ public class DimensionType {
this.namespace = namespace;
this.name = name;
this.signature = this.properties.hashCode();
}

public CompoundTag getProperties() {
return properties;
}

/**
Expand Down
6 changes: 1 addition & 5 deletions src/main/java/game/data/entity/EntityRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public void updatePositionAbsolute(DataTypeProvider provider) {
}));
}

private IMovableEntity getMovableEntity(int entId) {
public IMovableEntity getMovableEntity(int entId) {
IMovableEntity ent = players.get(entId);
if (ent != null) {
return ent;
Expand All @@ -146,10 +146,6 @@ private IMovableEntity getMovableEntity(int entId) {
return entities.get(entId);
}

public Entity getEntity(int entityId) {
return (Entity) getMovableEntity(entityId);
}

public List<SpecificTag> getEntitiesNbt(CoordinateDim2D location) {
Set<Entity> entities = perChunk.get(location);

Expand Down
9 changes: 8 additions & 1 deletion src/main/java/game/data/entity/ObjectEntity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package game.data.entity;

import config.Config;
import packets.DataTypeProvider;
import se.llbit.nbt.CompoundTag;

Expand All @@ -20,7 +21,13 @@ public static Entity parse(DataTypeProvider provider) {
ent.readPosition(provider);
ent.pitch = provider.readNext();
ent.yaw = provider.readNext();
int data = provider.readInt();
int data;
if (Config.versionReporter().isAtLeast1_19()) {
provider.readNext(); // head rotation
data = provider.readVarInt();
} else {
data = provider.readInt();
}
parseVelocity(provider);

// only if it's an ObjectEntity do we actually set the data bit
Expand Down
Loading

0 comments on commit 1b40f80

Please sign in to comment.