Author SHA1 Message Date
ppc 4092a2e373 remove padding hack for android 2026-02-08 15:47:05 +00:00
ppc 56f6ad649b attempt to fix android safe area inserts 2026-02-08 15:30:38 +00:00
ppc 17603da953 remove physical card scanning (enables sideloading) 2026-01-30 22:16:58 +00:00
8 changed files with 26 additions and 34 deletions
+1 -1
View File
@@ -74,7 +74,7 @@ export default function CardManager({navigation}) {
return ( return (
<FlatList contentInsetAdjustmentBehavior="always" <FlatList contentInsetAdjustmentBehavior="always"
style={{padding: 16, paddingTop: 24}} style={{padding: 16}}
data={cards} data={cards}
keyExtractor={i => i._id.toString()} keyExtractor={i => i._id.toString()}
contentContainerStyle={{paddingBottom: 120}} contentContainerStyle={{paddingBottom: 120}}
+10 -7
View File
@@ -1,7 +1,8 @@
import {BSON} from "realm"; import {BSON} from "realm";
import {ActivityIndicator, Button, Text, useTheme} from "react-native-paper"; import {ActivityIndicator, Button, Text, useTheme} from "react-native-paper";
import React, {useCallback, useEffect, useLayoutEffect, useMemo, useState} from "react"; import React, {useCallback, useEffect, useLayoutEffect, useMemo, useState} from "react";
import {Alert, Platform, RefreshControl, ScrollView, Share, StyleSheet, View} from "react-native"; import {Alert, Platform, RefreshControl, ScrollView, Share, View} from "react-native";
import {useSafeAreaInsets} from "react-native-safe-area-context";
import { import {
CircleCheck, CircleCheck,
CircleDot, CircleDot,
@@ -41,7 +42,8 @@ const {useRealm, useQuery, useObject} = RealmContext;
export default function ServerCardIn({route, navigation}) { export default function ServerCardIn({route, navigation}) {
const realm = useRealm(); const realm = useRealm();
const theme = useTheme() const theme = useTheme();
const insets = useSafeAreaInsets();
const {serverId} = route.params; const {serverId} = route.params;
const server = useObject(AMServer, ObjectId.createFromHexString(serverId)); const server = useObject(AMServer, ObjectId.createFromHexString(serverId));
@@ -216,7 +218,8 @@ export default function ServerCardIn({route, navigation}) {
} }
return ( return (
<ScrollView contentInsetAdjustmentBehavior="automatic" refreshControl={<RefreshControl refreshing={serverRefreshing} onRefresh={performRefresh}/>}> <ScrollView contentInsetAdjustmentBehavior="always"
refreshControl={<RefreshControl refreshing={serverRefreshing} onRefresh={performRefresh}/>}>
<View style={styles.container}> <View style={styles.container}>
<StatusAlert server={server} connectionEstablished={serverConnectionSuccess}/> <StatusAlert server={server} connectionEstablished={serverConnectionSuccess}/>
<View style={styles.section}> <View style={styles.section}>
@@ -344,21 +347,21 @@ const menuActions: MenuAction[] = [
} }
]; ];
const styles = StyleSheet.create({ const styles = {
section: { section: {
gap: 10 gap: 10
}, },
sectionTitle: { sectionTitle: {
fontWeight: "bold" fontWeight: "bold" as const
}, },
emptyPlaceholderView: { emptyPlaceholderView: {
marginVertical: 30, marginVertical: 30,
gap: 15 gap: 15
}, },
container: { container: {
paddingTop: Platform.select({android: 120, default: 0}), paddingTop: Platform.select({android: 18, default: 0}),
paddingHorizontal: 16, paddingHorizontal: 16,
paddingBottom: 80, paddingBottom: 80,
gap: 20 gap: 20
} }
}); };
+1 -1
View File
@@ -91,7 +91,7 @@ export default function ServerManager({navigation}) {
<FlatList contentInsetAdjustmentBehavior="always" <FlatList contentInsetAdjustmentBehavior="always"
data={servers} data={servers}
keyExtractor={i => i._id.toString()} keyExtractor={i => i._id.toString()}
style={{padding: 16, paddingTop: 24}} style={{padding: 16}}
contentContainerStyle={{paddingBottom: 80}} contentContainerStyle={{paddingBottom: 80}}
renderItem={i => <ServerCard navigation={navigation} server={i.item}/>} renderItem={i => <ServerCard navigation={navigation} server={i.item}/>}
ItemSeparatorComponent={() => <View style={{height: 15}}/>} ItemSeparatorComponent={() => <View style={{height: 15}}/>}
+1 -1
View File
@@ -33,7 +33,7 @@ export default function ServerManagerStack({navigation}) {
headerRight: () => Platform.OS === 'android' ? null : <TouchableOpacity onPress={() => navigation.navigate('add-server')}><Plus color={theme.colors.primary}/></TouchableOpacity> headerRight: () => Platform.OS === 'android' ? null : <TouchableOpacity onPress={() => navigation.navigate('add-server')}><Plus color={theme.colors.primary}/></TouchableOpacity>
}}/> }}/>
<Stack.Screen name="server" options={{title: "Server", headerTransparent: true}} component={ServerCardIn}/> <Stack.Screen name="server" options={{title: "Server", headerTransparent: Platform.select({default: false, ios: true})}} component={ServerCardIn}/>
</Stack.Group> </Stack.Group>
</Stack.Navigator> </Stack.Navigator>
); );
+4 -1
View File
@@ -84,4 +84,7 @@ function MethodCard(props: {
) )
} }
export default CardAddModal; export default Platform.select({
default: ManualCardEntry,
ios: CardAddModal
});
+3 -6
View File
@@ -96,13 +96,10 @@ impl Config {
.map(|v| v > 0) .map(|v| v > 0)
.unwrap_or(defaults::AIME_KEYBOARD_ENABLED); .unwrap_or(defaults::AIME_KEYBOARD_ENABLED);
let aime_txt_path_raw = aime_section let aime_txt_path = aime_section
.and_then(|s| s.get("aimePath")) .and_then(|s| s.get("aimePath"))
.unwrap_or(defaults::AIME_FILE); .unwrap_or(defaults::AIME_FILE)
.into();
// Normalize backslashes to forward slashes to avoid escape issues
let aime_txt_path_str = aime_txt_path_raw.replace("\\", "/");
let aime_txt_path = PathBuf::from(aime_txt_path_str);
let server_listen_address = io_section.get("listenAddress") let server_listen_address = io_section.get("listenAddress")
.unwrap_or(defaults::SERVER_ADDRESS) .unwrap_or(defaults::SERVER_ADDRESS)
+2 -2
View File
@@ -1,6 +1,6 @@
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use axum::http::{Method, StatusCode, header}; use axum::http::{StatusCode, header};
use axum::response::{IntoResponse, Response}; use axum::response::{IntoResponse, Response};
use axum::routing::{get, post}; use axum::routing::{get, post};
use axum::{Json, Router}; use axum::{Json, Router};
@@ -16,7 +16,7 @@ use crate::webapi::API_VERSION;
pub fn build_server() -> Router { pub fn build_server() -> Router {
let services = ServiceBuilder::new() let services = ServiceBuilder::new()
.layer(TraceLayer::new_for_http()) .layer(TraceLayer::new_for_http())
.layer(CorsLayer::new().allow_origin(Any).allow_headers(Any).allow_methods([Method::GET, Method::POST]).max_age(Duration::from_secs(600))); .layer(CorsLayer::new().allow_origin(Any).allow_methods(Any));
Router::<()>::new() Router::<()>::new()
.route("/amnet/info", get(server_state_handler)) .route("/amnet/info", get(server_state_handler))
+4 -15
View File
@@ -1,7 +1,7 @@
<div align="center"> <div align="center">
# AMNet # AMNet
[Latest .ipa](https://amnet-dist.ppc.moe/amnet-1.3.9.ipa) • [Firebase](https://appdistribution.firebase.dev/i/6acc3151357deaa8) • [Website](http://card.ppc.moe) • [Server DLLs](https://gitea.tendokyu.moe/ppc/amnet/releases) [Firebase](https://appdistribution.firebase.dev/i/6acc3151357deaa8) • [Website](http://card.ppc.moe) • [Server DLLs](https://gitea.tendokyu.moe/ppc/amnet/releases)
An Amusement IC Card Switcher for segatools-based games. An Amusement IC Card Switcher for segatools-based games.
@@ -13,6 +13,7 @@ This was originally intended for use with maimai and CHUNITHM, but should be com
> [!WARNING] > [!WARNING]
> TestFlight is no longer available and must be sideloaded using AltStore or similar tooling for the forseeable future. > TestFlight is no longer available and must be sideloaded using AltStore or similar tooling for the forseeable future.
> See issue #1 for more details.
## Setup ## Setup
1. Download the latest `amnet.dll` from the releases page 1. Download the latest `amnet.dll` from the releases page
@@ -39,18 +40,6 @@ This was originally intended for use with maimai and CHUNITHM, but should be com
4. Launch the game, and check the amdaemon console for server startup messages 4. Launch the game, and check the amdaemon console for server startup messages
5. Access the using one of the interfaces (see below), add a new server `http://<your-ip-address>:6070`, import your existing card (or create a new one) and start playing! 5. Access the using one of the interfaces (see below), add a new server `http://<your-ip-address>:6070`, import your existing card (or create a new one) and start playing!
### Physical Cards
AMNet 1.3 adds support for scanning physical cards on iOS devices. If you own a physical Aime/Banapass/NESiCA/e-Amusement card, you can scan it using the app and use it in-game.
By changing the `useAimeDBForPhysicalCards` in segatools.ini, you can choose how the card is read on a per-game basis:
- `0` will send the 20-digit access code on the back of the card to the game and load the save data directly (default option).
- `1` - Send the card's IDm to the game and use AiMeDB to retrieve the 20-digit code assigned to the card.
Mode `1` makes the app function in the same way to a real card reader and should be used if you want the same access code to show when scanning the card on a cab.
You should also use this option if you're connecting to a hosted server (AquaNet/rinnet/etc).
Additionally, if `useAimeDBForPhysicalCards` is set to `1` and the game is failing to read the card, make sure an up-to-date version of segatools is being used.
## Interfaces ## Interfaces
AMNet can be used on most platforms, see below for options available for each platform: AMNet can be used on most platforms, see below for options available for each platform:
@@ -63,8 +52,8 @@ AMNet can be used on most platforms, see below for options available for each pl
</tr> </tr>
<tr> <tr>
<td>iOS</td> <td>iOS</td>
<td><a href="https://amnet-dist.ppc.moe/amnet-1.3.9.ipa" target="_blank">.ipa</a></td> <td><a href="https://amnet-dist.ppc.moe/amnet-1.3.2.ipa" target="_blank">.ipa download</a></td>
<td>*TestFlight has been shut down and won't be back for the forseeable future, sideload using AltStore or similar tooling</td> <td>*TestFlight is no longer available, sideload using AltStore or similar tooling</td>
</tr> </tr>
<tr> <tr>
<td rowspan="2">Android</td> <td rowspan="2">Android</td>