Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 3 additions & 5 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ assignees: AxalotLDev, FurryMileon
### 🐛 Describe the bug
A clear and concise description of what the bug is.

### 🔁 Reproducibility
- [ ] This bug is not consistently reproducible

### 📋 Steps to reproduce *(skip if checked above)*
### 📋 Steps to reproduce*
1.
2.
3.
Expand All @@ -26,9 +23,10 @@ What actually happened?

### 🖥️ Environment
- 🔧 Async version:
- 🎮 Minecraft enviroment (Client or Server):
- 🎮 Minecraft version:
- ⚙️ Modloader & version:
- 📦 Other mods installed (if relevant):
- 📦 Other mods installed:

### 📜 Logs
Please attach your `latest.log` or crash report if available.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Fixed incompatibility with VMP
- Fixed an error receiving a remote entity's packet
- Config fixes (JordanOlivet)
21 changes: 6 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
<div align="center">

# Async - Minecraft Entity Multi-Threading Mod ⚙️

[![Modrinth Downloads](https://img.shields.io/modrinth/dt/async?style=for-the-badge&logo=modrinth)](https://modrinth.com/mod/async)
[![Discord](https://img.shields.io/discord/YOUR_DISCORD_ID?style=for-the-badge&logo=discord&label=Discord)](https://discord.com/invite/scvCQ2qKS3)
[![GitHub Issues](https://img.shields.io/github/issues/AxalotLDev/Async?style=for-the-badge)](https://github.com/AxalotLDev/Async/issues)
</div>



**Async** is a Fabric mod designed to improve entity performance by processing them in parallel using multiple CPU cores and threads.


## Important❗
**Async** is currently in alpha testing and is experimental. Its use may lead to incorrect entity behavior and crashes.


## What is Async? 🤔
Async is a Fabric mod that enhances the performance of entity processing. The mod leverages multithreading, which allows multiple CPU cores to improve performance when handling a large number of entities.

### 💡 Key Benefits:
- ⚡ **Improved TPS**: Maintains stable tick times even with a large number of entities.
Expand All @@ -42,7 +32,7 @@ Concurrent Chunk Management Engine, Fabric API, FerriteCore, Lithium, ScalableLu
</details>

## ⚠️ Incompatible Mods
- ❌ Moonrise - Known incompatibility
- ❌ Moonrise - Known incompatibility
- ⚠️ ...and there may be conflicts with other mods.

*If you encounter issues with other mods, please report them on our [GitHub](https://github.com/AxalotLDev/Async/issues) or [Discord](https://discord.com/invite/scvCQ2qKS3).*
Expand All @@ -55,7 +45,8 @@ Concurrent Chunk Management Engine, Fabric API, FerriteCore, Lithium, ScalableLu
- `/async config synchronizedEntities remove` — Removes selected entity from synchronized processing.
- `/async stats` — Displays the number of threads in use.
- `/async stats entity` — Shows the number of entities processed by Async in various worlds.
- `/async stats entity [number]` — Shows the top [number] entity types by count in descending order. For example, `/async stats entity 10` displays the top 10 most numerous entity types.
- `/async stats entity [number]` — Shows the top [number] entity types by count in descending order. For example, `/async stats entity 10` displays the top 10 most numerous entity types.
- `/async stats entity [number] [ticks]` displays the top [number] most numerous entity types with their average mspt usage per [ticks].

## 📥 Download
The mod is available on [Modrinth](https://modrinth.com/mod/async)
Expand All @@ -71,4 +62,4 @@ You can also chat with us on Discord:
[![Chat with us on Discord](https://img.shields.io/badge/Chat%20with%20us%20on-Discord-blue)](https://discord.com/invite/scvCQ2qKS3)

## 🙌 Acknowledgements
This mod is based on code from [MCMTFabric](https://modrinth.com/mod/mcmtfabric), which in turn was based on [JMT-MCMT](https://github.com/jediminer543/JMT-MCMT). Huge thanks to Grider and jediminer543 for their invaluable contributions!
This mod is based on code from [MCMTFabric](https://modrinth.com/mod/mcmtfabric), which in turn was based on [JMT-MCMT](https://github.com/jediminer543/JMT-MCMT). Huge thanks to Grider and jediminer543 for their invaluable contributions!
96 changes: 96 additions & 0 deletions api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
plugins {
id 'java'
id 'maven-publish'
id 'com.gradleup.nmcp' version '1.4.4'
id 'signing'
id 'idea'
id 'fabric-loom'
}

group = 'io.github.axalotldev'
version = "1.0.4"

base {
archivesName = "${mod_id}-${project.name}"
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(project.java_version)
}

withSourcesJar()
withJavadocJar()
}

repositories {
mavenCentral()
maven { url = "https://maven.parchmentmc.org/" }
maven { url = "https://maven.fabricmc.net/" }
maven { url = "https://libraries.minecraft.net/" }
maven { url = "https://maven.neoforged.net/releases/" }
}

dependencies {
minecraft("com.mojang:minecraft:${minecraft_version}")
mappings loom.layered {
officialMojangMappings()
if (project.hasProperty('parchment_minecraft_version') && project.hasProperty('parchment_mappings_version')) {
def mcVer = project.parchment_minecraft_version
def mapVer = project.parchment_mappings_version

if (mcVer != null && mapVer != null && !mcVer.isBlank() && !mapVer.isBlank()) {
parchment("org.parchmentmc.data:parchment-${mcVer}:${mapVer}@zip")
}
}
}
compileOnly("net.fabricmc:fabric-loader:$fabric_loader_version")
compileOnly "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
compileOnly(annotationProcessor'org.projectlombok:lombok:1.18.44')
}

publishing {
publications {
create("mavenJava", MavenPublication) {
groupId = group
artifactId = "${mod_id}-${project.name}"
version = version
from components.java
pom {
name = mod_id
description = "Async API"
url = "https://github.com/axalotldev/${mod_id}"
licenses {
license {
name = "MIT License"
url = "https://opensource.org/license/mit/"
}
}
developers {
developer {
id = "axalotldev"
name = "AxalotlDev"
}
}
scm {
connection = "scm:git:git://github.com/axalotldev/${mod_id}.git"
developerConnection = "scm:git:ssh://github.com/axalotldev/${mod_id}.git"
url = "https://github.com/axalotldev/${mod_id}"
}
}
}
}
}

nmcp {
publishAllPublicationsToCentralPortal {
username = findProperty("mavenCentralUsername")
password = findProperty("mavenCentralPassword")
publishingType = "USER_MANAGED"
}
}

signing {
useGpgCmd()
sign publishing.publications.mavenJava
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package com.axalotl.async.api.fastutil;

import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.fastutil.longs.*;
import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;

/**
* Thread-safe implementation of LongLinkedOpenHashSet using ConcurrentSkipListSet as backing storage.
* This implementation provides concurrent access and maintains elements in sorted order.
*
* <p>
* A type-specific linked hash set with a fast, small-footprint implementation.
*
* <p>
* Instances of this class use a hash table to represent a set. The table is filled up to a
* specified <em>load factor</em>, and then doubled in size to accommodate new entries. If the table
* is emptied below <em>one fourth</em> of the load factor, it is halved in size; however, the table
* is never reduced to a size smaller than that at creation time: this approach makes it possible to
* create sets with a large capacity in which insertions and deletions do not cause immediately
* rehashing. Moreover, halving is not performed when deleting entries from an iterator, as it would
* interfere with the iteration process.
*
* <p>
* Note that {@link #clear()} does not modify the hash table size. Rather, a family of
* {@linkplain #trim() trimming methods} lets you control the size of the table; this is
* particularly useful if you reuse instances of this class.
*
* <p>
* Iterators generated by this set will enumerate elements in the same order in which they have been
* added to the set (addition of elements already present in the set does not change the iteration
* order). Note that this order has nothing in common with the natural order of the keys. The order
* is kept by means of a doubly linked list, represented <i>via</i> an array of longs parallel to
* the table.
*
* <p>
* This class implements the interface of a sorted set, so to allow easy access of the iteration
* order: for instance, you can get the first element in iteration order with {@code first()}
* without having to create an iterator; however, this class partially violates the
* {@link java.util.SortedSet} contract because all subset methods throw an exception and
* {@link #comparator()} returns always {@code null}.
*
* <p>
* Additional methods, such as {@code addAndMoveToFirst()}, make it easy to use instances of this
* class as a cache (e.g., with LRU policy).
*
* <p>
* The iterators provided by this class are type-specific {@linkplain java.util.ListIterator list
* iterators}, and can be started at any element <em>which is in the set</em> (if the provided
* element is not in the set, a {@link NoSuchElementException} exception will be thrown). If,
* however, the provided element is not the first or last element in the set, the first access to
* the list index will require linear time, as in the worst case the entire set must be scanned in
* iteration order to retrieve the positional index of the starting element. If you use just the
* methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}, however, all
* operations will be performed in constant time.
*
* @see Hash
* @see HashCommon
*/
public class ConcurrentLongLinkedOpenHashSet extends LongLinkedOpenHashSet {

/**
* Thread-safe sorted backing set used for storing Long values.
* Delegates concurrency and ordering to ConcurrentSkipListSet.
*/
private final ConcurrentSkipListSet<Long> backing = new ConcurrentSkipListSet<>();

public ConcurrentLongLinkedOpenHashSet() {
}

@Override
public boolean add(final long k) {
return backing.add(k);
}

@Override
public boolean addAll(Collection<? extends Long> c) {
Objects.requireNonNull(c, "Collection cannot be null");
return backing.addAll(c);
}

@Override
public boolean contains(final long k) {
return backing.contains(k);
}

@Override
public boolean remove(final long k) {
return backing.remove(k);
}

@Override
public void clear() {
backing.clear();
}

@Override
public boolean isEmpty() {
return backing.isEmpty();
}

@Override
public int size() {
return backing.size();
}

/**
* Returns the first element of this set in iteration order.
*
* @return the first element in iteration order.
*/
@Override
public long firstLong() {
return Optional.ofNullable(backing.first())
.orElseThrow(() -> new NoSuchElementException("Set is empty"));
}

/**
* Returns the last element of this set in iteration order.
*
* @return the last element in iteration order.
*/
@Override
public long lastLong() {
return Optional.ofNullable(backing.last())
.orElseThrow(() -> new NoSuchElementException("Set is empty"));
}

/**
* Removes the first key in iteration order.
*
* @return the first key.
*/
@Override
public long removeFirstLong() {
long first = firstLong();
backing.remove(first);
return first;
}

/**
* Removes the last key in iteration order.
*
* @return the last key.
*/
@Override
public long removeLastLong() {
long last = lastLong();
backing.remove(last);
return last;
}

@Override
public @NotNull LongListIterator iterator() {
return FastUtilHackUtil.wrap(backing.iterator());
}

@Override
public boolean equals(Object obj) {
return this == obj || (obj instanceof ConcurrentLongLinkedOpenHashSet other && backing.equals(other.backing));
}

@Override
public int hashCode() {
return backing.hashCode();
}

@Override
public String toString() {
return backing.toString();
}
}
Loading
Loading