Skip to content

Commit

Permalink
Add buttons to CommentToolScreen
Browse files Browse the repository at this point in the history
  • Loading branch information
zbx1425 committed Jul 21, 2023
1 parent 8cf159e commit 6d6ce0a
Show file tree
Hide file tree
Showing 9 changed files with 437 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@
import java.nio.ByteBuffer;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.UUID;

public class CommentEntry {

public int id;
public long id;
public long timestamp;
public boolean deleted;
public ResourceLocation dimension;
public ResourceLocation level;
public ChunkPos region;
public BlockPos location;
public UUID initiator;
Expand All @@ -27,10 +26,10 @@ public class CommentEntry {

public CommentEntry(CommentTable table, ResultSet result) throws SQLException {
int iota = 0;
id = result.getInt(++iota);
id = result.getLong(++iota);
timestamp = result.getLong(++iota);
deleted = result.getBoolean(++iota);
dimension = table.db.dimensions.getDimensionById(result.getInt(++iota));
level = table.db.dimensions.getDimensionById(result.getInt(++iota));
region = new ChunkPos(result.getLong(++iota));
location = new BlockPos(result.getInt(++iota), result.getInt(++iota), result.getInt(++iota));
initiator = uuidFromByteArray(result.getBytes(++iota));
Expand All @@ -45,7 +44,7 @@ private static UUID uuidFromByteArray(byte[] bytes) {
return new UUID(bb.getLong(), bb.getLong());
}

public void insertOrUpdate(CommentTable table) throws SQLException {
public void insertTo(CommentTable table) throws SQLException {
table.db.execute("""
INSERT OR REPLACE INTO comments (
id, timestamp, deleted, level, region, locationX, locationY, locationZ, initiator, initiatorName, messageType, message, imageUrl
Expand All @@ -54,14 +53,11 @@ INSERT OR REPLACE INTO comments (
);
""", params -> {
int iota = 0;
if (id == 0) {
params.setNull(++iota, Types.INTEGER);
} else {
params.setInt(++iota, id);
}
if (id == 0) id = Database.SNOWFLAKE.nextId();
params.setLong(++iota, id);
params.setLong(++iota, timestamp);
params.setBoolean(++iota, deleted);
params.setInt(++iota, table.db.dimensions.getDimensionId(dimension));
params.setInt(++iota, table.db.dimensions.getDimensionId(level));
params.setLong(++iota, region.toLong());
params.setInt(++iota, location.getX());
params.setInt(++iota, location.getY());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package cn.zbx1425.worldcomment.data;

import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ChunkPos;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class CommentTable {

Expand All @@ -15,7 +20,7 @@ public CommentTable(Database db) {
public void init() throws SQLException {
db.execute("""
CREATE TABLE IF NOT EXISTS comments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY,
timestamp INTEGER,
deleted INTEGER,
level INTEGER,
Expand All @@ -39,13 +44,32 @@ CREATE INDEX IF NOT EXISTS timestampIndex ON comments (
""");
}

public void fetchMaxId() throws SQLException {
try (ResultSet result = db.executeQuery("SELECT id FROM comments ORDER BY id DESC LIMIT 1;")) {
if (!result.next()) {
maxId = 0;
} else {
maxId = result.getInt(1);
public List<CommentEntry> queryInRegion(ResourceLocation level, ChunkPos region) throws SQLException {
ArrayList<CommentEntry> entries = new ArrayList<>();
try (ResultSet result = db.executeQuery(
"SELECT * FROM comments WHERE level = ? AND region = ?", params -> {
params.setInt(1, db.dimensions.getDimensionId(level));
params.setLong(2, region.toLong());
}
)) {
while (result.next()) {
entries.add(new CommentEntry(this, result));
}
}
return entries;
}

public List<CommentEntry> queryInTime(long from) throws SQLException {
ArrayList<CommentEntry> entries = new ArrayList<>();
try (ResultSet result = db.executeQuery(
"SELECT * FROM comments WHERE timestamp > ?", params -> {
params.setLong(1, from);
}
)) {
while (result.next()) {
entries.add(new CommentEntry(this, result));
}
}
return entries;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ public class Database {

public static Database INSTANCE;

public static final Snowflake SNOWFLAKE = new Snowflake();

private final Connection dbConn;

public final CommentTable comments;

public final DimensionTable dimensions;

public Database(Path dbPath) throws SQLException {
Expand Down
133 changes: 133 additions & 0 deletions common/src/main/java/cn/zbx1425/worldcomment/data/Snowflake.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package cn.zbx1425.worldcomment.data;

import java.net.NetworkInterface;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.Enumeration;

/**
* Distributed Sequence Generator.
* Inspired by Twitter snowflake: https://github.com/twitter/snowflake/tree/snowflake-2010
*
* This class should be used as a Singleton.
* Make sure that you create and reuse a Single instance of Snowflake per node in your distributed system cluster.
*/
public class Snowflake {
private static final int UNUSED_BITS = 1; // Sign bit, Unused (always set to 0)
private static final int EPOCH_BITS = 41;
private static final int NODE_ID_BITS = 10;
private static final int SEQUENCE_BITS = 12;

private static final long maxNodeId = (1L << NODE_ID_BITS) - 1;
private static final long maxSequence = (1L << SEQUENCE_BITS) - 1;

// Custom Epoch (January 1, 2015 Midnight UTC = 2015-01-01T00:00:00Z)
private static final long DEFAULT_CUSTOM_EPOCH = 1420070400000L;

private final long nodeId;
private final long customEpoch;

private volatile long lastTimestamp = -1L;
private volatile long sequence = 0L;

// Create Snowflake with a nodeId and custom epoch
public Snowflake(long nodeId, long customEpoch) {
if(nodeId < 0 || nodeId > maxNodeId) {
throw new IllegalArgumentException(String.format("NodeId must be between %d and %d", 0, maxNodeId));
}
this.nodeId = nodeId;
this.customEpoch = customEpoch;
}

// Create Snowflake with a nodeId
public Snowflake(long nodeId) {
this(nodeId, DEFAULT_CUSTOM_EPOCH);
}

// Let Snowflake generate a nodeId
public Snowflake() {
this.nodeId = createNodeId();
this.customEpoch = DEFAULT_CUSTOM_EPOCH;
}

public synchronized long nextId() {
long currentTimestamp = timestamp();

if(currentTimestamp < lastTimestamp) {
throw new IllegalStateException("Invalid System Clock!");
}

if (currentTimestamp == lastTimestamp) {
sequence = (sequence + 1) & maxSequence;
if(sequence == 0) {
// Sequence Exhausted, wait till next millisecond.
currentTimestamp = waitNextMillis(currentTimestamp);
}
} else {
// reset sequence to start with zero for the next millisecond
sequence = 0;
}

lastTimestamp = currentTimestamp;

long id = currentTimestamp << (NODE_ID_BITS + SEQUENCE_BITS)
| (nodeId << SEQUENCE_BITS)
| sequence;

return id;
}


// Get current timestamp in milliseconds, adjust for the custom epoch.
private long timestamp() {
return Instant.now().toEpochMilli() - customEpoch;
}

// Block and wait till next millisecond
private long waitNextMillis(long currentTimestamp) {
while (currentTimestamp == lastTimestamp) {
currentTimestamp = timestamp();
}
return currentTimestamp;
}

private long createNodeId() {
long nodeId;
try {
StringBuilder sb = new StringBuilder();
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
byte[] mac = networkInterface.getHardwareAddress();
if (mac != null) {
for(byte macPort: mac) {
sb.append(String.format("%02X", macPort));
}
}
}
nodeId = sb.toString().hashCode();
} catch (Exception ex) {
nodeId = (new SecureRandom().nextInt());
}
nodeId = nodeId & maxNodeId;
return nodeId;
}

public long[] parse(long id) {
long maskNodeId = ((1L << NODE_ID_BITS) - 1) << SEQUENCE_BITS;
long maskSequence = (1L << SEQUENCE_BITS) - 1;

long timestamp = (id >> (NODE_ID_BITS + SEQUENCE_BITS)) + customEpoch;
long nodeId = (id & maskNodeId) >> SEQUENCE_BITS;
long sequence = id & maskSequence;

return new long[]{timestamp, nodeId, sequence};
}

@Override
public String toString() {
return "Snowflake Settings [EPOCH_BITS=" + EPOCH_BITS + ", NODE_ID_BITS=" + NODE_ID_BITS
+ ", SEQUENCE_BITS=" + SEQUENCE_BITS + ", CUSTOM_EPOCH=" + customEpoch
+ ", NodeId=" + nodeId + "]";
}
}
Loading

0 comments on commit 6d6ce0a

Please sign in to comment.